summaryrefslogtreecommitdiff
path: root/chromium/content/browser
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 15:28:34 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:54:51 +0000
commit2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch)
treeeb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/content/browser
parentb014812705fc80bff0a5c120dfcef88f349816dc (diff)
downloadqtwebengine-chromium-2a19c63448c84c1805fb1a585c3651318bb86ca7.tar.gz
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/content/browser')
-rw-r--r--chromium/content/browser/BUILD.gn165
-rw-r--r--chromium/content/browser/DEPS14
-rw-r--r--chromium/content/browser/OWNERS5
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_win.cc16
-rw-r--r--chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc8
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter.cc22
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm6
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc5
-rw-r--r--chromium/content/browser/accessibility/accessibility_ui.cc12
-rw-r--r--chromium/content/browser/accessibility/accessibility_win_browsertest.cc23
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc85
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h8
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc20
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm795
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.cc133
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.h39
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac.mm34
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm121
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc24
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h7
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm17
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc63
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc5
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc56
-rw-r--r--chromium/content/browser/accessibility/captioning_controller.cc2
-rw-r--r--chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc53
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc10
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc48
-rw-r--r--chromium/content/browser/accessibility/hit_testing_browsertest.cc224
-rw-r--r--chromium/content/browser/accessibility/line_layout_browsertest.cc97
-rw-r--r--chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc2
-rw-r--r--chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc10
-rw-r--r--chromium/content/browser/accessibility/web_contents_accessibility_android.cc4
-rw-r--r--chromium/content/browser/android/browser_startup_controller.cc36
-rw-r--r--chromium/content/browser/android/browser_startup_controller.h1
-rw-r--r--chromium/content/browser/android/content_feature_list.cc1
-rw-r--r--chromium/content/browser/android/content_startup_flags.cc8
-rw-r--r--chromium/content/browser/android/content_startup_flags.h3
-rw-r--r--chromium/content/browser/android/content_video_view.cc172
-rw-r--r--chromium/content/browser/android/content_video_view.h115
-rw-r--r--chromium/content/browser/android/content_view_core.cc153
-rw-r--r--chromium/content/browser/android/content_view_core.h74
-rw-r--r--chromium/content/browser/android/content_view_render_view.cc138
-rw-r--r--chromium/content/browser/android/content_view_render_view.h77
-rw-r--r--chromium/content/browser/android/dialog_overlay_impl.cc4
-rw-r--r--chromium/content/browser/android/gesture_listener_manager.cc54
-rw-r--r--chromium/content/browser/android/gesture_listener_manager.h1
-rw-r--r--chromium/content/browser/android/overscroll_controller_android.cc20
-rw-r--r--chromium/content/browser/android/overscroll_controller_android.h11
-rw-r--r--chromium/content/browser/android/selection/composited_touch_handle_drawable.cc95
-rw-r--r--chromium/content/browser/android/selection/composited_touch_handle_drawable.h16
-rw-r--r--chromium/content/browser/android/selection/selection_popup_controller.cc3
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.cc10
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.h1
-rw-r--r--chromium/content/browser/android/url_request_content_job.cc6
-rw-r--r--chromium/content/browser/android/url_request_content_job.h4
-rw-r--r--chromium/content/browser/android/web_contents_observer_proxy.cc7
-rw-r--r--chromium/content/browser/android/web_contents_observer_proxy.h1
-rw-r--r--chromium/content/browser/appcache/appcache_backend_impl.cc31
-rw-r--r--chromium/content/browser/appcache/appcache_backend_impl.h7
-rw-r--r--chromium/content/browser/appcache/appcache_database.cc78
-rw-r--r--chromium/content/browser/appcache/appcache_database.h4
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.cc6
-rw-r--r--chromium/content/browser/appcache/appcache_dispatcher_host.cc24
-rw-r--r--chromium/content/browser/appcache/appcache_host.cc17
-rw-r--r--chromium/content/browser/appcache/appcache_host.h4
-rw-r--r--chromium/content/browser/appcache/appcache_internals_ui.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_navigation_handle.cc14
-rw-r--r--chromium/content/browser/appcache/appcache_navigation_handle.h15
-rw-r--r--chromium/content/browser/appcache/appcache_navigation_handle_core.cc6
-rw-r--r--chromium/content/browser/appcache/appcache_navigation_handle_core.h2
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.cc6
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.h8
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler_unittest.cc35
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.h2
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl_unittest.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_subresource_url_factory.cc61
-rw-r--r--chromium/content/browser/appcache/appcache_subresource_url_factory.h23
-rw-r--r--chromium/content/browser/appcache/appcache_update_job_unittest.cc11
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_loader_request.cc9
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_loader_request.h4
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_job.cc5
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_job.h4
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_request.cc7
-rw-r--r--chromium/content/browser/appcache/chrome_appcache_service.cc22
-rw-r--r--chromium/content/browser/appcache/chrome_appcache_service.h16
-rw-r--r--chromium/content/browser/background_fetch/background_fetch.proto47
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.cc288
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.h122
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager.cc538
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager.h85
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h31
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc732
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc33
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h11
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc35
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc14
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h16
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc25
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h15
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc12
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller.cc9
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller.h8
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc92
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_request_info.cc13
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_request_info.h12
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler.cc31
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler.h8
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_impl.h1
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_unittest.cc187
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_base.cc31
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_base.h10
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_data_manager.cc76
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_data_manager.h51
-rw-r--r--chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc6
-rw-r--r--chromium/content/browser/background_fetch/mock_background_fetch_delegate.h2
-rw-r--r--chromium/content/browser/background_fetch/storage/README.md13
-rw-r--r--chromium/content/browser/background_fetch/storage/cleanup_task.cc23
-rw-r--r--chromium/content/browser/background_fetch/storage/cleanup_task.h11
-rw-r--r--chromium/content/browser/background_fetch/storage/create_metadata_task.cc131
-rw-r--r--chromium/content/browser/background_fetch/storage/create_metadata_task.h16
-rw-r--r--chromium/content/browser/background_fetch/storage/database_helpers.cc41
-rw-r--r--chromium/content/browser/background_fetch/storage/database_helpers.h4
-rw-r--r--chromium/content/browser/background_fetch/storage/database_task.cc60
-rw-r--r--chromium/content/browser/background_fetch/storage/database_task.h65
-rw-r--r--chromium/content/browser/background_fetch/storage/delete_registration_task.cc77
-rw-r--r--chromium/content/browser/background_fetch/storage/delete_registration_task.h25
-rw-r--r--chromium/content/browser/background_fetch/storage/get_developer_ids_task.cc25
-rw-r--r--chromium/content/browser/background_fetch/storage/get_developer_ids_task.h10
-rw-r--r--chromium/content/browser/background_fetch/storage/get_initialization_data_task.cc536
-rw-r--r--chromium/content/browser/background_fetch/storage/get_initialization_data_task.h100
-rw-r--r--chromium/content/browser/background_fetch/storage/get_metadata_task.cc47
-rw-r--r--chromium/content/browser/background_fetch/storage/get_metadata_task.h10
-rw-r--r--chromium/content/browser/background_fetch/storage/get_num_requests_task.cc88
-rw-r--r--chromium/content/browser/background_fetch/storage/get_num_requests_task.h53
-rw-r--r--chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc143
-rw-r--r--chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h40
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc34
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.h10
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc228
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_request_complete_task.h38
-rw-r--r--chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc45
-rw-r--r--chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h14
-rw-r--r--chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc24
-rw-r--r--chromium/content/browser/background_fetch/storage/update_registration_ui_task.h8
-rw-r--r--chromium/content/browser/background_sync/background_sync_browsertest.cc9
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.cc106
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.h20
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager_unittest.cc112
-rw-r--r--chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc20
-rw-r--r--chromium/content/browser/bad_message.h6
-rw-r--r--chromium/content/browser/battery_monitor_browsertest.cc9
-rw-r--r--chromium/content/browser/blob_storage/OWNERS2
-rw-r--r--chromium/content/browser/blob_storage/blob_internals_url_loader.cc2
-rw-r--r--chromium/content/browser/blob_storage/blob_url_browsertest.cc23
-rw-r--r--chromium/content/browser/blob_storage/blob_url_loader_factory.cc88
-rw-r--r--chromium/content/browser/blob_storage/blob_url_loader_factory.h88
-rw-r--r--chromium/content/browser/blob_storage/blob_url_unittest.cc36
-rw-r--r--chromium/content/browser/blob_storage/chrome_blob_storage_context.cc43
-rw-r--r--chromium/content/browser/blob_storage/chrome_blob_storage_context.h21
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc3
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h2
-rw-r--r--chromium/content/browser/bluetooth/tools/BUILD.gn1
-rw-r--r--chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc4
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.cc23
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.h12
-rw-r--r--chromium/content/browser/browser_context.cc89
-rw-r--r--chromium/content/browser/browser_main.cc8
-rw-r--r--chromium/content/browser/browser_main.h5
-rw-r--r--chromium/content/browser/browser_main_loop.cc249
-rw-r--r--chromium/content/browser/browser_main_loop.h42
-rw-r--r--chromium/content/browser/browser_main_loop_unittest.cc4
-rw-r--r--chromium/content/browser/browser_main_runner_impl.cc9
-rw-r--r--chromium/content/browser/browser_main_runner_impl.h7
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_embedder.cc8
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_embedder.h6
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc17
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.h18
-rw-r--r--chromium/content/browser/browser_process_sub_thread.cc9
-rw-r--r--chromium/content/browser/browser_side_navigation_browsertest.cc404
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl.cc4
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc17
-rw-r--r--chromium/content/browser/cache_storage/README.md13
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc3
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.cc85
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.h7
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc79
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.cc7
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.h3
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.cc9
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.h19
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc2
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_operation_unittest.cc2
-rw-r--r--chromium/content/browser/child_process_launcher.cc15
-rw-r--r--chromium/content/browser/child_process_launcher.h74
-rw-r--r--chromium/content/browser/child_process_launcher_helper.cc47
-rw-r--r--chromium/content/browser/child_process_launcher_helper.h51
-rw-r--r--chromium/content/browser/child_process_launcher_helper_android.cc79
-rw-r--r--chromium/content/browser/child_process_launcher_helper_fuchsia.cc30
-rw-r--r--chromium/content/browser/child_process_launcher_helper_linux.cc17
-rw-r--r--chromium/content/browser/child_process_launcher_helper_mac.cc16
-rw-r--r--chromium/content/browser/child_process_launcher_helper_posix.cc11
-rw-r--r--chromium/content/browser/child_process_launcher_helper_posix.h6
-rw-r--r--chromium/content/browser/child_process_launcher_helper_win.cc25
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc259
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.h25
-rw-r--r--chromium/content/browser/child_process_security_policy_unittest.cc210
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache.cc383
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache.h125
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache_unittest.cc293
-rw-r--r--chromium/content/browser/compositor/external_begin_frame_controller_client_impl.cc45
-rw-r--r--chromium/content/browser/compositor/external_begin_frame_controller_client_impl.h45
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc17
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h7
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.cc134
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.h7
-rw-r--r--chromium/content/browser/compositor/gpu_vsync_begin_frame_source.cc87
-rw-r--r--chromium/content/browser/compositor/gpu_vsync_begin_frame_source.h52
-rw-r--r--chromium/content/browser/compositor/gpu_vsync_begin_frame_source_unittest.cc190
-rw-r--r--chromium/content/browser/compositor/image_transport_factory.h4
-rw-r--r--chromium/content/browser/compositor/image_transport_factory_browsertest.cc63
-rw-r--r--chromium/content/browser/compositor/in_process_display_client.cc73
-rw-r--r--chromium/content/browser/compositor/in_process_display_client.h54
-rw-r--r--chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc1
-rw-r--r--chromium/content/browser/compositor/owned_mailbox.cc4
-rw-r--r--chromium/content/browser/compositor/owned_mailbox.h3
-rw-r--r--chromium/content/browser/compositor/reflector_impl_unittest.cc1
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.cc6
-rw-r--r--chromium/content/browser/compositor/viz_process_transport_factory.cc325
-rw-r--r--chromium/content/browser/compositor/viz_process_transport_factory.h66
-rw-r--r--chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc4
-rw-r--r--chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h1
-rw-r--r--chromium/content/browser/content_service_browsertest.cc59
-rw-r--r--chromium/content/browser/content_service_delegate_impl.cc90
-rw-r--r--chromium/content/browser/content_service_delegate_impl.h56
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_manager.cc21
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_manager.h4
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc106
-rw-r--r--chromium/content/browser/dedicated_worker/dedicated_worker_host.cc57
-rw-r--r--chromium/content/browser/device_sensors/device_sensor_browsertest.cc39
-rw-r--r--chromium/content/browser/devtools/README.md3
-rw-r--r--chromium/content/browser/devtools/browser_devtools_agent_host.cc53
-rw-r--r--chromium/content/browser/devtools/browser_devtools_agent_host.h15
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.cc69
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.h27
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler.cc5
-rw-r--r--chromium/content/browser/devtools/devtools_manager_unittest.cc43
-rw-r--r--chromium/content/browser/devtools/devtools_pipe_handler.cc11
-rw-r--r--chromium/content/browser/devtools/devtools_session.cc24
-rw-r--r--chromium/content/browser/devtools/devtools_session.h5
-rw-r--r--chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc69
-rw-r--r--chromium/content/browser/devtools/devtools_url_interceptor_request_job.h4
-rw-r--r--chromium/content/browser/devtools/devtools_url_loader_interceptor.cc42
-rw-r--r--chromium/content/browser/devtools/devtools_url_request_interceptor.cc4
-rw-r--r--chromium/content/browser/devtools/devtools_video_consumer.cc42
-rw-r--r--chromium/content/browser/devtools/devtools_video_consumer.h28
-rw-r--r--chromium/content/browser/devtools/devtools_video_consumer_unittest.cc32
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.cc22
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.h2
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc18
-rw-r--r--chromium/content/browser/devtools/protocol/emulation_handler.cc39
-rw-r--r--chromium/content/browser/devtools/protocol/emulation_handler.h16
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.cc43
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.cc231
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.h28
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.cc51
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.h9
-rw-r--r--chromium/content/browser/devtools/protocol/service_worker_handler.cc7
-rw-r--r--chromium/content/browser/devtools/protocol/system_info_handler.cc4
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.cc293
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.h16
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.cc99
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.h12
-rw-r--r--chromium/content/browser/devtools/protocol_config.json4
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.cc80
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.h15
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_agent_host.cc13
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_agent_host.h5
-rw-r--r--chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc13
-rw-r--r--chromium/content/browser/devtools/shared_worker_devtools_agent_host.h5
-rw-r--r--chromium/content/browser/devtools/target_registry.cc56
-rw-r--r--chromium/content/browser/devtools/target_registry.h44
-rw-r--r--chromium/content/browser/display_cutout/OWNERS3
-rw-r--r--chromium/content/browser/display_cutout/display_cutout_browsertest.cc468
-rw-r--r--chromium/content/browser/display_cutout/display_cutout_constants.h37
-rw-r--r--chromium/content/browser/display_cutout/display_cutout_host_impl.cc230
-rw-r--r--chromium/content/browser/display_cutout/display_cutout_host_impl.h100
-rw-r--r--chromium/content/browser/do_not_track_browsertest.cc193
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_area.cc2
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_browsertest.cc126
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc20
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.h8
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database_unittest.cc5
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.cc4
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.h3
-rw-r--r--chromium/content/browser/dom_storage/local_storage_context_mojo.cc195
-rw-r--r--chromium/content/browser/dom_storage/local_storage_context_mojo.h20
-rw-r--r--chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc389
-rw-r--r--chromium/content/browser/dom_storage/session_storage_area_impl.cc (renamed from chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.cc)109
-rw-r--r--chromium/content/browser/dom_storage/session_storage_area_impl.h (renamed from chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.h)61
-rw-r--r--chromium/content/browser/dom_storage/session_storage_area_impl_unittest.cc (renamed from chromium/content/browser/dom_storage/session_storage_leveldb_wrapper_unittest.cc)206
-rw-r--r--chromium/content/browser/dom_storage/session_storage_context_mojo.cc217
-rw-r--r--chromium/content/browser/dom_storage/session_storage_context_mojo.h51
-rw-r--r--chromium/content/browser/dom_storage/session_storage_context_mojo_unittest.cc568
-rw-r--r--chromium/content/browser/dom_storage/session_storage_data_map.cc31
-rw-r--r--chromium/content/browser/dom_storage/session_storage_data_map.h31
-rw-r--r--chromium/content/browser/dom_storage/session_storage_data_map_unittest.cc44
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.cc20
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database_unittest.cc20
-rw-r--r--chromium/content/browser/dom_storage/session_storage_metadata.cc3
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl.cc11
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl.h8
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc48
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h39
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc191
-rw-r--r--chromium/content/browser/dom_storage/storage_area_impl.cc (renamed from chromium/content/browser/leveldb_wrapper_impl.cc)251
-rw-r--r--chromium/content/browser/dom_storage/storage_area_impl.h (renamed from chromium/content/browser/leveldb_wrapper_impl.h)89
-rw-r--r--chromium/content/browser/dom_storage/storage_area_impl_unittest.cc (renamed from chromium/content/browser/leveldb_wrapper_impl_unittest.cc)587
-rw-r--r--chromium/content/browser/download/blob_download_url_loader_factory_getter.cc38
-rw-r--r--chromium/content/browser/download/blob_download_url_loader_factory_getter.h40
-rw-r--r--chromium/content/browser/download/download_browsertest.cc303
-rw-r--r--chromium/content/browser/download/download_manager_impl.cc201
-rw-r--r--chromium/content/browser/download/download_manager_impl.h37
-rw-r--r--chromium/content/browser/download/download_manager_impl_unittest.cc69
-rw-r--r--chromium/content/browser/download/download_request_core.cc26
-rw-r--r--chromium/content/browser/download/download_request_core.h4
-rw-r--r--chromium/content/browser/download/download_request_core_unittest.cc3
-rw-r--r--chromium/content/browser/download/download_resource_handler.cc60
-rw-r--r--chromium/content/browser/download/download_resource_handler.h12
-rw-r--r--chromium/content/browser/download/download_utils.cc4
-rw-r--r--chromium/content/browser/download/file_download_url_loader_factory_getter.cc44
-rw-r--r--chromium/content/browser/download/file_download_url_loader_factory_getter.h36
-rw-r--r--chromium/content/browser/download/mhtml_generation_browsertest.cc2
-rw-r--r--chromium/content/browser/download/save_package.cc7
-rw-r--r--chromium/content/browser/download/url_downloader.cc40
-rw-r--r--chromium/content/browser/download/url_downloader.h9
-rw-r--r--chromium/content/browser/download/url_downloader_factory.cc3
-rw-r--r--chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc33
-rw-r--r--chromium/content/browser/download/web_ui_download_url_loader_factory_getter.h40
-rw-r--r--chromium/content/browser/file_url_loader_factory.cc13
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper.cc6
-rw-r--r--chromium/content/browser/fileapi/file_system_url_loader_factory.cc13
-rw-r--r--chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc32
-rw-r--r--chromium/content/browser/find_request_manager_browsertest.cc9
-rw-r--r--chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc6
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.cc76
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.h9
-rw-r--r--chromium/content/browser/frame_host/frame_navigation_entry.h12
-rw-r--r--chromium/content/browser/frame_host/frame_tree.cc4
-rw-r--r--chromium/content/browser/frame_host/frame_tree.h1
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.cc32
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.h54
-rw-r--r--chromium/content/browser/frame_host/frame_tree_unittest.cc68
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc7
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_delegate.h9
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.cc799
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.h61
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc187
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc69
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.cc49
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.h36
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc23
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.cc14
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.h12
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc2
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc298
-rw-r--r--chromium/content/browser/frame_host/navigation_request.h63
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.cc11
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.h35
-rw-r--r--chromium/content/browser/frame_host/navigator.cc25
-rw-r--r--chromium/content/browser/frame_host/navigator.h43
-rw-r--r--chromium/content/browser/frame_host/navigator_delegate.cc3
-rw-r--r--chromium/content/browser/frame_host/navigator_delegate.h8
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.cc375
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.h46
-rw-r--r--chromium/content/browser/frame_host/navigator_impl_unittest.cc92
-rw-r--r--chromium/content/browser/frame_host/origin_policy_throttle.cc249
-rw-r--r--chromium/content/browser/frame_host/origin_policy_throttle.h86
-rw-r--r--chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc155
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_android.cc8
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.cc6
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h11
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_feature_policy_unittest.cc4
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc752
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h121
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc7
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc168
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.h16
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc555
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc26
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.cc108
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.h7
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc30
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.cc35
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.cc64
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.h10
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc89
-rw-r--r--chromium/content/browser/frame_host/webui_navigation_browsertest.cc220
-rw-r--r--chromium/content/browser/generic_sensor/generic_sensor_browsertest.cc50
-rw-r--r--chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.cc57
-rw-r--r--chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.h17
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl.cc22
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl.h11
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc23
-rw-r--r--chromium/content/browser/gpu/OWNERS1
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc23
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc13
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h9
-rw-r--r--chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc115
-rw-r--r--chromium/content/browser/gpu/ca_transaction_gpu_coordinator.h60
-rw-r--r--chromium/content/browser/gpu/compositor_util.cc23
-rw-r--r--chromium/content/browser/gpu/gpu_client_impl.cc97
-rw-r--r--chromium/content/browser/gpu/gpu_client_impl.h62
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.cc33
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.h44
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc179
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.h33
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc42
-rw-r--r--chromium/content/browser/gpu/gpu_internals_ui.cc74
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc345
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.h42
-rw-r--r--chromium/content/browser/host_zoom_map_impl.cc19
-rw-r--r--chromium/content/browser/host_zoom_map_impl.h6
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc10
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.cc9
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.h4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc50
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.h4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc18
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc2
-rw-r--r--chromium/content/browser/isolated_origin_browsertest.cc31
-rw-r--r--chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc11
-rw-r--r--chromium/content/browser/keyboard_lock_browsertest.cc45
-rw-r--r--chromium/content/browser/linux_ipc_browsertest.cc91
-rw-r--r--chromium/content/browser/loader/cors_file_origin_browsertest.cc86
-rw-r--r--chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc235
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler.cc60
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler.h4
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc2
-rw-r--r--chromium/content/browser/loader/data_pipe_to_source_stream.cc6
-rw-r--r--chromium/content/browser/loader/data_pipe_to_source_stream.h5
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.cc15
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.h1
-rw-r--r--chromium/content/browser/loader/download_utils_impl.cc (renamed from chromium/content/browser/loader/navigation_loader_util.cc)11
-rw-r--r--chromium/content/browser/loader/download_utils_impl.h22
-rw-r--r--chromium/content/browser/loader/downloaded_temp_file_impl.cc30
-rw-r--r--chromium/content/browser/loader/downloaded_temp_file_impl.h40
-rw-r--r--chromium/content/browser/loader/intercepting_resource_handler.cc8
-rw-r--r--chromium/content/browser/loader/layered_resource_handler.cc5
-rw-r--r--chromium/content/browser/loader/layered_resource_handler.h1
-rw-r--r--chromium/content/browser/loader/loader_browsertest.cc50
-rw-r--r--chromium/content/browser/loader/merkle_integrity_source_stream.cc2
-rw-r--r--chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc16
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler.cc9
-rw-r--r--chromium/content/browser/loader/mock_resource_loader.cc9
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.cc90
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.h13
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc74
-rw-r--r--chromium/content/browser/loader/navigation_loader_util.h34
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.h10
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc272
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.h8
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc97
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_unittest.cc6
-rw-r--r--chromium/content/browser/loader/null_resource_controller.cc9
-rw-r--r--chromium/content/browser/loader/null_resource_controller.h2
-rw-r--r--chromium/content/browser/loader/prefetch_browsertest.cc34
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.cc36
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.h18
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.cc55
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.h27
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.cc376
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.h138
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc925
-rw-r--r--chromium/content/browser/loader/resource_buffer.cc173
-rw-r--r--chromium/content/browser/loader/resource_buffer.h122
-rw-r--r--chromium/content/browser/loader/resource_buffer_unittest.cc137
-rw-r--r--chromium/content/browser/loader/resource_controller.h11
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc195
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h52
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc153
-rw-r--r--chromium/content/browser/loader/resource_handler.cc5
-rw-r--r--chromium/content/browser/loader/resource_handler.h8
-rw-r--r--chromium/content/browser/loader/resource_hints_impl.cc38
-rw-r--r--chromium/content/browser/loader/resource_loader.cc111
-rw-r--r--chromium/content/browser/loader/resource_loader.h26
-rw-r--r--chromium/content/browser/loader/resource_loader_unittest.cc3
-rw-r--r--chromium/content/browser/loader/resource_message_filter.cc31
-rw-r--r--chromium/content/browser/loader/resource_message_filter.h2
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc29
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h41
-rw-r--r--chromium/content/browser/loader/resource_scheduler_filter.cc20
-rw-r--r--chromium/content/browser/loader/resource_scheduler_filter.h23
-rw-r--r--chromium/content/browser/loader/stream_resource_handler.cc4
-rw-r--r--chromium/content/browser/loader/stream_resource_handler.h2
-rw-r--r--chromium/content/browser/loader/temporary_file_stream.cc71
-rw-r--r--chromium/content/browser/loader/temporary_file_stream.h46
-rw-r--r--chromium/content/browser/loader/temporary_file_stream_unittest.cc121
-rw-r--r--chromium/content/browser/loader/test_resource_handler.cc13
-rw-r--r--chromium/content/browser/loader/test_resource_handler.h12
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl_unittest.cc131
-rw-r--r--chromium/content/browser/loader/wake_lock_resource_throttle.cc70
-rw-r--r--chromium/content/browser/loader/wake_lock_resource_throttle.h46
-rw-r--r--chromium/content/browser/manifest/manifest_icon_downloader.cc1
-rw-r--r--chromium/content/browser/manifest/manifest_icon_selector.cc86
-rw-r--r--chromium/content/browser/manifest/manifest_icon_selector_unittest.cc499
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.cc115
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.h14
-rw-r--r--chromium/content/browser/media/android/browser_surface_view_manager.cc130
-rw-r--r--chromium/content/browser/media/android/browser_surface_view_manager.h60
-rw-r--r--chromium/content/browser/media/android/media_player_renderer.cc5
-rw-r--r--chromium/content/browser/media/android/media_player_renderer.h1
-rw-r--r--chromium/content/browser/media/android/media_web_contents_observer_android.cc38
-rw-r--r--chromium/content/browser/media/android/media_web_contents_observer_android.h11
-rw-r--r--chromium/content/browser/media/audible_metrics_unittest.cc4
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker.cc12
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker.h4
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker_unittest.cc5
-rw-r--r--chromium/content/browser/media/audio_log_factory.cc25
-rw-r--r--chromium/content/browser/media/audio_log_factory.h28
-rw-r--r--chromium/content/browser/media/audio_loopback_stream_broker.cc2
-rw-r--r--chromium/content/browser/media/audio_loopback_stream_broker.h2
-rw-r--r--chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc11
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker.cc10
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker.h3
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker_unittest.cc4
-rw-r--r--chromium/content/browser/media/audio_stream_monitor.cc2
-rw-r--r--chromium/content/browser/media/capture/aura_window_capture_machine.cc485
-rw-r--r--chromium/content/browser/media/capture/aura_window_capture_machine.h150
-rw-r--r--chromium/content/browser/media/capture/content_capture_device_browsertest_base.cc2
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer.cc6
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer.h4
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura.cc82
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura.h48
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc175
-rw-r--r--chromium/content/browser/media/capture/fake_webcontent_capture_machine.cc35
-rw-r--r--chromium/content/browser/media/capture/fake_webcontent_capture_machine.h41
-rw-r--r--chromium/content/browser/media/capture/frame_sink_video_capture_device.cc26
-rw-r--r--chromium/content/browser/media/capture/frame_sink_video_capture_device.h7
-rw-r--r--chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc10
-rw-r--r--chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc4
-rw-r--r--chromium/content/browser/media/capture/lame_window_capturer_chromeos.h4
-rw-r--r--chromium/content/browser/media/capture/screen_capture_device_android.cc52
-rw-r--r--chromium/content/browser/media/capture/screen_capture_device_android.h15
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.cc23
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device.cc15
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc8
-rw-r--r--chromium/content/browser/media/cdm_registry_impl_unittest.cc125
-rw-r--r--chromium/content/browser/media/encrypted_media_browsertest.cc111
-rw-r--r--chromium/content/browser/media/flinging_renderer.cc3
-rw-r--r--chromium/content/browser/media/flinging_renderer.h6
-rw-r--r--chromium/content/browser/media/flinging_renderer_unittest.cc6
-rw-r--r--chromium/content/browser/media/key_system_support_impl.cc134
-rw-r--r--chromium/content/browser/media/key_system_support_impl_unittest.cc92
-rw-r--r--chromium/content/browser/media/media_autoplay_browsertest.cc66
-rw-r--r--chromium/content/browser/media/media_canplaytype_browsertest.cc24
-rw-r--r--chromium/content/browser/media/media_internals.cc100
-rw-r--r--chromium/content/browser/media/media_internals.h16
-rw-r--r--chromium/content/browser/media/media_source_browsertest.cc29
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.cc92
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.h4
-rw-r--r--chromium/content/browser/media/midi_host.cc4
-rw-r--r--chromium/content/browser/media/mojo_audio_logging_adapter.cc49
-rw-r--r--chromium/content/browser/media/mojo_audio_logging_adapter.h45
-rw-r--r--chromium/content/browser/media/session/media_session_controller.cc23
-rw-r--r--chromium/content/browser/media/session/media_session_controller_unittest.cc15
-rw-r--r--chromium/content/browser/media/session/media_session_controllers_manager.cc2
-rw-r--r--chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc4
-rw-r--r--chromium/content/browser/media/session/media_session_impl_browsertest.cc2
-rw-r--r--chromium/content/browser/media/session/media_session_impl_uma_unittest.cc2
-rw-r--r--chromium/content/browser/media/session/media_session_service_impl_browsertest.cc27
-rw-r--r--chromium/content/browser/media/session/media_session_uma_helper_unittest.cc2
-rw-r--r--chromium/content/browser/memory/memory_coordinator_impl_browsertest.cc19
-rw-r--r--chromium/content/browser/mojo_sandbox_browsertest.cc1
-rw-r--r--chromium/content/browser/net/network_quality_observer_impl.cc20
-rw-r--r--chromium/content/browser/net/network_quality_observer_impl_unittest.cc2
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store.cc87
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store.h33
-rw-r--r--chromium/content/browser/net/reporting_service_proxy.cc40
-rw-r--r--chromium/content/browser/net_info_browsertest.cc2
-rw-r--r--chromium/content/browser/network_service_browsertest.cc8
-rw-r--r--chromium/content/browser/network_service_client.cc82
-rw-r--r--chromium/content/browser/network_service_client.h21
-rw-r--r--chromium/content/browser/network_service_client_unittest.cc192
-rw-r--r--chromium/content/browser/network_service_instance.cc3
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl.cc258
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl.h44
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc113
-rw-r--r--chromium/content/browser/notifications/notification_database.cc110
-rw-r--r--chromium/content/browser/notifications/notification_database.h25
-rw-r--r--chromium/content/browser/notifications/notification_database_data_conversions.cc24
-rw-r--r--chromium/content/browser/notifications/notification_database_data_unittest.cc30
-rw-r--r--chromium/content/browser/notifications/notification_database_unittest.cc94
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.cc151
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.h5
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc43
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_impl.cc42
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_impl.h29
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_unittest.cc62
-rw-r--r--chromium/content/browser/oop_browsertest.cc22
-rw-r--r--chromium/content/browser/origin_manifest/origin_manifest_parser.cc105
-rw-r--r--chromium/content/browser/origin_manifest/origin_manifest_parser.h54
-rw-r--r--chromium/content/browser/origin_manifest/origin_manifest_parser_unittest.cc386
-rw-r--r--chromium/content/browser/payments/payment_app_browsertest.cc22
-rw-r--r--chromium/content/browser/payments/payment_app_content_unittest_base.cc30
-rw-r--r--chromium/content/browser/payments/payment_app_database.cc100
-rw-r--r--chromium/content/browser/payments/payment_app_database.h50
-rw-r--r--chromium/content/browser/payments/payment_app_info_fetcher.cc8
-rw-r--r--chromium/content/browser/payments/payment_app_provider_impl.cc64
-rw-r--r--chromium/content/browser/payments/payment_app_provider_impl_unittest.cc4
-rw-r--r--chromium/content/browser/payments/payment_instrument_icon_fetcher.cc18
-rw-r--r--chromium/content/browser/payments/payment_instrument_icon_fetcher.h2
-rw-r--r--chromium/content/browser/performance_memory_browsertest.cc56
-rw-r--r--chromium/content/browser/permissions/permission_controller_impl.cc126
-rw-r--r--chromium/content/browser/permissions/permission_controller_impl.h72
-rw-r--r--chromium/content/browser/permissions/permission_service_context.cc24
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.cc40
-rw-r--r--chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc57
-rw-r--r--chromium/content/browser/picture_in_picture/overlay_surface_embedder.h9
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc105
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h17
-rw-r--r--chromium/content/browser/plugin_service_impl.cc8
-rw-r--r--chromium/content/browser/plugin_service_impl_unittest.cc25
-rw-r--r--chromium/content/browser/pointer_lock_browsertest.cc82
-rw-r--r--chromium/content/browser/pointer_lock_browsertest_mac.mm14
-rw-r--r--chromium/content/browser/power_monitor_browsertest.cc10
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc1
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl_unittest.cc2
-rw-r--r--chromium/content/browser/process_internals/process_internals.mojom5
-rw-r--r--chromium/content/browser/process_internals/process_internals_handler_impl.cc13
-rw-r--r--chromium/content/browser/process_internals/process_internals_handler_impl.h2
-rw-r--r--chromium/content/browser/process_internals/process_internals_ui.cc2
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_manager.cc97
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_manager.h17
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.cc66
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.h8
-rw-r--r--chromium/content/browser/renderer_host/OWNERS4
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.h36
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.mm305
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl.cc138
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl.h23
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc62
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc245
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h31
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc101
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.cc86
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.h26
-rw-r--r--chromium/content/browser/renderer_host/display_util.cc4
-rw-r--r--chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/font_utils_linux.cc265
-rw-r--r--chromium/content/browser/renderer_host/font_utils_linux.h22
-rw-r--r--chromium/content/browser/renderer_host/frame_connector_delegate.h7
-rw-r--r--chromium/content/browser/renderer_host/frame_metadata_util.cc29
-rw-r--r--chromium/content/browser/renderer_host/frame_metadata_util.h10
-rw-r--r--chromium/content/browser/renderer_host/input/README.md23
-rw-r--r--chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc14
-rw-r--r--chromium/content/browser/renderer_host/input/fling_browsertest.cc90
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller.cc47
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller.h2
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller_unittest.cc18
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler.cc1
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler.h6
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler_android.cc83
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler_android.h55
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler_base.h20
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue.cc26
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue.h11
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc69
-rw-r--r--chromium/content/browser/renderer_host/input/input_router.h11
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.cc69
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.h17
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc398
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc120
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc145
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h26
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc520
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc5
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.h6
-rw-r--r--chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc98
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h9
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc269
-rw-r--r--chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc100
-rw-r--r--chromium/content/browser/renderer_host/input/stylus_text_selector.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc39
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc3
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc33
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_browsertest.cc71
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.cc137
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.h26
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc951
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.h1
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc3
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc12
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc187
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.cc161
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.h76
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue_unittest.cc350
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm4
-rw-r--r--chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc306
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_stream_handle.cc5
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_stream_handle.h2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc8
-rw-r--r--chromium/content/browser/renderer_host/media/audio_service_listener.cc30
-rw-r--r--chromium/content/browser/renderer_host/media/audio_service_listener.h4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/fake_video_capture_device_launcher.cc1
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc18
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h1
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc31
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager.cc108
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager.h32
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc260
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc100
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.h15
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc64
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc15
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc5
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc1
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider.cc57
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider.h14
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc18
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_browsertest.cc21
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc3
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc14
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_dependencies.cc53
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_dependencies.h25
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc336
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h123
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.cc12
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.h2
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc10
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h5
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc4
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc6
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc13
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.cc7
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc15
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc26
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h11
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc34
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h11
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_android.cc16
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc14
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_android.cc20
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc17
-rw-r--r--chromium/content/browser/renderer_host/plugin_registry_impl.cc87
-rw-r--r--chromium/content/browser/renderer_host/plugin_registry_impl.h43
-rw-r--r--chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc15
-rw-r--r--chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h3
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.cc4
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.h5
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc582
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h27
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_unittest.cc49
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.cc4
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.h7
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.cc9
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.h2
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc72
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h17
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_unittest.cc1
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_browsertest.cc82
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.cc11
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.h29
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc346
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h71
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc285
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.h8
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.h126
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h99
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm (renamed from chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm)158
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h163
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_owner_delegate.h3
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc348
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc569
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h54
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc110
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h18
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc1239
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc92
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h35
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc3
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc244
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h45
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc41
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc89
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h30
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm353
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc160
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.h212
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm498
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.mm4
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm293
-rw-r--r--chromium/content/browser/renderer_host/render_widget_targeter.cc18
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.cc5
-rw-r--r--chromium/content/browser/renderer_host/web_database_host_impl.cc4
-rw-r--r--chromium/content/browser/renderer_interface_binders.cc22
-rw-r--r--chromium/content/browser/resources/gpu/OWNERS3
-rw-r--r--chromium/content/browser/resources/gpu/info_view.js1
-rw-r--r--chromium/content/browser/resources/histograms/histograms_internals.html2
-rw-r--r--chromium/content/browser/resources/media/peer_connection_update_table.js8
-rw-r--r--chromium/content/browser/resources/process/process_internals.html2
-rw-r--r--chromium/content/browser/resources/process/process_internals.js5
-rw-r--r--chromium/content/browser/resources/service_worker/serviceworker_internals.js4
-rw-r--r--chromium/content/browser/sandbox_ipc_linux.cc253
-rw-r--r--chromium/content/browser/sandbox_ipc_linux.h38
-rw-r--r--chromium/content/browser/sandbox_parameters_mac.mm5
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc9
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc95
-rw-r--r--chromium/content/browser/service_manager/common_browser_interfaces.cc51
-rw-r--r--chromium/content/browser/service_manager/service_manager_context.cc288
-rw-r--r--chromium/content/browser/service_manager/service_manager_context.h17
-rw-r--r--chromium/content/browser/service_worker/OWNERS8
-rw-r--r--chromium/content/browser/service_worker/README.md44
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc327
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h93
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc535
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.h2
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.cc293
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.h155
-rw-r--r--chromium/content/browser/service_worker/service_worker_browsertest.cc512
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_utils.cc10
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_utils.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.cc110
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.h58
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core_observer.h8
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core_unittest.cc19
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc12
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_unittest.cc65
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.h8
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher_unittest.cc19
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.cc242
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.h38
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc132
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.h15
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.cc17
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.h2
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.cc173
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.h87
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc292
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc79
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h26
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_script_loader.cc12
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_script_loader.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.cc41
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.h7
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_unittest.cc229
-rw-r--r--chromium/content/browser/service_worker/service_worker_lifetime_tracker_unittest.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.cc337
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.h176
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics_unittest.cc251
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc18
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader.cc181
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader.h19
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc186
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader.cc195
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader.h69
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc598
-rw-r--r--chromium/content/browser/service_worker/service_worker_object_host.cc (renamed from chromium/content/browser/service_worker/service_worker_handle.cc)70
-rw-r--r--chromium/content/browser/service_worker/service_worker_object_host.h (renamed from chromium/content/browser/service_worker/service_worker_handle.h)71
-rw-r--r--chromium/content/browser/service_worker/service_worker_object_host_unittest.cc (renamed from chromium/content/browser/service_worker/service_worker_handle_unittest.cc)166
-rw-r--r--chromium/content/browser/service_worker/service_worker_ping_controller.cc68
-rw-r--r--chromium/content/browser/service_worker/service_worker_ping_controller.h54
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager.cc17
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager.h17
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc45
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.cc366
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.h141
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc414
-rw-r--r--chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc43
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.cc145
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.h42
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.cc41
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.h16
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_object_host.cc28
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_object_host.h8
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_status.cc47
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_status.h6
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_unittest.cc64
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.cc31
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.h2
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_loader_factory.cc102
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_loader_factory.h5
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.cc183
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.h32
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage_unittest.cc493
-rw-r--r--chromium/content/browser/service_worker/service_worker_test_utils.cc125
-rw-r--r--chromium/content/browser/service_worker/service_worker_test_utils.h36
-rw-r--r--chromium/content/browser/service_worker/service_worker_type_converters.cc16
-rw-r--r--chromium/content/browser/service_worker/service_worker_type_converters.h15
-rw-r--r--chromium/content/browser/service_worker/service_worker_unregister_job.cc24
-rw-r--r--chromium/content/browser/service_worker/service_worker_unregister_job.h13
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc14
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.cc10
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.h6
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc67
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc430
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h148
-rw-r--r--chromium/content/browser/service_worker/service_worker_version_unittest.cc247
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.h2
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc34
-rw-r--r--chromium/content/browser/shared_worker/OWNERS1
-rw-r--r--chromium/content/browser/shared_worker/mock_shared_worker.cc3
-rw-r--r--chromium/content/browser/shared_worker/mock_shared_worker.h3
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_connector_impl.cc16
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_connector_impl.h3
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.cc59
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.h6
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host_unittest.cc23
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader.cc21
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader.h8
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc4
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.cc171
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.h27
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc2
-rw-r--r--chromium/content/browser/shared_worker/worker_browsertest.cc37
-rw-r--r--chromium/content/browser/site_instance_impl.cc47
-rw-r--r--chromium/content/browser/site_instance_impl.h7
-rw-r--r--chromium/content/browser/site_instance_impl_unittest.cc107
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc945
-rw-r--r--chromium/content/browser/site_per_process_hit_test_browsertest.cc546
-rw-r--r--chromium/content/browser/site_per_process_mac_browsertest.mm22
-rw-r--r--chromium/content/browser/snapshot_browsertest.cc25
-rw-r--r--chromium/content/browser/speech/chunked_byte_buffer.cc2
-rw-r--r--chromium/content/browser/speech/chunked_byte_buffer.h3
-rw-r--r--chromium/content/browser/speech/speech_recognition_browsertest.cc16
-rw-r--r--chromium/content/browser/speech/speech_recognition_dispatcher_host.cc73
-rw-r--r--chromium/content/browser/speech/speech_recognition_dispatcher_host.h65
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine.cc429
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine.h67
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine_unittest.cc533
-rw-r--r--chromium/content/browser/speech/speech_recognition_manager_impl.cc21
-rw-r--r--chromium/content/browser/speech/speech_recognition_manager_impl.h13
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.cc58
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.h15
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_android.cc24
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_android.h7
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_unittest.cc197
-rw-r--r--chromium/content/browser/startup_data_impl.cc13
-rw-r--r--chromium/content/browser/startup_data_impl.h26
-rw-r--r--chromium/content/browser/startup_task_runner.cc17
-rw-r--r--chromium/content/browser/startup_task_runner.h4
-rw-r--r--chromium/content/browser/startup_task_runner_unittest.cc10
-rw-r--r--chromium/content/browser/storage_partition_impl.cc67
-rw-r--r--chromium/content/browser/storage_partition_impl.h22
-rw-r--r--chromium/content/browser/storage_partition_impl_browsertest.cc88
-rw-r--r--chromium/content/browser/storage_partition_impl_map.cc5
-rw-r--r--chromium/content/browser/tracing/background_memory_tracing_observer.cc73
-rw-r--r--chromium/content/browser/tracing/background_memory_tracing_observer.h6
-rw-r--r--chromium/content/browser/tracing/background_memory_tracing_observer_unittest.cc176
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_browsertest.cc60
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.cc9
-rw-r--r--chromium/content/browser/tracing/cast_tracing_agent.cc3
-rw-r--r--chromium/content/browser/tracing/cros_tracing_agent.cc3
-rw-r--r--chromium/content/browser/tracing/etw_tracing_agent_win.cc3
-rw-r--r--chromium/content/browser/tracing/memory_instrumentation_browsertest.cc19
-rw-r--r--chromium/content/browser/tracing/power_tracing_agent.cc6
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc31
-rw-r--r--chromium/content/browser/url_loader_factory_getter.cc31
-rw-r--r--chromium/content/browser/url_loader_factory_getter.h10
-rw-r--r--chromium/content/browser/utility_process_host.cc37
-rw-r--r--chromium/content/browser/utility_process_host.h16
-rw-r--r--chromium/content/browser/utility_process_host_browsertest.cc134
-rw-r--r--chromium/content/browser/vibration_browsertest.cc9
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc4
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.cc32
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.h25
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc407
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h100
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc271
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_unittest.cc406
-rw-r--r--chromium/content/browser/web_contents/web_contents_view.h10
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.cc107
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.h6
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc12
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.h4
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc3
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_child_frame.cc6
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_child_frame.h4
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.cc13
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.h4
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.h19
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm40
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac_unittest.mm24
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc75
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher.h11
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc15
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.h5
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc177
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain.cc181
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain.h6
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc2
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc255
-rw-r--r--chromium/content/browser/web_package/signed_exchange_consts.h11
-rw-r--r--chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc24
-rw-r--r--chromium/content/browser/web_package/signed_exchange_devtools_proxy.h14
-rw-r--r--chromium/content/browser/web_package/signed_exchange_envelope.cc (renamed from chromium/content/browser/web_package/signed_exchange_header.cc)195
-rw-r--r--chromium/content/browser/web_package/signed_exchange_envelope.h (renamed from chromium/content/browser/web_package/signed_exchange_header.h)43
-rw-r--r--chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc230
-rw-r--r--chromium/content/browser/web_package/signed_exchange_error.cc48
-rw-r--r--chromium/content/browser/web_package/signed_exchange_error.h50
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler.cc365
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler.h20
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler_unittest.cc590
-rw-r--r--chromium/content/browser/web_package/signed_exchange_header_parser_unittest.cc281
-rw-r--r--chromium/content/browser/web_package/signed_exchange_header_unittest.cc210
-rw-r--r--chromium/content/browser/web_package/signed_exchange_loader.cc (renamed from chromium/content/browser/web_package/web_package_loader.cc)137
-rw-r--r--chromium/content/browser/web_package/signed_exchange_loader.h (renamed from chromium/content/browser/web_package/web_package_loader.h)37
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc (renamed from chromium/content/browser/web_package/web_package_prefetch_handler.cc)45
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prefetch_handler.h (renamed from chromium/content/browser/web_package/web_package_prefetch_handler.h)34
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prologue.cc83
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prologue.h74
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prologue_unittest.cc63
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler.cc (renamed from chromium/content/browser/web_package/web_package_request_handler.cc)41
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler.h (renamed from chromium/content/browser/web_package/web_package_request_handler.h)25
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc (renamed from chromium/content/browser/web_package/web_package_request_handler_browsertest.cc)224
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_header_field.cc (renamed from chromium/content/browser/web_package/signed_exchange_header_parser.cc)175
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_header_field.h (renamed from chromium/content/browser/web_package/signed_exchange_header_parser.h)12
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc333
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier.cc229
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier.h9
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc276
-rw-r--r--chromium/content/browser/web_package/signed_exchange_utils.cc19
-rw-r--r--chromium/content/browser/web_package/signed_exchange_utils.h17
-rw-r--r--chromium/content/browser/webauth/OWNERS3
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.cc489
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.h39
-rw-r--r--chromium/content/browser/webauth/authenticator_impl_unittest.cc627
-rw-r--r--chromium/content/browser/webauth/authenticator_type_converters.cc30
-rw-r--r--chromium/content/browser/webauth/authenticator_type_converters.h40
-rw-r--r--chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc10
-rw-r--r--chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h10
-rw-r--r--chromium/content/browser/webauth/virtual_authenticator.cc21
-rw-r--r--chromium/content/browser/webauth/virtual_authenticator.h10
-rw-r--r--chromium/content/browser/webauth/webauth_browsertest.cc731
-rw-r--r--chromium/content/browser/webrtc/webrtc_audio_browsertest.cc79
-rw-r--r--chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc138
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals.cc10
-rw-r--r--chromium/content/browser/webrtc/webrtc_stress_image_capture_browsertest.cc126
-rw-r--r--chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc473
-rw-r--r--chromium/content/browser/websockets/websocket_manager.cc7
-rw-r--r--chromium/content/browser/websockets/websocket_manager.h10
-rw-r--r--chromium/content/browser/websockets/websocket_manager_unittest.cc1
-rw-r--r--chromium/content/browser/webui/content_web_ui_controller_factory.cc28
-rw-r--r--chromium/content/browser/webui/content_web_ui_controller_factory.h10
-rw-r--r--chromium/content/browser/webui/shared_resources_data_source.cc72
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.cc49
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.h7
-rw-r--r--chromium/content/browser/webui/url_data_source_impl.h20
-rw-r--r--chromium/content/browser/webui/web_ui_controller_factory_registry.cc16
-rw-r--r--chromium/content/browser/webui/web_ui_controller_factory_registry.h5
-rw-r--r--chromium/content/browser/webui/web_ui_impl.cc7
-rw-r--r--chromium/content/browser/webui/web_ui_impl.h2
-rw-r--r--chromium/content/browser/webui/web_ui_mojo_browsertest.cc155
-rw-r--r--chromium/content/browser/webui/web_ui_url_loader_factory.cc4
1081 files changed, 42573 insertions, 34275 deletions
diff --git a/chromium/content/browser/BUILD.gn b/chromium/content/browser/BUILD.gn
index 5747496dc5f..abaa573b8f1 100644
--- a/chromium/content/browser/BUILD.gn
+++ b/chromium/content/browser/BUILD.gn
@@ -39,11 +39,12 @@ jumbo_source_set("browser") {
"//base/third_party/dynamic_annotations",
"//cc",
"//cc/animation",
+ "//cc/mojo_embedder",
"//cc/paint",
"//components/cbor",
"//components/discardable_memory/common",
"//components/discardable_memory/service",
- "//components/download/downloader/in_progress",
+ "//components/download/database",
"//components/download/public/common:public",
"//components/download/quarantine",
"//components/filename_generation",
@@ -84,17 +85,17 @@ jumbo_source_set("browser") {
"//content/common:mojo_bindings",
"//content/public/common:common_sources",
"//crypto",
+ "//device/base",
"//device/bluetooth",
"//device/fido",
"//device/gamepad",
- "//device/geolocation/public/cpp",
"//device/vr/public/mojom",
"//google_apis",
"//gpu",
"//gpu/command_buffer/client:gles2_implementation",
"//gpu/command_buffer/client:gles2_interface",
"//gpu/command_buffer/client:raster_interface",
- "//gpu/ipc/common:gpu_preferences_util",
+ "//gpu/ipc:gl_in_process_context",
"//gpu/ipc/host",
"//gpu/vulkan:buildflags",
"//jingle:jingle_glue",
@@ -108,12 +109,14 @@ jumbo_source_set("browser") {
"//media/mojo/interfaces",
"//media/mojo/interfaces:constants",
"//media/mojo/services",
- "//mojo/edk",
+ "//mojo/core/embedder",
"//mojo/public/cpp/bindings",
+ "//mojo/public/cpp/platform",
+ "//mojo/public/cpp/system",
"//mojo/public/js:resources",
"//net",
"//net:extras",
- "//net:http_server",
+ "//net/server:http_server",
"//ppapi/buildflags",
"//printing/buildflags",
"//services/audio:lib",
@@ -122,10 +125,13 @@ jumbo_source_set("browser") {
"//services/catalog:constants",
"//services/catalog/public/cpp",
"//services/catalog/public/mojom:constants",
+ "//services/content:impl",
+ "//services/content/public/mojom",
"//services/data_decoder/public/cpp",
"//services/data_decoder/public/mojom",
"//services/device:lib",
"//services/device/public/cpp:device_features",
+ "//services/device/public/cpp/geolocation",
"//services/device/public/mojom",
"//services/device/public/mojom:generic_sensor",
"//services/file:lib",
@@ -310,8 +316,6 @@ jumbo_source_set("browser") {
"android/content_protocol_handler_impl.h",
"android/content_startup_flags.cc",
"android/content_startup_flags.h",
- "android/content_video_view.cc",
- "android/content_video_view.h",
"android/devtools_auth.cc",
"android/dialog_overlay_impl.cc",
"android/dialog_overlay_impl.h",
@@ -435,10 +439,10 @@ jumbo_source_set("browser") {
"background_fetch/storage/delete_registration_task.h",
"background_fetch/storage/get_developer_ids_task.cc",
"background_fetch/storage/get_developer_ids_task.h",
+ "background_fetch/storage/get_initialization_data_task.cc",
+ "background_fetch/storage/get_initialization_data_task.h",
"background_fetch/storage/get_metadata_task.cc",
"background_fetch/storage/get_metadata_task.h",
- "background_fetch/storage/get_num_requests_task.cc",
- "background_fetch/storage/get_num_requests_task.h",
"background_fetch/storage/get_settled_fetches_task.cc",
"background_fetch/storage/get_settled_fetches_task.h",
"background_fetch/storage/mark_registration_for_deletion_task.cc",
@@ -472,8 +476,6 @@ jumbo_source_set("browser") {
"blob_storage/blob_internals_url_loader.h",
"blob_storage/blob_registry_wrapper.cc",
"blob_storage/blob_registry_wrapper.h",
- "blob_storage/blob_url_loader_factory.cc",
- "blob_storage/blob_url_loader_factory.h",
"blob_storage/chrome_blob_storage_context.cc",
"blob_storage/chrome_blob_storage_context.h",
"bluetooth/bluetooth_allowed_devices.cc",
@@ -571,12 +573,18 @@ jumbo_source_set("browser") {
"cocoa/system_hotkey_helper_mac.mm",
"cocoa/system_hotkey_map.h",
"cocoa/system_hotkey_map.mm",
+ "code_cache/generated_code_cache.cc",
+ "code_cache/generated_code_cache.h",
+ "startup_data_impl.cc",
+ "startup_data_impl.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.
"compositor/surface_utils.cc",
"compositor/surface_utils.h",
+ "content_service_delegate_impl.cc",
+ "content_service_delegate_impl.h",
"cookie_store/cookie_change_subscription.cc",
"cookie_store/cookie_change_subscription.h",
"cookie_store/cookie_store_context.cc",
@@ -684,7 +692,12 @@ jumbo_source_set("browser") {
"devtools/shared_worker_devtools_agent_host.h",
"devtools/shared_worker_devtools_manager.cc",
"devtools/shared_worker_devtools_manager.h",
+ "devtools/target_registry.cc",
+ "devtools/target_registry.h",
"discardable_shared_memory_manager.cc",
+ "display_cutout/display_cutout_constants.h",
+ "display_cutout/display_cutout_host_impl.cc",
+ "display_cutout/display_cutout_host_impl.h",
"dom_storage/dom_storage_area.cc",
"dom_storage/dom_storage_area.h",
"dom_storage/dom_storage_context_impl.cc",
@@ -704,6 +717,8 @@ jumbo_source_set("browser") {
"dom_storage/dom_storage_task_runner.h",
"dom_storage/local_storage_context_mojo.cc",
"dom_storage/local_storage_context_mojo.h",
+ "dom_storage/session_storage_area_impl.cc",
+ "dom_storage/session_storage_area_impl.h",
"dom_storage/session_storage_context_mojo.cc",
"dom_storage/session_storage_context_mojo.h",
"dom_storage/session_storage_data_map.cc",
@@ -712,16 +727,14 @@ jumbo_source_set("browser") {
"dom_storage/session_storage_database.h",
"dom_storage/session_storage_database_adapter.cc",
"dom_storage/session_storage_database_adapter.h",
- "dom_storage/session_storage_leveldb_wrapper.cc",
- "dom_storage/session_storage_leveldb_wrapper.h",
"dom_storage/session_storage_metadata.cc",
"dom_storage/session_storage_metadata.h",
"dom_storage/session_storage_namespace_impl.cc",
"dom_storage/session_storage_namespace_impl.h",
"dom_storage/session_storage_namespace_impl_mojo.cc",
"dom_storage/session_storage_namespace_impl_mojo.h",
- "download/blob_download_url_loader_factory_getter.cc",
- "download/blob_download_url_loader_factory_getter.h",
+ "dom_storage/storage_area_impl.cc",
+ "dom_storage/storage_area_impl.h",
"download/byte_stream_input_stream.cc",
"download/byte_stream_input_stream.h",
"download/download_item_utils.cc",
@@ -742,6 +755,8 @@ jumbo_source_set("browser") {
"download/drag_download_file.h",
"download/drag_download_util.cc",
"download/drag_download_util.h",
+ "download/file_download_url_loader_factory_getter.cc",
+ "download/file_download_url_loader_factory_getter.h",
"download/mhtml_extra_parts_impl.cc",
"download/mhtml_extra_parts_impl.h",
"download/mhtml_generation_manager.cc",
@@ -762,6 +777,8 @@ jumbo_source_set("browser") {
"download/url_downloader.h",
"download/url_downloader_factory.cc",
"download/url_downloader_factory.h",
+ "download/web_ui_download_url_loader_factory_getter.cc",
+ "download/web_ui_download_url_loader_factory_getter.h",
"field_trial_recorder.cc",
"field_trial_recorder.h",
"file_url_loader_factory.cc",
@@ -824,6 +841,8 @@ jumbo_source_set("browser") {
"frame_host/navigator_delegate.h",
"frame_host/navigator_impl.cc",
"frame_host/navigator_impl.h",
+ "frame_host/origin_policy_throttle.cc",
+ "frame_host/origin_policy_throttle.h",
"frame_host/popup_menu_helper_mac.h",
"frame_host/popup_menu_helper_mac.mm",
"frame_host/render_frame_host_delegate.cc",
@@ -968,16 +987,14 @@ jumbo_source_set("browser") {
"keyboard_lock/keyboard_lock_metrics.h",
"keyboard_lock/keyboard_lock_service_impl.cc",
"keyboard_lock/keyboard_lock_service_impl.h",
- "leveldb_wrapper_impl.cc",
- "leveldb_wrapper_impl.h",
"loader/cross_site_document_resource_handler.cc",
"loader/cross_site_document_resource_handler.h",
"loader/data_pipe_to_source_stream.cc",
"loader/data_pipe_to_source_stream.h",
"loader/detachable_resource_handler.cc",
"loader/detachable_resource_handler.h",
- "loader/downloaded_temp_file_impl.cc",
- "loader/downloaded_temp_file_impl.h",
+ "loader/download_utils_impl.cc",
+ "loader/download_utils_impl.h",
"loader/global_routing_id.h",
"loader/intercepting_resource_handler.cc",
"loader/intercepting_resource_handler.h",
@@ -994,8 +1011,6 @@ jumbo_source_set("browser") {
"loader/mojo_async_resource_handler.h",
"loader/navigation_loader_interceptor.cc",
"loader/navigation_loader_interceptor.h",
- "loader/navigation_loader_util.cc",
- "loader/navigation_loader_util.h",
"loader/navigation_url_loader.cc",
"loader/navigation_url_loader.h",
"loader/navigation_url_loader_delegate.h",
@@ -1008,10 +1023,6 @@ jumbo_source_set("browser") {
"loader/prefetch_url_loader.h",
"loader/prefetch_url_loader_service.cc",
"loader/prefetch_url_loader_service.h",
- "loader/redirect_to_file_resource_handler.cc",
- "loader/redirect_to_file_resource_handler.h",
- "loader/resource_buffer.cc",
- "loader/resource_buffer.h",
"loader/resource_controller.h",
"loader/resource_dispatcher_host_impl.cc",
"loader/resource_dispatcher_host_impl.h",
@@ -1035,16 +1046,12 @@ jumbo_source_set("browser") {
"loader/stream_resource_handler.h",
"loader/stream_writer.cc",
"loader/stream_writer.h",
- "loader/temporary_file_stream.cc",
- "loader/temporary_file_stream.h",
"loader/throttling_resource_handler.cc",
"loader/throttling_resource_handler.h",
"loader/upload_data_stream_builder.cc",
"loader/upload_data_stream_builder.h",
"loader/url_loader_factory_impl.cc",
"loader/url_loader_factory_impl.h",
- "loader/wake_lock_resource_throttle.cc",
- "loader/wake_lock_resource_throttle.h",
"loader_delegate_impl.cc",
"loader_delegate_impl.h",
"locks/lock_manager.cc",
@@ -1052,13 +1059,10 @@ jumbo_source_set("browser") {
"mach_broker_mac.h",
"mach_broker_mac.mm",
"manifest/manifest_icon_downloader.cc",
- "manifest/manifest_icon_selector.cc",
"manifest/manifest_manager_host.cc",
"manifest/manifest_manager_host.h",
"media/android/browser_media_player_manager.cc",
"media/android/browser_media_player_manager.h",
- "media/android/browser_surface_view_manager.cc",
- "media/android/browser_surface_view_manager.h",
"media/android/media_player_renderer.cc",
"media/android/media_player_renderer.h",
"media/android/media_player_renderer_web_contents_observer.cc",
@@ -1071,6 +1075,8 @@ jumbo_source_set("browser") {
"media/audible_metrics.h",
"media/audio_input_stream_broker.cc",
"media/audio_input_stream_broker.h",
+ "media/audio_log_factory.cc",
+ "media/audio_log_factory.h",
"media/audio_loopback_stream_broker.cc",
"media/audio_loopback_stream_broker.h",
"media/audio_muting_session.cc",
@@ -1115,8 +1121,6 @@ jumbo_source_set("browser") {
"media/media_web_contents_observer.h",
"media/midi_host.cc",
"media/midi_host.h",
- "media/mojo_audio_logging_adapter.cc",
- "media/mojo_audio_logging_adapter.h",
"media/session/audio_focus_delegate.h",
"media/session/audio_focus_delegate_android.cc",
"media/session/audio_focus_delegate_android.h",
@@ -1191,8 +1195,6 @@ jumbo_source_set("browser") {
"notifications/notification_id_generator.h",
"notifications/platform_notification_context_impl.cc",
"notifications/platform_notification_context_impl.h",
- "origin_manifest/origin_manifest_parser.cc",
- "origin_manifest/origin_manifest_parser.h",
"payments/payment_app_context_impl.cc",
"payments/payment_app_context_impl.h",
"payments/payment_app_database.cc",
@@ -1207,6 +1209,8 @@ jumbo_source_set("browser") {
"payments/payment_instrument_icon_fetcher.h",
"payments/payment_manager.cc",
"payments/payment_manager.h",
+ "permissions/permission_controller_impl.cc",
+ "permissions/permission_controller_impl.h",
"permissions/permission_service_context.cc",
"permissions/permission_service_context.h",
"permissions/permission_service_impl.cc",
@@ -1247,8 +1251,6 @@ jumbo_source_set("browser") {
"renderer_host/event_with_latency_info.h",
"renderer_host/file_utilities_host_impl.cc",
"renderer_host/file_utilities_host_impl.h",
- "renderer_host/font_utils_linux.cc",
- "renderer_host/font_utils_linux.h",
"renderer_host/frame_connector_delegate.cc",
"renderer_host/frame_connector_delegate.h",
"renderer_host/frame_metadata_util.cc",
@@ -1261,6 +1263,7 @@ jumbo_source_set("browser") {
"renderer_host/input/fling_controller.h",
"renderer_host/input/fling_scheduler.cc",
"renderer_host/input/fling_scheduler.h",
+ "renderer_host/input/fling_scheduler_base.h",
"renderer_host/input/fling_scheduler_mac.h",
"renderer_host/input/fling_scheduler_mac.mm",
"renderer_host/input/gesture_event_queue.cc",
@@ -1340,6 +1343,8 @@ jumbo_source_set("browser") {
"renderer_host/input/touch_selection_controller_client_child_frame.h",
"renderer_host/input/touch_timeout_handler.cc",
"renderer_host/input/touch_timeout_handler.h",
+ "renderer_host/input/touchpad_pinch_event_queue.cc",
+ "renderer_host/input/touchpad_pinch_event_queue.h",
"renderer_host/input/touchpad_tap_suppression_controller.cc",
"renderer_host/input/touchpad_tap_suppression_controller.h",
"renderer_host/input/touchscreen_tap_suppression_controller.cc",
@@ -1407,11 +1412,11 @@ jumbo_source_set("browser") {
"renderer_host/media/video_capture_controller.cc",
"renderer_host/media/video_capture_controller.h",
"renderer_host/media/video_capture_controller_event_handler.h",
+ "renderer_host/media/video_capture_dependencies.cc",
+ "renderer_host/media/video_capture_dependencies.h",
"renderer_host/media/video_capture_device_launch_observer.h",
"renderer_host/media/video_capture_factory_delegate.cc",
"renderer_host/media/video_capture_factory_delegate.h",
- "renderer_host/media/video_capture_gpu_jpeg_decoder.cc",
- "renderer_host/media/video_capture_gpu_jpeg_decoder.h",
"renderer_host/media/video_capture_host.cc",
"renderer_host/media/video_capture_host.h",
"renderer_host/media/video_capture_manager.cc",
@@ -1548,8 +1553,6 @@ jumbo_source_set("browser") {
"service_worker/service_worker_dispatcher_host.h",
"service_worker/service_worker_fetch_dispatcher.cc",
"service_worker/service_worker_fetch_dispatcher.h",
- "service_worker/service_worker_handle.cc",
- "service_worker/service_worker_handle.h",
"service_worker/service_worker_info.cc",
"service_worker/service_worker_info.h",
"service_worker/service_worker_installed_script_loader.cc",
@@ -1574,6 +1577,10 @@ jumbo_source_set("browser") {
"service_worker/service_worker_navigation_loader.h",
"service_worker/service_worker_new_script_loader.cc",
"service_worker/service_worker_new_script_loader.h",
+ "service_worker/service_worker_object_host.cc",
+ "service_worker/service_worker_object_host.h",
+ "service_worker/service_worker_ping_controller.cc",
+ "service_worker/service_worker_ping_controller.h",
"service_worker/service_worker_process_manager.cc",
"service_worker/service_worker_process_manager.h",
"service_worker/service_worker_provider_host.cc",
@@ -1728,12 +1735,22 @@ jumbo_source_set("browser") {
"web_package/signed_exchange_consts.h",
"web_package/signed_exchange_devtools_proxy.cc",
"web_package/signed_exchange_devtools_proxy.h",
+ "web_package/signed_exchange_envelope.cc",
+ "web_package/signed_exchange_envelope.h",
+ "web_package/signed_exchange_error.cc",
+ "web_package/signed_exchange_error.h",
"web_package/signed_exchange_handler.cc",
"web_package/signed_exchange_handler.h",
- "web_package/signed_exchange_header.cc",
- "web_package/signed_exchange_header.h",
- "web_package/signed_exchange_header_parser.cc",
- "web_package/signed_exchange_header_parser.h",
+ "web_package/signed_exchange_loader.cc",
+ "web_package/signed_exchange_loader.h",
+ "web_package/signed_exchange_prefetch_handler.cc",
+ "web_package/signed_exchange_prefetch_handler.h",
+ "web_package/signed_exchange_prologue.cc",
+ "web_package/signed_exchange_prologue.h",
+ "web_package/signed_exchange_request_handler.cc",
+ "web_package/signed_exchange_request_handler.h",
+ "web_package/signed_exchange_signature_header_field.cc",
+ "web_package/signed_exchange_signature_header_field.h",
"web_package/signed_exchange_signature_verifier.cc",
"web_package/signed_exchange_signature_verifier.h",
"web_package/signed_exchange_url_loader_factory_for_non_network_service.cc",
@@ -1742,12 +1759,6 @@ jumbo_source_set("browser") {
"web_package/signed_exchange_utils.h",
"web_package/web_package_context_impl.cc",
"web_package/web_package_context_impl.h",
- "web_package/web_package_loader.cc",
- "web_package/web_package_loader.h",
- "web_package/web_package_prefetch_handler.cc",
- "web_package/web_package_prefetch_handler.h",
- "web_package/web_package_request_handler.cc",
- "web_package/web_package_request_handler.h",
"webrtc/webrtc_internals.cc",
"webrtc/webrtc_internals.h",
"webrtc/webrtc_internals_message_handler.cc",
@@ -1789,7 +1800,11 @@ jumbo_source_set("browser") {
}
if (is_linux) {
- deps += [ "//services/service_manager/zygote" ]
+ deps += [
+ "//components/services/font:lib",
+ "//components/services/font/public/interfaces",
+ "//services/service_manager/zygote",
+ ]
}
# ChromeOS also defines linux but their memory-monitors conflict.
@@ -1842,6 +1857,14 @@ jumbo_source_set("browser") {
deps += [ "//printing" ]
}
+ if (is_mac) {
+ sources += [
+ "gpu/ca_transaction_gpu_coordinator.cc",
+ "gpu/ca_transaction_gpu_coordinator.h",
+ ]
+ deps += [ "//ui/events:dom_keyboard_layout" ]
+ }
+
if (!is_mac) {
deps += [ "//sandbox" ]
}
@@ -1868,8 +1891,6 @@ jumbo_source_set("browser") {
"media/capture/cursor_renderer.h",
"media/capture/desktop_capture_device.cc",
"media/capture/desktop_capture_device.h",
- "media/capture/fake_webcontent_capture_machine.cc",
- "media/capture/fake_webcontent_capture_machine.h",
"media/capture/frame_sink_video_capture_device.cc",
"media/capture/frame_sink_video_capture_device.h",
"media/capture/web_contents_video_capture_device.cc",
@@ -1879,14 +1900,10 @@ jumbo_source_set("browser") {
deps += [ "//third_party/webrtc/modules/desktop_capture" ]
if (use_aura) {
sources += [
- "media/capture/aura_window_capture_machine.cc",
- "media/capture/aura_window_capture_machine.h",
"media/capture/aura_window_video_capture_device.cc",
"media/capture/aura_window_video_capture_device.h",
"media/capture/cursor_renderer_aura.cc",
"media/capture/cursor_renderer_aura.h",
- "media/capture/desktop_capture_device_aura.cc",
- "media/capture/desktop_capture_device_aura.h",
]
}
if (is_chromeos) {
@@ -1998,12 +2015,10 @@ jumbo_source_set("browser") {
"renderer_host/pepper/pepper_tcp_socket_message_filter.cc",
"renderer_host/pepper/pepper_tcp_socket_message_filter.h",
"renderer_host/pepper/pepper_truetype_font.h",
- "renderer_host/pepper/pepper_truetype_font_android.cc",
"renderer_host/pepper/pepper_truetype_font_host.cc",
"renderer_host/pepper/pepper_truetype_font_host.h",
"renderer_host/pepper/pepper_truetype_font_linux.cc",
"renderer_host/pepper/pepper_truetype_font_list.h",
- "renderer_host/pepper/pepper_truetype_font_list_android.cc",
"renderer_host/pepper/pepper_truetype_font_list_host.cc",
"renderer_host/pepper/pepper_truetype_font_list_host.h",
"renderer_host/pepper/pepper_truetype_font_list_mac.mm",
@@ -2018,6 +2033,8 @@ jumbo_source_set("browser") {
"renderer_host/pepper/quota_reservation.h",
"renderer_host/pepper/ssl_context_helper.cc",
"renderer_host/pepper/ssl_context_helper.h",
+ "renderer_host/plugin_registry_impl.cc",
+ "renderer_host/plugin_registry_impl.h",
]
deps += [
"//ppapi/host",
@@ -2031,6 +2048,9 @@ jumbo_source_set("browser") {
if (use_pangocairo) {
sources += [ "renderer_host/pepper/pepper_truetype_font_list_pango.cc" ]
}
+ if (is_linux) {
+ deps += [ "//components/services/font:ppapi_fontconfig_matching" ]
+ }
}
if (enable_library_cdms) {
@@ -2086,10 +2106,6 @@ jumbo_source_set("browser") {
"accessibility/web_contents_accessibility_android.h",
"android/content_ui_event_handler.cc",
"android/content_ui_event_handler.h",
- "android/content_view_core.cc",
- "android/content_view_core.h",
- "android/content_view_render_view.cc",
- "android/content_view_render_view.h",
"android/content_view_statics.cc",
"android/date_time_chooser_android.cc",
"android/date_time_chooser_android.h",
@@ -2144,14 +2160,14 @@ jumbo_source_set("browser") {
"android/tracing_controller_android.h",
"android/web_contents_observer_proxy.cc",
"android/web_contents_observer_proxy.h",
- "compositor/in_process_display_client.cc",
- "compositor/in_process_display_client.h",
"frame_host/render_frame_host_android.cc",
"frame_host/render_frame_host_android.h",
"media/capture/screen_capture_device_android.cc",
"media/capture/screen_capture_device_android.h",
"renderer_host/compositor_impl_android.cc",
"renderer_host/compositor_impl_android.h",
+ "renderer_host/input/fling_scheduler_android.cc",
+ "renderer_host/input/fling_scheduler_android.h",
"renderer_host/input/synthetic_gesture_target_android.cc",
"renderer_host/input/synthetic_gesture_target_android.h",
"renderer_host/input/touch_selection_controller_client_manager_android.cc",
@@ -2199,7 +2215,11 @@ jumbo_source_set("browser") {
"//ui/accessibility/mojom",
"//ui/android",
"//ui/compositor",
+ "//ui/compositor/host",
]
+ if (enable_vulkan) {
+ deps += [ "//gpu/vulkan/init" ]
+ }
defines += [
"APPCACHE_USE_SIMPLE_CACHE",
"ENABLE_SCREEN_CAPTURE=1",
@@ -2265,8 +2285,8 @@ jumbo_source_set("browser") {
sources += [
"renderer_host/popup_window_mac.h",
"renderer_host/popup_window_mac.mm",
- "renderer_host/render_widget_host_ns_view_bridge.h",
- "renderer_host/render_widget_host_ns_view_bridge.mm",
+ "renderer_host/render_widget_host_ns_view_bridge_local.h",
+ "renderer_host/render_widget_host_ns_view_bridge_local.mm",
"renderer_host/render_widget_host_ns_view_client.h",
"renderer_host/render_widget_host_view_cocoa.h",
"renderer_host/render_widget_host_view_cocoa.mm",
@@ -2325,8 +2345,6 @@ jumbo_source_set("browser") {
sources += [
"compositor/browser_compositor_output_surface.cc",
"compositor/browser_compositor_output_surface.h",
- "compositor/external_begin_frame_controller_client_impl.cc",
- "compositor/external_begin_frame_controller_client_impl.h",
"compositor/gpu_browser_compositor_output_surface.cc",
"compositor/gpu_browser_compositor_output_surface.h",
"compositor/gpu_output_surface_mac.cc",
@@ -2335,12 +2353,8 @@ jumbo_source_set("browser") {
"compositor/gpu_process_transport_factory.h",
"compositor/gpu_surfaceless_browser_compositor_output_surface.cc",
"compositor/gpu_surfaceless_browser_compositor_output_surface.h",
- "compositor/gpu_vsync_begin_frame_source.cc",
- "compositor/gpu_vsync_begin_frame_source.h",
"compositor/image_transport_factory.cc",
"compositor/image_transport_factory.h",
- "compositor/in_process_display_client.cc",
- "compositor/in_process_display_client.h",
"compositor/offscreen_browser_compositor_output_surface.cc",
"compositor/offscreen_browser_compositor_output_surface.h",
"compositor/owned_mailbox.cc",
@@ -2379,6 +2393,7 @@ jumbo_source_set("browser") {
deps += [
"//components/viz/service",
"//ui/compositor",
+ "//ui/compositor/host",
]
}
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index 59cc7c497cd..afd8cb019fb 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -3,11 +3,13 @@ include_rules = [
# See comment in content/DEPS for which components are allowed.
"+components/discardable_memory/common",
"+components/discardable_memory/service",
- "+components/download/downloader/in_progress",
+ "+components/download/database",
"+components/download/public/common",
"+components/download/quarantine/quarantine.h",
"+components/filename_generation",
+ "+components/services/font",
"+components/services/filesystem",
+ "+components/services/font/ppapi_fontconfig_matching.h",
"+components/services/leveldb",
"+components/link_header_util",
"+components/metrics",
@@ -28,7 +30,6 @@ include_rules = [
"+content/public/browser",
"+device/base/synchronization",
"+device/gamepad", # For gamepad API
- "+device/geolocation/public/cpp",
"+device/nfc",
"+device/vr", # For WebVR API
# This can only be used on POSIX, in particular it mustn't be used on Windows
@@ -61,6 +62,13 @@ include_rules = [
"+chromeos",
"+third_party/cros_system_api",
+ # Limit visibility into Content Service internals.
+ "-services/content",
+ "+services/content/public",
+ "+services/content/navigable_contents_delegate.h",
+ "+services/content/service.h",
+ "+services/content/service_delegate.h",
+
# No inclusion of WebKit from the browser, other than the ones in
# WebKit/public/{mojom,common}, or the ones that are strictly enum/POD,
# header-only types, and some selected common code.
@@ -97,7 +105,7 @@ include_rules = [
"+third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h",
"+third_party/blink/public/platform/modules/indexeddb/web_idb_types.h",
"+third_party/blink/public/platform/modules/notifications/web_notification_constants.h",
- "+third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h",
+ "+third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h",
"+third_party/blink/public/public_buildflags.h",
"+third_party/blink/public/web/web_ax_enums.h",
"+third_party/blink/public/web/web_console_message.h",
diff --git a/chromium/content/browser/OWNERS b/chromium/content/browser/OWNERS
index 76478df0021..223a5fa2d14 100644
--- a/chromium/content/browser/OWNERS
+++ b/chromium/content/browser/OWNERS
@@ -28,8 +28,3 @@ per-file sandbox_host_linux.*=jln@chromium.org
per-file sandbox_host_linux.*=jorgelo@chromium.org
per-file sandbox_ipc_linux.*=jln@chromium.org
per-file sandbox_ipc_linux.*=jorgelo@chromium.org
-
-# LevelDBWrapperImpl used in LocalStorage
-per-file leveldb_wrapper_impl*=mek@chromium.org
-per-file leveldb_wrapper_impl*=dmurph@chromium.org
-per-file leveldb_wrapper_impl*=pwnall@chromium.org
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
index b1f5295d639..a71a156a72e 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
@@ -258,12 +258,13 @@ void AccessibilityEventRecorderWin::OnWinEventHook(
AccessibleStates ia2_state = 0;
Microsoft::WRL::ComPtr<IAccessible2> iaccessible2;
hr = QueryIAccessible2(iaccessible.Get(), iaccessible2.GetAddressOf());
+ bool has_ia2 = SUCCEEDED(hr) && iaccessible2;
base::string16 html_tag;
base::string16 obj_class;
base::string16 html_id;
- if (SUCCEEDED(hr)) {
+ if (has_ia2) {
iaccessible2->get_states(&ia2_state);
base::win::ScopedBstr attributes_bstr;
if (S_OK == iaccessible2->get_attributes(attributes_bstr.Receive())) {
@@ -307,6 +308,19 @@ void AccessibilityEventRecorderWin::OnWinEventHook(
log += " ";
log += base::UTF16ToUTF8(IAccessible2StateToString(ia2_state));
+ // Group position, e.g. L3, 5 of 7
+ LONG group_level, similar_items_in_group, position_in_group;
+ if (has_ia2 &&
+ iaccessible2->get_groupPosition(&group_level, &similar_items_in_group,
+ &position_in_group) == S_OK) {
+ if (group_level)
+ log += base::StringPrintf(" level=%ld", group_level);
+ if (similar_items_in_group) {
+ log += base::StringPrintf(" %ld of %ld", position_in_group,
+ similar_items_in_group);
+ }
+ }
+
// For TEXT_REMOVED and TEXT_INSERTED events, query the text that was
// inserted or removed and include that in the log.
Microsoft::WRL::ComPtr<IAccessibleText> accessible_text;
diff --git a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
index a85dba33883..c91e712b57c 100644
--- a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -159,9 +159,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
// Construct a bad accessibility message that BrowserAccessibilityManager
// will reject.
- std::vector<AXEventNotificationDetails> bad_accessibility_event_list;
- bad_accessibility_event_list.push_back(AXEventNotificationDetails());
- bad_accessibility_event_list[0].update.node_id_to_clear = -2;
+ AXEventNotificationDetails bad_accessibility_event;
+ bad_accessibility_event.updates.resize(1);
+ bad_accessibility_event.updates[0].node_id_to_clear = -2;
// We should be able to reset accessibility |max_iterations-1| times
// (see render_frame_host_impl.cc - kMaxAccessibilityResets),
@@ -172,7 +172,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
// Send the browser accessibility the bad message.
BrowserAccessibilityManager* manager =
frame->GetOrCreateBrowserAccessibilityManager();
- manager->OnAccessibilityEvents(bad_accessibility_event_list);
+ manager->OnAccessibilityEvents(bad_accessibility_event);
// Now the frame should have deleted the BrowserAccessibilityManager.
ASSERT_EQ(nullptr, frame->browser_accessibility_manager());
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
index d5cfe4df644..5236a97ee06 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
@@ -107,16 +107,20 @@ bool AccessibilityTreeFormatter::MatchesFilters(
const std::vector<Filter>& filters,
const base::string16& text,
bool default_result) {
- std::vector<Filter>::const_iterator iter = filters.begin();
bool allow = default_result;
- for (iter = filters.begin(); iter != filters.end(); ++iter) {
- if (base::MatchPattern(text, iter->match_str)) {
- if (iter->type == Filter::ALLOW_EMPTY)
- allow = true;
- else if (iter->type == Filter::ALLOW)
- allow = (!base::MatchPattern(text, base::UTF8ToUTF16("*=''")));
- else
- allow = false;
+ for (const auto& filter : filters) {
+ if (base::MatchPattern(text, filter.match_str)) {
+ switch (filter.type) {
+ case Filter::ALLOW_EMPTY:
+ allow = true;
+ break;
+ case Filter::ALLOW:
+ allow = (!base::MatchPattern(text, base::UTF8ToUTF16("*=''")));
+ break;
+ case Filter::DENY:
+ allow = false;
+ break;
+ }
}
}
return allow;
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index 1402f8eb016..a63ae0b7b07 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -170,6 +170,8 @@ NSArray* BuildAllAttributesArray() {
@"AXARIARowIndex",
@"AXARIASetSize",
@"AXARIAPosInSet",
+ @"AXAutocomplete",
+ @"AXAutocompleteValue",
NSAccessibilityColumnHeaderUIElementsAttribute,
NSAccessibilityColumnIndexRangeAttribute,
@"AXDOMIdentifier",
@@ -177,9 +179,12 @@ NSArray* BuildAllAttributesArray() {
@"AXEditableAncestor",
NSAccessibilityEnabledAttribute,
NSAccessibilityExpandedAttribute,
+ @"AXFocusableAncestor",
NSAccessibilityFocusedAttribute,
@"AXGrabbed",
NSAccessibilityHeaderAttribute,
+ @"AXHasPopup",
+ @"AXHasPopupValue",
@"AXHighestEditableAncestor",
NSAccessibilityIndexAttribute,
@"AXLanguage",
@@ -192,6 +197,7 @@ NSArray* BuildAllAttributesArray() {
@"AXRequired",
NSAccessibilityRowHeaderUIElementsAttribute,
NSAccessibilityRowIndexRangeAttribute,
+ NSAccessibilitySelectedAttribute,
NSAccessibilitySelectedChildrenAttribute,
NSAccessibilityTitleUIElementAttribute,
NSAccessibilityURLAttribute,
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
index f5281e28968..a54957c628f 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
@@ -131,7 +131,10 @@ CONTENT_EXPORT base::string16 IAccessible2RoleToString(int32_t ia2_role) {
QUOTE(IA2_ROLE_VIEW_PORT),
QUOTE(IA2_ROLE_COMPLEMENTARY_CONTENT),
QUOTE(IA2_ROLE_LANDMARK),
- QUOTE(IA2_ROLE_LEVEL_BAR)};
+ QUOTE(IA2_ROLE_LEVEL_BAR),
+ QUOTE(IA2_ROLE_CONTENT_DELETION),
+ QUOTE(IA2_ROLE_CONTENT_INSERTION),
+ };
return GetNameForPlatformConstant(ia2_table, arraysize(ia2_table), ia2_role);
}
diff --git a/chromium/content/browser/accessibility/accessibility_ui.cc b/chromium/content/browser/accessibility/accessibility_ui.cc
index 945acc066ab..4dada7363d2 100644
--- a/chromium/content/browser/accessibility/accessibility_ui.cc
+++ b/chromium/content/browser/accessibility/accessibility_ui.cc
@@ -39,6 +39,7 @@
#include "content/public/common/url_constants.h"
#include "net/base/escape.h"
#include "ui/accessibility/platform/ax_platform_node.h"
+#include "ui/base/webui/web_ui_util.h"
static const char kTargetsDataFile[] = "targets-data.json";
@@ -105,8 +106,13 @@ std::unique_ptr<base::DictionaryValue> BuildTargetDescriptor(
title = base::UTF16ToUTF8(web_contents->GetTitle());
NavigationController& controller = web_contents->GetController();
NavigationEntry* entry = controller.GetVisibleEntry();
- if (entry != nullptr && entry->GetURL().is_valid())
- favicon_url = entry->GetFavicon().url;
+ if (entry != nullptr && entry->GetURL().is_valid()) {
+ gfx::Image favicon_image = entry->GetFavicon().image;
+ if (!favicon_image.IsEmpty()) {
+ const SkBitmap* favicon_bitmap = favicon_image.ToSkBitmap();
+ favicon_url = GURL(webui::GetBitmapDataUrl(*favicon_bitmap));
+ }
+ }
accessibility_mode = web_contents->GetAccessibilityMode();
}
@@ -131,7 +137,7 @@ bool HandleAccessibilityRequestCallback(
while (RenderWidgetHost* widget = widgets->GetNextHost()) {
// Ignore processes that don't have a connection, such as crashed tabs.
- if (!widget->GetProcess()->HasConnection())
+ if (!widget->GetProcess()->IsInitializedAndNotDead())
continue;
RenderViewHost* rvh = RenderViewHost::From(widget);
if (!rvh)
diff --git a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
index 089946e6c50..4ab51921d62 100644
--- a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -192,7 +192,7 @@ void AccessibilityWinBrowserTest::SetUpScrollableInputField(
R"HTML(<!DOCTYPE html>
<html>
<body>
- <input type="text" style="width: 30px;" value=")HTML") +
+ <input type="text" style="width: 150px;" value=")HTML") +
net::EscapeForHTML(kInputContents) +
std::string(R"HTML(">
</body>
@@ -240,7 +240,9 @@ void AccessibilityWinBrowserTest::SetUpInputFieldHelper(
ExecuteScript(std::wstring(L"let textField = document.querySelector('input');"
L"textField.focus();"
L"textField.setSelectionRange(") +
- caret_offset + L"," + caret_offset + L");");
+ caret_offset + L"," + caret_offset +
+ L");"
+ L"textField.scrollLeft = 1000;");
waiter.WaitForNotification();
}
@@ -1314,11 +1316,11 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
- DISABLED_TestCharacterExtentsInScrollableInputField) {
+ TestCharacterExtentsInScrollableInputField) {
Microsoft::WRL::ComPtr<IAccessibleText> input_text;
SetUpScrollableInputField(&input_text);
- constexpr LONG visible_characters_start = 20;
+ constexpr LONG visible_characters_start = 21;
LONG n_characters;
ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
ASSERT_EQ(kContentsLength, n_characters);
@@ -1338,7 +1340,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// of 0 is not used because it signifies an invalid size.
EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
0, coordinate_type, &x, &y, &width, &height));
- EXPECT_LT(0, x) << "at offset 0";
+ EXPECT_LT(0, x + width) << "at offset 0";
EXPECT_LT(0, y) << "at offset 0";
EXPECT_EQ(1, width) << "at offset 0";
EXPECT_LT(1, height) << "at offset 0";
@@ -1346,7 +1348,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Test that characters at the start of the input field are offscreen by
// checking that their x coordinate is at the start of the field and their
// width is 1.
- for (LONG offset = 1; offset < visible_characters_start; ++offset) {
+ // Exclude the character that is partly visible.
+ for (LONG offset = 1; offset < (visible_characters_start - 1); ++offset) {
previous_x = x;
previous_y = y;
previous_height = height;
@@ -1356,7 +1359,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_EQ(previous_x, x) << "at offset " << offset;
EXPECT_EQ(previous_y, y) << "at offset " << offset;
EXPECT_EQ(1, width) << "at offset " << offset;
- EXPECT_LT(previous_height, height) << "at offset " << offset;
+ EXPECT_EQ(previous_height, height) << "at offset " << offset;
}
// Test that non offscreen characters have increasing x coordinates and a
@@ -1369,8 +1372,10 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_EQ(previous_height, height)
<< "at offset " << visible_characters_start;
- for (LONG offset = visible_characters_start + 1; offset < n_characters;
- ++offset) {
+ // Exclude the dot at the end of the text field, because it has a width of
+ // one anyway.
+ for (LONG offset = visible_characters_start + 1;
+ offset < (n_characters - 1); ++offset) {
previous_x = x;
previous_y = y;
previous_height = height;
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index 64868046c9a..68e62b1db86 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -426,47 +426,52 @@ gfx::Rect BrowserAccessibility::GetPageBoundsForRange(int start, int len)
local_start > 0 ? character_offsets[local_start - 1] : 0;
int end_pixel_offset =
local_end > 0 ? character_offsets[local_end - 1] : 0;
+ int max_pixel_offset = character_offsets_length > 0
+ ? character_offsets[character_offsets_length - 1]
+ : 0;
- gfx::Rect child_rect = child->GetPageBoundsRect();
auto text_direction = static_cast<ax::mojom::TextDirection>(
child->GetIntAttribute(ax::mojom::IntAttribute::kTextDirection));
- gfx::Rect child_overlap_rect;
+ gfx::RectF child_overlap_rect;
switch (text_direction) {
case ax::mojom::TextDirection::kNone:
case ax::mojom::TextDirection::kLtr: {
- int left = child_rect.x() + start_pixel_offset;
- int right = child_rect.x() + end_pixel_offset;
- child_overlap_rect = gfx::Rect(left, child_rect.y(),
- right - left, child_rect.height());
+ int height = child->GetLocation().height();
+ child_overlap_rect =
+ gfx::RectF(start_pixel_offset, 0,
+ end_pixel_offset - start_pixel_offset, height);
break;
}
case ax::mojom::TextDirection::kRtl: {
- int right = child_rect.right() - start_pixel_offset;
- int left = child_rect.right() - end_pixel_offset;
- child_overlap_rect = gfx::Rect(left, child_rect.y(),
- right - left, child_rect.height());
+ int right = max_pixel_offset - start_pixel_offset;
+ int left = max_pixel_offset - end_pixel_offset;
+ int height = child->GetLocation().height();
+ child_overlap_rect = gfx::RectF(left, 0, right - left, height);
break;
}
case ax::mojom::TextDirection::kTtb: {
- int top = child_rect.y() + start_pixel_offset;
- int bottom = child_rect.y() + end_pixel_offset;
- child_overlap_rect = gfx::Rect(child_rect.x(), top,
- child_rect.width(), bottom - top);
+ int width = child->GetLocation().width();
+ child_overlap_rect = gfx::RectF(0, start_pixel_offset, width,
+ end_pixel_offset - start_pixel_offset);
break;
}
case ax::mojom::TextDirection::kBtt: {
- int bottom = child_rect.bottom() - start_pixel_offset;
- int top = child_rect.bottom() - end_pixel_offset;
- child_overlap_rect = gfx::Rect(child_rect.x(), top,
- child_rect.width(), bottom - top);
+ int bottom = max_pixel_offset - start_pixel_offset;
+ int top = max_pixel_offset - end_pixel_offset;
+ int width = child->GetLocation().width();
+ child_overlap_rect = gfx::RectF(0, top, width, bottom - top);
break;
}
}
- if (bounds.width() == 0 && bounds.height() == 0)
- bounds = child_overlap_rect;
- else
- bounds.Union(child_overlap_rect);
+ gfx::Rect absolute_child_rect = child->RelativeToAbsoluteBounds(
+ child_overlap_rect, false /* frame_only */, nullptr /* offscreen */,
+ true /* clip_bounds */);
+ if (bounds.width() == 0 && bounds.height() == 0) {
+ bounds = absolute_child_rect;
+ } else {
+ bounds.Union(absolute_child_rect);
+ }
}
return bounds;
@@ -974,26 +979,54 @@ int BrowserAccessibility::GetTableColCount() const {
return table_info->col_count;
}
+std::vector<int32_t> BrowserAccessibility::GetColHeaderNodeIds() const {
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (!table_info)
+ return {};
+
+ std::vector<std::vector<int32_t>> headers = table_info->col_headers;
+ std::vector<int32_t> all_ids;
+ for (const auto& col_ids : headers) {
+ all_ids.insert(all_ids.end(), col_ids.begin(), col_ids.end());
+ }
+
+ return all_ids;
+}
+
std::vector<int32_t> BrowserAccessibility::GetColHeaderNodeIds(
int32_t col_index) const {
ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
if (!table_info)
- return std::vector<int32_t>();
+ return {};
if (col_index < 0 || col_index >= table_info->col_count)
- return std::vector<int32_t>();
+ return {};
return table_info->col_headers[col_index];
}
+std::vector<int32_t> BrowserAccessibility::GetRowHeaderNodeIds() const {
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (!table_info)
+ return {};
+
+ std::vector<std::vector<int32_t>> headers = table_info->row_headers;
+ std::vector<int32_t> all_ids;
+ for (const auto& col_ids : headers) {
+ all_ids.insert(all_ids.end(), col_ids.begin(), col_ids.end());
+ }
+
+ return all_ids;
+}
+
std::vector<int32_t> BrowserAccessibility::GetRowHeaderNodeIds(
int32_t row_index) const {
ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
if (!table_info)
- return std::vector<int32_t>();
+ return {};
if (row_index < 0 || row_index >= table_info->row_count)
- return std::vector<int32_t>();
+ return {};
return table_info->row_headers[row_index];
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index 83f78a21604..f3d85b39061 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -73,7 +73,7 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
// caller.
static BrowserAccessibility* Create();
- virtual ~BrowserAccessibility();
+ ~BrowserAccessibility() override;
// Called only once, immediately after construction. The constructor doesn't
// take any arguments because in the Windows subclass we use a special
@@ -116,11 +116,11 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
// Returns the number of children of this object, or 0 if PlatformIsLeaf()
// returns true.
- uint32_t PlatformChildCount() const;
+ virtual uint32_t PlatformChildCount() const;
// Return a pointer to the child at the given index, or NULL for an
// invalid index. Returns NULL if PlatformIsLeaf() returns true.
- BrowserAccessibility* PlatformGetChild(uint32_t child_index) const;
+ virtual BrowserAccessibility* PlatformGetChild(uint32_t child_index) const;
// Returns true if an ancestor of this node (not including itself) is a
// leaf node, meaning that this node is not actually exposed to the
@@ -343,7 +343,9 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
int GetTableRowCount() const override;
int GetTableColCount() const override;
+ std::vector<int32_t> GetColHeaderNodeIds() const override;
std::vector<int32_t> GetColHeaderNodeIds(int32_t col_index) const override;
+ std::vector<int32_t> GetRowHeaderNodeIds() const override;
std::vector<int32_t> GetRowHeaderNodeIds(int32_t row_index) const override;
int32_t GetCellId(int32_t row_index, int32_t col_index) const override;
int32_t CellIdToIndex(int32_t cell_id) const override;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index 0bce59cad23..3dd224bd18d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -18,6 +18,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "ui/accessibility/ax_assistant_structure.h"
#include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_table_info.h"
#include "ui/accessibility/platform/ax_android_constants.h"
#include "ui/accessibility/platform/ax_unique_id.h"
@@ -510,7 +511,7 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
// No role description.
break;
case ax::mojom::Role::kCell:
- message_id = IDS_AX_ROLE_CELL;
+ // No role description.
break;
case ax::mojom::Role::kCheckBox:
message_id = IDS_AX_ROLE_CHECK_BOX;
@@ -536,6 +537,12 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ax::mojom::Role::kComplementary:
message_id = IDS_AX_ROLE_COMPLEMENTARY;
break;
+ case ax::mojom::Role::kContentDeletion:
+ message_id = IDS_AX_ROLE_CONTENT_DELETION;
+ break;
+ case ax::mojom::Role::kContentInsertion:
+ message_id = IDS_AX_ROLE_CONTENT_INSERTION;
+ break;
case ax::mojom::Role::kContentInfo:
message_id = IDS_AX_ROLE_CONTENT_INFO;
break;
@@ -787,9 +794,6 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ax::mojom::Role::kList:
// No role description.
break;
- case ax::mojom::Role::kLocationBar:
- // No role description.
- break;
case ax::mojom::Role::kLog:
message_id = IDS_AX_ROLE_LOG;
break;
@@ -1320,7 +1324,9 @@ int BrowserAccessibilityAndroid::AndroidRangeType() const {
int BrowserAccessibilityAndroid::RowCount() const {
if (ui::IsTableLikeRole(GetRole())) {
- return CountChildrenWithRole(ax::mojom::Role::kRow);
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (table_info)
+ return table_info->row_count;
}
if (GetRole() == ax::mojom::Role::kList ||
@@ -1335,7 +1341,9 @@ int BrowserAccessibilityAndroid::RowCount() const {
int BrowserAccessibilityAndroid::ColumnCount() const {
if (ui::IsTableLikeRole(GetRole())) {
- return CountChildrenWithRole(ax::mojom::Role::kColumn);
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (table_info)
+ return table_info->col_count;
}
return 0;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
index a03585269db..44c85b5ad57 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -35,7 +35,7 @@ struct AXTextEdit {
// This class converts it into a format Cocoa can query.
@interface BrowserAccessibilityCocoa : NSObject {
@private
- content::BrowserAccessibility* browserAccessibility_;
+ content::BrowserAccessibility* owner_;
base::scoped_nsobject<NSMutableArray> children_;
// Stores the previous value of an edit field.
base::string16 oldValue_;
@@ -62,7 +62,7 @@ struct AXTextEdit {
- (content::BrowserAccessibilityDelegate*)delegate;
// Get the BrowserAccessibility that this object wraps.
-- (content::BrowserAccessibility*)browserAccessibility;
+- (content::BrowserAccessibility*)owner;
// Computes the text that was added or deleted in a text field after an edit.
- (content::AXTextEdit)computeTextEdit;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index bc4b972f9c7..07e9862b76a 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -30,6 +30,7 @@
#include "ui/accessibility/ax_range.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/ax_table_info.h"
+#include "ui/accessibility/platform/ax_platform_node.h"
#import "ui/accessibility/platform/ax_platform_node_mac.h"
@@ -65,12 +66,17 @@ NSString* const NSAccessibilityARIARowCountAttribute = @"AXARIARowCount";
NSString* const NSAccessibilityARIARowIndexAttribute = @"AXARIARowIndex";
NSString* const NSAccessibilityARIASetSizeAttribute = @"AXARIASetSize";
NSString* const NSAccessibilityAccessKeyAttribute = @"AXAccessKey";
+NSString* const NSAccessibilityAutocompleteValueAttribute =
+ @"AXAutocompleteValue";
NSString* const NSAccessibilityDOMIdentifierAttribute = @"AXDOMIdentifier";
NSString* const NSAccessibilityDropEffectsAttribute = @"AXDropEffects";
NSString* const NSAccessibilityEditableAncestorAttribute =
@"AXEditableAncestor";
+NSString* const NSAccessibilityFocusableAncestorAttribute =
+ @"AXFocusableAncestor";
NSString* const NSAccessibilityGrabbedAttribute = @"AXGrabbed";
NSString* const NSAccessibilityHasPopupAttribute = @"AXHasPopup";
+NSString* const NSAccessibilityHasPopupValueAttribute = @"AXHasPopupValue";
NSString* const NSAccessibilityHighestEditableAncestorAttribute =
@"AXHighestEditableAncestor";
NSString* const NSAccessibilityInvalidAttribute = @"AXInvalid";
@@ -112,6 +118,13 @@ NSString* const NSAccessibilityTextMarkerRangeForUnorderedTextMarkersParameteriz
@"AXTextMarkerRangeForUnorderedTextMarkers";
NSString* const NSAccessibilityIndexForChildUIElementParameterizedAttribute =
@"AXIndexForChildUIElement";
+NSString* const NSAccessibilityValueAutofillAvailableAttribute =
+ @"AXValueAutofillAvailable";
+// Not currently supported by Chrome -- information not stored:
+// NSString* const NSAccessibilityValueAutofilledAttribute =
+// @"AXValueAutofilled"; Not currently supported by Chrome -- mismatch of types
+// supported: NSString* const NSAccessibilityValueAutofillTypeAttribute =
+// @"AXValueAutofillType";
// Actions.
NSString* const NSAccessibilityScrollToVisibleAction = @"AXScrollToVisible";
@@ -460,7 +473,7 @@ bool InitializeAccessibilityTreeSearch(
if ([startElementParameter isKindOfClass:[BrowserAccessibilityCocoa class]]) {
BrowserAccessibilityCocoa* startNodeCocoa =
(BrowserAccessibilityCocoa*)startElementParameter;
- search->SetStartNode([startNodeCocoa browserAccessibility]);
+ search->SetStartNode([startNodeCocoa owner]);
}
bool immediateDescendantsOnly = false;
@@ -567,6 +580,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
{NSAccessibilityARIARowIndexAttribute, @"ariaRowIndex"},
{NSAccessibilityARIASetSizeAttribute, @"ariaSetSize"},
{NSAccessibilityAccessKeyAttribute, @"accessKey"},
+ {NSAccessibilityAutocompleteValueAttribute, @"autocompleteValue"},
{NSAccessibilityChildrenAttribute, @"children"},
{NSAccessibilityColumnsAttribute, @"columns"},
{NSAccessibilityColumnHeaderUIElementsAttribute, @"columnHeaders"},
@@ -583,10 +597,12 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
{NSAccessibilityEnabledAttribute, @"enabled"},
{NSAccessibilityEndTextMarkerAttribute, @"endTextMarker"},
{NSAccessibilityExpandedAttribute, @"expanded"},
+ {NSAccessibilityFocusableAncestorAttribute, @"focusableAncestor"},
{NSAccessibilityFocusedAttribute, @"focused"},
{NSAccessibilityGrabbedAttribute, @"grabbed"},
{NSAccessibilityHeaderAttribute, @"header"},
{NSAccessibilityHasPopupAttribute, @"hasPopup"},
+ {NSAccessibilityHasPopupValueAttribute, @"hasPopupValue"},
{NSAccessibilityHelpAttribute, @"help"},
{NSAccessibilityHighestEditableAncestorAttribute,
@"highestEditableAncestor"},
@@ -630,6 +646,12 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
{NSAccessibilityTopLevelUIElementAttribute, @"window"},
{NSAccessibilityURLAttribute, @"url"},
{NSAccessibilityValueAttribute, @"value"},
+ {NSAccessibilityValueAutofillAvailableAttribute,
+ @"valueAutofillAvailable"},
+ // Not currently supported by Chrome -- information not stored:
+ // {NSAccessibilityValueAutofilledAttribute, @"valueAutofilled"},
+ // Not currently supported by Chrome -- mismatch of types supported:
+ // {NSAccessibilityValueAutofillTypeAttribute, @"valueAutofillType"},
{NSAccessibilityValueDescriptionAttribute, @"valueDescription"},
{NSAccessibilityVisibleCharacterRangeAttribute, @"visibleCharacterRange"},
{NSAccessibilityVisibleCellsAttribute, @"visibleCells"},
@@ -654,57 +676,57 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (instancetype)initWithObject:(BrowserAccessibility*)accessibility {
if ((self = [super init]))
- browserAccessibility_ = accessibility;
+ owner_ = accessibility;
return self;
}
- (void)detach {
- if (!browserAccessibility_)
+ if (!owner_)
return;
NSAccessibilityPostNotification(
self, NSAccessibilityUIElementDestroyedNotification);
- browserAccessibility_ = nullptr;
+ owner_ = nullptr;
}
- (NSString*)accessKey {
if (![self instanceActive])
return nil;
- return NSStringForStringAttribute(browserAccessibility_,
+ return NSStringForStringAttribute(owner_,
ax::mojom::StringAttribute::kAccessKey);
}
- (NSNumber*)ariaAtomic {
if (![self instanceActive])
return nil;
- bool boolValue = browserAccessibility_->GetBoolAttribute(
- ax::mojom::BoolAttribute::kLiveAtomic);
+ bool boolValue =
+ owner_->GetBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic);
return [NSNumber numberWithBool:boolValue];
}
- (NSNumber*)ariaBusy {
if (![self instanceActive])
return nil;
- return [NSNumber numberWithBool:browserAccessibility_->GetBoolAttribute(
- ax::mojom::BoolAttribute::kBusy)];
+ return [NSNumber
+ numberWithBool:owner_->GetBoolAttribute(ax::mojom::BoolAttribute::kBusy)];
}
- (NSNumber*)ariaColumnCount {
- if (!ui::IsTableLikeRole(browserAccessibility_->GetRole()))
+ if (!ui::IsTableLikeRole(owner_->GetRole()))
return nil;
int count = -1;
- if (!browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kAriaColumnCount, &count)) {
+ if (!owner_->GetIntAttribute(ax::mojom::IntAttribute::kAriaColumnCount,
+ &count)) {
return nil;
}
return [NSNumber numberWithInt:count];
}
- (NSNumber*)ariaColumnIndex {
- if (!ui::IsCellOrTableHeaderRole(browserAccessibility_->GetRole()))
+ if (!ui::IsCellOrTableHeaderRole(owner_->GetRole()))
return nil;
int index = -1;
- if (!browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kAriaCellColumnIndex, &index)) {
+ if (!owner_->GetIntAttribute(ax::mojom::IntAttribute::kAriaCellColumnIndex,
+ &index)) {
return nil;
}
return [NSNumber numberWithInt:index];
@@ -713,41 +735,41 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSString*)ariaLive {
if (![self instanceActive])
return nil;
- return NSStringForStringAttribute(browserAccessibility_,
+ return NSStringForStringAttribute(owner_,
ax::mojom::StringAttribute::kLiveStatus);
}
- (NSNumber*)ariaPosInSet {
if (![self instanceActive])
return nil;
- return [NSNumber numberWithInt:browserAccessibility_->GetIntAttribute(
+ return [NSNumber numberWithInt:owner_->GetIntAttribute(
ax::mojom::IntAttribute::kPosInSet)];
}
- (NSString*)ariaRelevant {
if (![self instanceActive])
return nil;
- return NSStringForStringAttribute(browserAccessibility_,
+ return NSStringForStringAttribute(owner_,
ax::mojom::StringAttribute::kLiveRelevant);
}
- (NSNumber*)ariaRowCount {
- if (!ui::IsTableLikeRole(browserAccessibility_->GetRole()))
+ if (!ui::IsTableLikeRole(owner_->GetRole()))
return nil;
int count = -1;
- if (!browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kAriaRowCount, &count)) {
+ if (!owner_->GetIntAttribute(ax::mojom::IntAttribute::kAriaRowCount,
+ &count)) {
return nil;
}
return [NSNumber numberWithInt:count];
}
- (NSNumber*)ariaRowIndex {
- if (!ui::IsCellOrTableHeaderRole(browserAccessibility_->GetRole()))
+ if (!ui::IsCellOrTableHeaderRole(owner_->GetRole()))
return nil;
int index = -1;
- if (!browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kAriaCellRowIndex, &index)) {
+ if (!owner_->GetIntAttribute(ax::mojom::IntAttribute::kAriaCellRowIndex,
+ &index)) {
return nil;
}
return [NSNumber numberWithInt:index];
@@ -756,8 +778,15 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)ariaSetSize {
if (![self instanceActive])
return nil;
- return [NSNumber numberWithInt:browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kSetSize)];
+ return [NSNumber
+ numberWithInt:owner_->GetIntAttribute(ax::mojom::IntAttribute::kSetSize)];
+}
+
+- (NSString*)autocompleteValue {
+ if (![self instanceActive])
+ return nil;
+ return NSStringForStringAttribute(owner_,
+ ax::mojom::StringAttribute::kAutoComplete);
}
// Returns an array of BrowserAccessibilityCocoa objects, representing the
@@ -768,12 +797,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if ([self internalRole] == ax::mojom::Role::kLayoutTableColumn)
return nil;
if (!children_) {
- uint32_t childCount = browserAccessibility_->PlatformChildCount();
+ uint32_t childCount = owner_->PlatformChildCount();
children_.reset([[NSMutableArray alloc] initWithCapacity:childCount]);
for (uint32_t index = 0; index < childCount; ++index) {
BrowserAccessibilityCocoa* child =
- ToBrowserAccessibilityCocoa(
- browserAccessibility_->PlatformGetChild(index));
+ ToBrowserAccessibilityCocoa(owner_->PlatformGetChild(index));
if ([child isIgnored])
[children_ addObjectsFromArray:[child children]];
else
@@ -781,13 +809,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
}
// Also, add indirect children (if any).
- const std::vector<int32_t>& indirectChildIds =
- browserAccessibility_->GetIntListAttribute(
- ax::mojom::IntListAttribute::kIndirectChildIds);
+ const std::vector<int32_t>& indirectChildIds = owner_->GetIntListAttribute(
+ ax::mojom::IntListAttribute::kIndirectChildIds);
for (uint32_t i = 0; i < indirectChildIds.size(); ++i) {
int32_t child_id = indirectChildIds[i];
- BrowserAccessibility* child =
- browserAccessibility_->manager()->GetFromID(child_id);
+ BrowserAccessibility* child = owner_->manager()->GetFromID(child_id);
// This only became necessary as a result of crbug.com/93095. It should be
// a DCHECK in the future.
@@ -807,24 +833,23 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self isIgnored]) {
children_.reset();
} else {
- [ToBrowserAccessibilityCocoa(browserAccessibility_->PlatformGetParent())
- childrenChanged];
+ [ToBrowserAccessibilityCocoa(owner_->PlatformGetParent()) childrenChanged];
}
}
- (BOOL)isColumnHeaderForCurrentCell:(BrowserAccessibility*)header {
int cell_first_col = -1;
int cell_colspan = -1;
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kAriaCellColumnIndex, &cell_first_col);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kAriaCellColumnIndex,
+ &cell_first_col);
if (cell_first_col < 0) {
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableCellColumnIndex, &cell_first_col);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableCellColumnIndex,
+ &cell_first_col);
}
if (cell_first_col < 0)
return false;
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableCellColumnSpan, &cell_colspan);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableCellColumnSpan,
+ &cell_colspan);
if (cell_colspan <= 0)
cell_colspan = 1;
int cell_last_col = cell_first_col + cell_colspan - 1;
@@ -857,9 +882,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
- bool is_cell_or_table_header =
- ui::IsCellOrTableHeaderRole(browserAccessibility_->GetRole());
- bool is_table_like = ui::IsTableLikeRole(browserAccessibility_->GetRole());
+ bool is_cell_or_table_header = ui::IsCellOrTableHeaderRole(owner_->GetRole());
+ bool is_table_like = ui::IsTableLikeRole(owner_->GetRole());
if (!is_table_like && !is_cell_or_table_header)
return nil;
BrowserAccessibility* table = [self containingTable];
@@ -877,21 +901,19 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
std::inserter(headerIds, headerIds.end()));
}
for (int32_t id : headerIds) {
- BrowserAccessibility* cell =
- browserAccessibility_->manager()->GetFromID(id);
+ BrowserAccessibility* cell = owner_->manager()->GetFromID(id);
if (cell)
[ret addObject:ToBrowserAccessibilityCocoa(cell)];
}
} else {
// Otherwise this is a cell, return the column headers for this cell.
int column = -1;
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableCellColumnIndex, &column);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableCellColumnIndex,
+ &column);
std::vector<int32_t> colHeaderIds = table->GetColHeaderNodeIds(column);
for (int32_t id : colHeaderIds) {
- BrowserAccessibility* cell =
- browserAccessibility_->manager()->GetFromID(id);
+ BrowserAccessibility* cell = owner_->manager()->GetFromID(id);
if (cell)
[ret addObject:ToBrowserAccessibilityCocoa(cell)];
}
@@ -903,15 +925,15 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSValue*)columnIndexRange {
if (![self instanceActive])
return nil;
- if (!ui::IsCellOrTableHeaderRole(browserAccessibility_->GetRole()))
+ if (!ui::IsCellOrTableHeaderRole(owner_->GetRole()))
return nil;
int column = -1;
int colspan = -1;
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableCellColumnIndex, &column);
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableCellColumnSpan, &colspan);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableCellColumnIndex,
+ &column);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableCellColumnSpan,
+ &colspan);
if (column >= 0 && colspan >= 1)
return [NSValue valueWithRange:NSMakeRange(column, colspan)];
return nil;
@@ -929,7 +951,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
}
- (BrowserAccessibility*)containingTable {
- BrowserAccessibility* table = browserAccessibility_;
+ BrowserAccessibility* table = owner_;
while (table && !ui::IsTableLikeRole(table->GetRole())) {
table = table->PlatformGetParent();
}
@@ -949,18 +971,21 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if ([self shouldExposeTitleUIElement])
return @"";
- ax::mojom::NameFrom nameFrom =
- static_cast<ax::mojom::NameFrom>(browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kNameFrom));
- std::string name = browserAccessibility_->GetStringAttribute(
- ax::mojom::StringAttribute::kName);
+ ax::mojom::NameFrom nameFrom = static_cast<ax::mojom::NameFrom>(
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kNameFrom));
+ std::string name =
+ owner_->GetStringAttribute(ax::mojom::StringAttribute::kName);
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
// otherwise, but never both.
- if (nameFrom == ax::mojom::NameFrom::kContents ||
- nameFrom == ax::mojom::NameFrom::kRelatedElement ||
- nameFrom == ax::mojom::NameFrom::kValue) {
+
+ // Group, radiogroup etc.
+ if ([self shouldExposeNameInDescription]) {
+ return base::SysUTF8ToNSString(name);
+ } else if (nameFrom == ax::mojom::NameFrom::kContents ||
+ nameFrom == ax::mojom::NameFrom::kRelatedElement ||
+ nameFrom == ax::mojom::NameFrom::kValue) {
return @"";
} else {
return base::SysUTF8ToNSString(name);
@@ -974,8 +999,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return @"";
std::string url;
- if (browserAccessibility_->GetStringAttribute(
- ax::mojom::StringAttribute::kUrl, &url)) {
+ if (owner_->GetStringAttribute(ax::mojom::StringAttribute::kUrl, &url)) {
// Given a url like http://foo.com/bar/baz.png, just return the
// base name, e.g., "baz.png".
size_t leftIndex = url.rfind('/');
@@ -987,14 +1011,14 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// If it's focusable but didn't have any other name or value, compute a name
// from its descendants.
- base::string16 value = browserAccessibility_->GetValue();
- if (browserAccessibility_->HasState(ax::mojom::State::kFocusable) &&
- !ui::IsControl(browserAccessibility_->GetRole()) && value.empty() &&
+ base::string16 value = owner_->GetValue();
+ if (owner_->HasState(ax::mojom::State::kFocusable) &&
+ !ui::IsControl(owner_->GetRole()) && value.empty() &&
[self internalRole] != ax::mojom::Role::kDateTime &&
[self internalRole] != ax::mojom::Role::kWebArea &&
[self internalRole] != ax::mojom::Role::kRootWebArea) {
return base::SysUTF8ToNSString(
- browserAccessibility_->ComputeAccessibleNameFromDescendants());
+ owner_->ComputeAccessibleNameFromDescendants());
}
return @"";
@@ -1004,8 +1028,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
if ([self internalRole] == ax::mojom::Role::kTreeItem) {
- return [NSNumber numberWithBool:GetState(browserAccessibility_,
- ax::mojom::State::kExpanded)];
+ return
+ [NSNumber numberWithBool:GetState(owner_, ax::mojom::State::kExpanded)];
} else {
return nil;
}
@@ -1025,8 +1049,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
ax::mojom::Role role = [self internalRole];
if (role == ax::mojom::Role::kRow || role == ax::mojom::Role::kTreeItem) {
- int level = browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kHierarchicalLevel);
+ int level =
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel);
// Mac disclosureLevel is 0-based, but web levels are 1-based.
if (level > 0)
level--;
@@ -1049,7 +1073,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
std::string dropEffects;
- if (browserAccessibility_->GetHtmlAttribute("aria-dropeffect", &dropEffects))
+ if (owner_->GetHtmlAttribute("aria-dropeffect", &dropEffects))
return base::SysUTF8ToNSString(dropEffects);
return nil;
@@ -1060,7 +1084,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
std::string id;
- if (browserAccessibility_->GetHtmlAttribute("id", &id))
+ if (owner_->GetHtmlAttribute("id", &id))
return base::SysUTF8ToNSString(id);
return nil;
@@ -1071,7 +1095,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
BrowserAccessibilityCocoa* editableRoot = self;
- while (![editableRoot browserAccessibility]->GetBoolAttribute(
+ while (![editableRoot owner]->GetBoolAttribute(
ax::mojom::BoolAttribute::kEditableRoot)) {
BrowserAccessibilityCocoa* parent = [editableRoot parent];
if (!parent || ![parent isKindOfClass:[self class]] ||
@@ -1086,16 +1110,14 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)enabled {
if (![self instanceActive])
return nil;
- return [NSNumber
- numberWithBool:browserAccessibility_->GetData().GetRestriction() !=
- ax::mojom::Restriction::kDisabled];
+ return [NSNumber numberWithBool:owner_->GetData().GetRestriction() !=
+ ax::mojom::Restriction::kDisabled];
}
// Returns a text marker that points to the last character in the document that
// can be selected with VoiceOver.
- (id)endTextMarker {
- const BrowserAccessibility* root =
- browserAccessibility_->manager()->GetRoot();
+ const BrowserAccessibility* root = owner_->manager()->GetRoot();
if (!root)
return nil;
@@ -1106,16 +1128,31 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)expanded {
if (![self instanceActive])
return nil;
- return [NSNumber numberWithBool:GetState(browserAccessibility_,
- ax::mojom::State::kExpanded)];
+ return
+ [NSNumber numberWithBool:GetState(owner_, ax::mojom::State::kExpanded)];
+}
+
+- (id)focusableAncestor {
+ if (![self instanceActive])
+ return nil;
+
+ BrowserAccessibilityCocoa* focusableRoot = self;
+ while (![focusableRoot owner]->HasState(ax::mojom::State::kFocusable)) {
+ BrowserAccessibilityCocoa* parent = [focusableRoot parent];
+ if (!parent || ![parent isKindOfClass:[self class]] ||
+ ![parent instanceActive]) {
+ return nil;
+ }
+ focusableRoot = parent;
+ }
+ return focusableRoot;
}
- (NSNumber*)focused {
if (![self instanceActive])
return nil;
- BrowserAccessibilityManager* manager = browserAccessibility_->manager();
- NSNumber* ret = [NSNumber numberWithBool:
- manager->GetFocus() == browserAccessibility_];
+ BrowserAccessibilityManager* manager = owner_->manager();
+ NSNumber* ret = [NSNumber numberWithBool:manager->GetFocus() == owner_];
return ret;
}
@@ -1123,8 +1160,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
std::string grabbed;
- if (browserAccessibility_->GetHtmlAttribute("aria-grabbed", &grabbed) &&
- grabbed == "true")
+ if (owner_->GetHtmlAttribute("aria-grabbed", &grabbed) && grabbed == "true")
return [NSNumber numberWithBool:YES];
return [NSNumber numberWithBool:NO];
@@ -1133,28 +1169,60 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)hasPopup {
if (![self instanceActive])
return nil;
- return browserAccessibility_->HasState(ax::mojom::State::kHasPopup) ? @YES
- : @NO;
+ return @(owner_->HasIntAttribute(ax::mojom::IntAttribute::kHasPopup));
+}
+
+- (NSString*)hasPopupValue {
+ if (![self instanceActive])
+ return nil;
+ int hasPopup = owner_->GetIntAttribute(ax::mojom::IntAttribute::kHasPopup);
+ switch (static_cast<ax::mojom::HasPopup>(hasPopup)) {
+ case ax::mojom::HasPopup::kFalse:
+ return @"false";
+ case ax::mojom::HasPopup::kTrue:
+ return @"true";
+ case ax::mojom::HasPopup::kMenu:
+ return @"menu";
+ case ax::mojom::HasPopup::kListbox:
+ return @"listbox";
+ case ax::mojom::HasPopup::kTree:
+ return @"tree";
+ case ax::mojom::HasPopup::kGrid:
+ return @"grid";
+ case ax::mojom::HasPopup::kDialog:
+ return @"dialog";
+ }
}
- (id)header {
if (![self instanceActive])
return nil;
int headerElementId = -1;
- if (ui::IsTableLikeRole(browserAccessibility_->GetRole())) {
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableHeaderId, &headerElementId);
+ if (ui::IsTableLikeRole(owner_->GetRole())) {
+ // The table header container is always the last child of the table,
+ // if it exists. The table header container is a special node in the
+ // accessibility tree only used on macOS. It has all of the table
+ // headers as its children, even though those cells are also children
+ // of rows in the table. Internally this is implemented using
+ // AXTableInfo and indirect_child_ids.
+ uint32_t childCount = owner_->PlatformChildCount();
+ if (childCount > 0) {
+ BrowserAccessibility* tableHeader =
+ owner_->PlatformGetChild(childCount - 1);
+ if (tableHeader->GetRole() == ax::mojom::Role::kTableHeaderContainer)
+ return ToBrowserAccessibilityCocoa(tableHeader);
+ }
} else if ([self internalRole] == ax::mojom::Role::kColumn) {
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableColumnHeaderId, &headerElementId);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableColumnHeaderId,
+ &headerElementId);
} else if ([self internalRole] == ax::mojom::Role::kRow) {
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableRowHeaderId, &headerElementId);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableRowHeaderId,
+ &headerElementId);
}
if (headerElementId > 0) {
BrowserAccessibility* headerObject =
- browserAccessibility_->manager()->GetFromID(headerElementId);
+ owner_->manager()->GetFromID(headerElementId);
if (headerObject)
return ToBrowserAccessibilityCocoa(headerObject);
}
@@ -1164,7 +1232,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSString*)help {
if (![self instanceActive])
return nil;
- return NSStringForStringAttribute(browserAccessibility_,
+ return NSStringForStringAttribute(owner_,
ax::mojom::StringAttribute::kDescription);
}
@@ -1192,12 +1260,12 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
if ([self internalRole] == ax::mojom::Role::kColumn) {
- int columnIndex = browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableColumnIndex);
+ int columnIndex =
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableColumnIndex);
return [NSNumber numberWithInt:columnIndex];
} else if ([self internalRole] == ax::mojom::Role::kRow) {
- int rowIndex = browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableRowIndex);
+ int rowIndex =
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableRowIndex);
return [NSNumber numberWithInt:rowIndex];
}
@@ -1210,18 +1278,16 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// TODO(nektar): Deprecate sel_start and sel_end attributes.
int selStart, selEnd;
- if (!browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTextSelStart, &selStart) ||
- !browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTextSelEnd, &selEnd)) {
+ if (!owner_->GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart,
+ &selStart) ||
+ !owner_->GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, &selEnd)) {
return nil;
}
if (selStart > selEnd)
std::swap(selStart, selEnd);
- const std::vector<int> line_breaks =
- browserAccessibility_->GetLineStartOffsets();
+ const std::vector<int> line_breaks = owner_->GetLineStartOffsets();
for (int i = 0; i < static_cast<int>(line_breaks.size()); ++i) {
if (line_breaks[i] > selStart)
return [NSNumber numberWithInt:i];
@@ -1242,8 +1308,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
int invalidState;
- if (!browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kInvalidState, &invalidState))
+ if (!owner_->GetIntAttribute(ax::mojom::IntAttribute::kInvalidState,
+ &invalidState))
return @"false";
switch (static_cast<ax::mojom::InvalidState>(invalidState)) {
@@ -1257,7 +1323,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return @"grammar";
case ax::mojom::InvalidState::kOther: {
std::string ariaInvalidValue;
- if (browserAccessibility_->GetStringAttribute(
+ if (owner_->GetStringAttribute(
ax::mojom::StringAttribute::kAriaInvalidValue, &ariaInvalidValue))
return base::SysUTF8ToNSString(ariaInvalidValue);
// Return @"true" since we cannot be more specific about the value.
@@ -1273,50 +1339,47 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)isMultiSelectable {
if (![self instanceActive])
return nil;
- return [NSNumber numberWithBool:GetState(browserAccessibility_,
- ax::mojom::State::kMultiselectable)];
+ return [NSNumber
+ numberWithBool:GetState(owner_, ax::mojom::State::kMultiselectable)];
}
- (NSString*)placeholderValue {
if (![self instanceActive])
return nil;
- ax::mojom::NameFrom nameFrom =
- static_cast<ax::mojom::NameFrom>(browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kNameFrom));
+ ax::mojom::NameFrom nameFrom = static_cast<ax::mojom::NameFrom>(
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kNameFrom));
if (nameFrom == ax::mojom::NameFrom::kPlaceholder) {
- return NSStringForStringAttribute(browserAccessibility_,
+ return NSStringForStringAttribute(owner_,
ax::mojom::StringAttribute::kName);
}
ax::mojom::DescriptionFrom descriptionFrom =
static_cast<ax::mojom::DescriptionFrom>(
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kDescriptionFrom));
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom));
if (descriptionFrom == ax::mojom::DescriptionFrom::kPlaceholder) {
- return NSStringForStringAttribute(browserAccessibility_,
+ return NSStringForStringAttribute(owner_,
ax::mojom::StringAttribute::kDescription);
}
- return NSStringForStringAttribute(browserAccessibility_,
+ return NSStringForStringAttribute(owner_,
ax::mojom::StringAttribute::kPlaceholder);
}
- (NSString*)language {
if (![self instanceActive])
return nil;
- return base::SysUTF8ToNSString(
- browserAccessibility_->GetInheritedStringAttribute(
- ax::mojom::StringAttribute::kLanguage));
+ return base::SysUTF8ToNSString(owner_->GetInheritedStringAttribute(
+ ax::mojom::StringAttribute::kLanguage));
}
// private
- (void)addLinkedUIElementsFromAttribute:(ax::mojom::IntListAttribute)attribute
addTo:(NSMutableArray*)outArray {
const std::vector<int32_t>& attributeValues =
- browserAccessibility_->GetIntListAttribute(attribute);
+ owner_->GetIntListAttribute(attribute);
for (size_t i = 0; i < attributeValues.size(); ++i) {
BrowserAccessibility* element =
- browserAccessibility_->manager()->GetFromID(attributeValues[i]);
+ owner_->manager()->GetFromID(attributeValues[i]);
if (element)
[outArray addObject:ToBrowserAccessibilityCocoa(element)];
}
@@ -1332,10 +1395,10 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
addTo:ret];
int target_id;
- if (browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kInPageLinkTargetId, &target_id)) {
- BrowserAccessibility* target = browserAccessibility_->manager()->GetFromID(
- static_cast<int32_t>(target_id));
+ if (owner_->GetIntAttribute(ax::mojom::IntAttribute::kInPageLinkTargetId,
+ &target_id)) {
+ BrowserAccessibility* target =
+ owner_->manager()->GetFromID(static_cast<int32_t>(target_id));
if (target)
[ret addObject:ToBrowserAccessibilityCocoa(target)];
}
@@ -1357,7 +1420,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)loadingProgress {
if (![self instanceActive])
return nil;
- BrowserAccessibilityManager* manager = browserAccessibility_->manager();
+ BrowserAccessibilityManager* manager = owner_->manager();
float floatValue = manager->GetTreeData().loading_progress;
return [NSNumber numberWithFloat:floatValue];
}
@@ -1365,25 +1428,25 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)maxValue {
if (![self instanceActive])
return nil;
- float floatValue = browserAccessibility_->GetFloatAttribute(
- ax::mojom::FloatAttribute::kMaxValueForRange);
+ float floatValue =
+ owner_->GetFloatAttribute(ax::mojom::FloatAttribute::kMaxValueForRange);
return [NSNumber numberWithFloat:floatValue];
}
- (NSNumber*)minValue {
if (![self instanceActive])
return nil;
- float floatValue = browserAccessibility_->GetFloatAttribute(
- ax::mojom::FloatAttribute::kMinValueForRange);
+ float floatValue =
+ owner_->GetFloatAttribute(ax::mojom::FloatAttribute::kMinValueForRange);
return [NSNumber numberWithFloat:floatValue];
}
- (NSString*)orientation {
if (![self instanceActive])
return nil;
- if (GetState(browserAccessibility_, ax::mojom::State::kVertical))
+ if (GetState(owner_, ax::mojom::State::kVertical))
return NSAccessibilityVerticalOrientationValue;
- else if (GetState(browserAccessibility_, ax::mojom::State::kHorizontal))
+ else if (GetState(owner_, ax::mojom::State::kHorizontal))
return NSAccessibilityHorizontalOrientationValue;
return @"";
@@ -1401,11 +1464,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
//
int activeDescendantId;
- if (!browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kActivedescendantId, &activeDescendantId))
+ if (!owner_->GetIntAttribute(ax::mojom::IntAttribute::kActivedescendantId,
+ &activeDescendantId))
return nil;
- BrowserAccessibilityManager* manager = browserAccessibility_->manager();
+ BrowserAccessibilityManager* manager = owner_->manager();
BrowserAccessibility* activeDescendant =
manager->GetFromID(activeDescendantId);
if (!activeDescendant)
@@ -1426,7 +1489,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)numberOfCharacters {
if (![self instanceActive])
return nil;
- base::string16 value = browserAccessibility_->GetValue();
+ base::string16 value = owner_->GetValue();
return [NSNumber numberWithUnsignedInt:value.size()];
}
@@ -1436,7 +1499,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSPoint)origin {
if (![self instanceActive])
return NSMakePoint(0, 0);
- gfx::Rect bounds = browserAccessibility_->GetPageBoundsRect();
+ gfx::Rect bounds = owner_->GetPageBoundsRect();
return NSMakePoint(bounds.x(), bounds.y());
}
@@ -1444,14 +1507,13 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
// A nil parent means we're the root.
- if (browserAccessibility_->PlatformGetParent()) {
- return NSAccessibilityUnignoredAncestor(ToBrowserAccessibilityCocoa(
- browserAccessibility_->PlatformGetParent()));
+ if (owner_->PlatformGetParent()) {
+ return NSAccessibilityUnignoredAncestor(
+ ToBrowserAccessibilityCocoa(owner_->PlatformGetParent()));
} else {
// Hook back up to RenderWidgetHostViewCocoa.
BrowserAccessibilityManagerMac* manager =
- browserAccessibility_->manager()->GetRootManager()
- ->ToBrowserAccessibilityManagerMac();
+ owner_->manager()->GetRootManager()->ToBrowserAccessibilityManagerMac();
if (manager)
return manager->GetParentView();
return nil;
@@ -1470,14 +1532,26 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)required {
if (![self instanceActive])
return nil;
- return [NSNumber numberWithBool:GetState(browserAccessibility_,
- ax::mojom::State::kRequired)];
+ return
+ [NSNumber numberWithBool:GetState(owner_, ax::mojom::State::kRequired)];
}
-// Returns an enum indicating the role from browserAccessibility_.
+// Returns an enum indicating the role from owner_.
// internal
- (ax::mojom::Role)internalRole {
- return static_cast<ax::mojom::Role>(browserAccessibility_->GetRole());
+ return static_cast<ax::mojom::Role>(owner_->GetRole());
+}
+
+- (BOOL)shouldExposeNameInDescription {
+ // VoiceOver will not read the label of a fieldset or radiogroup unless it is
+ // exposed in the description instead of the title.
+ switch (owner_->GetRole()) {
+ case ax::mojom::Role::kGroup:
+ case ax::mojom::Role::kRadioGroup:
+ return true;
+ default:
+ return false;
+ }
}
// Returns true if this object should expose its accessible name using
@@ -1487,23 +1561,20 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// internal
- (BOOL)shouldExposeTitleUIElement {
// VoiceOver ignores TitleUIElement if the element isn't a control.
- if (!ui::IsControl(browserAccessibility_->GetRole()))
+ if (!ui::IsControl(owner_->GetRole()))
return false;
- ax::mojom::NameFrom nameFrom =
- static_cast<ax::mojom::NameFrom>(browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kNameFrom));
+ ax::mojom::NameFrom nameFrom = static_cast<ax::mojom::NameFrom>(
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kNameFrom));
if (nameFrom != ax::mojom::NameFrom::kRelatedElement)
return false;
std::vector<int32_t> labelledby_ids =
- browserAccessibility_->GetIntListAttribute(
- ax::mojom::IntListAttribute::kLabelledbyIds);
+ owner_->GetIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds);
if (labelledby_ids.size() != 1)
return false;
- BrowserAccessibility* label =
- browserAccessibility_->manager()->GetFromID(labelledby_ids[0]);
+ BrowserAccessibility* label = owner_->manager()->GetFromID(labelledby_ids[0]);
if (!label)
return false;
@@ -1514,12 +1585,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// internal
- (content::BrowserAccessibilityDelegate*)delegate {
- return [self instanceActive] ? browserAccessibility_->manager()->delegate()
- : nil;
+ return [self instanceActive] ? owner_->manager()->delegate() : nil;
}
-- (content::BrowserAccessibility*)browserAccessibility {
- return browserAccessibility_;
+- (content::BrowserAccessibility*)owner {
+ return owner_;
}
// Assumes that there is at most one insertion, deletion or replacement at once.
@@ -1530,7 +1600,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// dispatch the actual text that changed on the value changed notification.
// We run this code on all macOS versions to get the highest test coverage.
base::string16 oldValue = oldValue_;
- base::string16 newValue = browserAccessibility_->GetValue();
+ base::string16 newValue = owner_->GetValue();
oldValue_ = newValue;
if (oldValue.empty() && newValue.empty())
return content::AXTextEdit();
@@ -1562,7 +1632,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
}
- (BOOL)instanceActive {
- return browserAccessibility_ && browserAccessibility_->instance_active();
+ return owner_ && owner_->instance_active();
}
// internal
@@ -1574,7 +1644,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// Get the delegate for the topmost BrowserAccessibilityManager, because
// that's the only one that can convert points to their origin in the screen.
BrowserAccessibilityDelegate* delegate =
- browserAccessibility_->manager()->GetDelegateFromRootManager();
+ owner_->manager()->GetDelegateFromRootManager();
if (delegate) {
gfx::Rect bounds(origin.x, origin.y, size.width, size.height);
gfx::Point point = delegate->AccessibilityOriginInScreen(bounds);
@@ -1591,25 +1661,23 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
ax::mojom::Role role = [self internalRole];
if (role == ax::mojom::Role::kCanvas &&
- browserAccessibility_->GetBoolAttribute(
- ax::mojom::BoolAttribute::kCanvasHasFallback)) {
+ owner_->GetBoolAttribute(ax::mojom::BoolAttribute::kCanvasHasFallback)) {
return NSAccessibilityGroupRole;
}
- if ((browserAccessibility_->IsPlainTextField() &&
- browserAccessibility_->HasState(ax::mojom::State::kMultiline)) ||
- browserAccessibility_->IsRichTextField()) {
+ if ((owner_->IsPlainTextField() &&
+ owner_->HasState(ax::mojom::State::kMultiline)) ||
+ owner_->IsRichTextField()) {
return NSAccessibilityTextAreaRole;
}
- if (role == ax::mojom::Role::kImage &&
- browserAccessibility_->HasExplicitlyEmptyName())
+ if (role == ax::mojom::Role::kImage && owner_->HasExplicitlyEmptyName())
return NSAccessibilityUnknownRole;
// If this is a web area for a presentational iframe, give it a role of
// something other than WebArea so that the fact that it's a separate doc
// is not exposed to AT.
- if (browserAccessibility_->IsWebAreaForPresentationalIframe())
+ if (owner_->IsWebAreaForPresentationalIframe())
return NSAccessibilityGroupRole;
return [AXPlatformNodeCocoa nativeRoleFromAXRole:role];
@@ -1620,10 +1688,10 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
- if (browserAccessibility_->HasStringAttribute(
+ if (owner_->HasStringAttribute(
ax::mojom::StringAttribute::kRoleDescription)) {
return NSStringForStringAttribute(
- browserAccessibility_, ax::mojom::StringAttribute::kRoleDescription);
+ owner_, ax::mojom::StringAttribute::kRoleDescription);
}
NSString* role = [self role];
@@ -1648,9 +1716,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (([role isEqualToString:NSAccessibilityGroupRole] ||
[role isEqualToString:NSAccessibilityRadioButtonRole]) &&
- !browserAccessibility_->IsWebAreaForPresentationalIframe()) {
+ !owner_->IsWebAreaForPresentationalIframe()) {
std::string role_attribute;
- if (browserAccessibility_->GetHtmlAttribute("role", &role_attribute)) {
+ if (owner_->GetHtmlAttribute("role", &role_attribute)) {
ax::mojom::Role internalRole = [self internalRole];
if ((internalRole != ax::mojom::Role::kGroup &&
internalRole != ax::mojom::Role::kListItem) ||
@@ -1742,17 +1810,17 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (BOOL)isRowHeaderForCurrentCell:(BrowserAccessibility*)header {
int cell_first_row = -1;
int cell_rowspan = -1;
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kAriaCellRowIndex, &cell_first_row);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kAriaCellRowIndex,
+ &cell_first_row);
if (cell_first_row < 0) {
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableCellRowIndex, &cell_first_row);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex,
+ &cell_first_row);
}
if (cell_first_row < 0)
return false;
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableCellRowSpan, &cell_rowspan);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowSpan,
+ &cell_rowspan);
if (cell_rowspan <= 0)
cell_rowspan = 1;
@@ -1787,9 +1855,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
- bool is_cell_or_table_header =
- ui::IsCellOrTableHeaderRole(browserAccessibility_->GetRole());
- bool is_table_like = ui::IsTableLikeRole(browserAccessibility_->GetRole());
+ bool is_cell_or_table_header = ui::IsCellOrTableHeaderRole(owner_->GetRole());
+ bool is_table_like = ui::IsTableLikeRole(owner_->GetRole());
if (!is_table_like && !is_cell_or_table_header)
return nil;
BrowserAccessibility* table = [self containingTable];
@@ -1807,21 +1874,18 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
headerIds.insert(id);
}
for (int32_t id : headerIds) {
- BrowserAccessibility* cell =
- browserAccessibility_->manager()->GetFromID(id);
+ BrowserAccessibility* cell = owner_->manager()->GetFromID(id);
if (cell)
[ret addObject:ToBrowserAccessibilityCocoa(cell)];
}
} else {
// Otherwise this is a cell, return the row headers for this cell.
int row = -1;
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableCellRowIndex, &row);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex, &row);
std::vector<int32_t> rowHeaderIds = table->GetRowHeaderNodeIds(row);
for (int32_t id : rowHeaderIds) {
- BrowserAccessibility* cell =
- browserAccessibility_->manager()->GetFromID(id);
+ BrowserAccessibility* cell = owner_->manager()->GetFromID(id);
if (cell)
[ret addObject:ToBrowserAccessibilityCocoa(cell)];
}
@@ -1833,15 +1897,13 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSValue*)rowIndexRange {
if (![self instanceActive])
return nil;
- if (!ui::IsCellOrTableHeaderRole(browserAccessibility_->GetRole()))
+ if (!ui::IsCellOrTableHeaderRole(owner_->GetRole()))
return nil;
int row = -1;
int rowspan = -1;
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableCellRowIndex, &row);
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableCellRowSpan, &rowspan);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex, &row);
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableCellRowSpan, &rowspan);
if (row >= 0 && rowspan >= 1)
return [NSValue valueWithRange:NSMakeRange(row, rowspan)];
return nil;
@@ -1859,13 +1921,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
[ret addObject:child];
}
} else if ([self internalRole] == ax::mojom::Role::kColumn) {
- const std::vector<int32_t>& indirectChildIds =
- browserAccessibility_->GetIntListAttribute(
- ax::mojom::IntListAttribute::kIndirectChildIds);
+ const std::vector<int32_t>& indirectChildIds = owner_->GetIntListAttribute(
+ ax::mojom::IntListAttribute::kIndirectChildIds);
for (uint32_t i = 0; i < indirectChildIds.size(); ++i) {
int id = indirectChildIds[i];
- BrowserAccessibility* rowElement =
- browserAccessibility_->manager()->GetFromID(id);
+ BrowserAccessibility* rowElement = owner_->manager()->GetFromID(id);
if (rowElement)
[ret addObject:ToBrowserAccessibilityCocoa(rowElement)];
}
@@ -1877,33 +1937,32 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)selected {
if (![self instanceActive])
return nil;
- // TODO(nektar): Implement.
- return [NSNumber numberWithBool:NO];
+ return [NSNumber numberWithBool:owner_->GetBoolAttribute(
+ ax::mojom::BoolAttribute::kSelected)];
}
- (NSArray*)selectedChildren {
if (![self instanceActive])
return nil;
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
- BrowserAccessibilityManager* manager = browserAccessibility_->manager();
+ BrowserAccessibilityManager* manager = owner_->manager();
BrowserAccessibility* focusedChild = manager->GetFocus();
- if (!focusedChild->IsDescendantOf(browserAccessibility_))
+ if (!focusedChild->IsDescendantOf(owner_))
focusedChild = nullptr;
// If it's not multiselectable, try to skip iterating over the
// children.
- if (!GetState(browserAccessibility_, ax::mojom::State::kMultiselectable)) {
+ if (!GetState(owner_, ax::mojom::State::kMultiselectable)) {
// First try the focused child.
- if (focusedChild && focusedChild != browserAccessibility_) {
+ if (focusedChild && focusedChild != owner_) {
[ret addObject:ToBrowserAccessibilityCocoa(focusedChild)];
return ret;
}
// Next try the active descendant.
int activeDescendantId;
- if (browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kActivedescendantId,
- &activeDescendantId)) {
+ if (owner_->GetIntAttribute(ax::mojom::IntAttribute::kActivedescendantId,
+ &activeDescendantId)) {
BrowserAccessibility* activeDescendant =
manager->GetFromID(activeDescendantId);
if (activeDescendant) {
@@ -1916,18 +1975,15 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// If it's multiselectable or if the previous attempts failed,
// return any children with the "selected" state, which may
// come from aria-selected.
- uint32_t childCount = browserAccessibility_->PlatformChildCount();
+ uint32_t childCount = owner_->PlatformChildCount();
for (uint32_t index = 0; index < childCount; ++index) {
- BrowserAccessibility* child =
- browserAccessibility_->PlatformGetChild(index);
+ BrowserAccessibility* child = owner_->PlatformGetChild(index);
if (child->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected))
[ret addObject:ToBrowserAccessibilityCocoa(child)];
}
// And if nothing's selected but one has focus, use the focused one.
- if ([ret count] == 0 &&
- focusedChild &&
- focusedChild != browserAccessibility_) {
+ if ([ret count] == 0 && focusedChild && focusedChild != owner_) {
[ret addObject:ToBrowserAccessibilityCocoa(focusedChild)];
}
@@ -1940,10 +1996,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// TODO(nektar): Deprecate sel_start and sel_end attributes.
int selStart, selEnd;
- if (!browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTextSelStart, &selStart) ||
- !browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTextSelEnd, &selEnd)) {
+ if (!owner_->GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart,
+ &selStart) ||
+ !owner_->GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, &selEnd)) {
return nil;
}
@@ -1951,7 +2006,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
std::swap(selStart, selEnd);
int selLength = selEnd - selStart;
- base::string16 value = browserAccessibility_->GetValue();
+ base::string16 value = owner_->GetValue();
return base::SysUTF16ToNSString(value.substr(selStart, selLength));
}
@@ -1961,10 +2016,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// TODO(nektar): Deprecate sel_start and sel_end attributes.
int selStart, selEnd;
- if (!browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTextSelStart, &selStart) ||
- !browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTextSelEnd, &selEnd)) {
+ if (!owner_->GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart,
+ &selStart) ||
+ !owner_->GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, &selEnd)) {
return nil;
}
@@ -1979,7 +2033,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
- BrowserAccessibilityManager* manager = browserAccessibility_->manager();
+ BrowserAccessibilityManager* manager = owner_->manager();
if (!manager)
return nil;
@@ -2011,7 +2065,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSValue*)size {
if (![self instanceActive])
return nil;
- gfx::Rect bounds = browserAccessibility_->GetPageBoundsRect();
+ gfx::Rect bounds = owner_->GetPageBoundsRect();
return [NSValue valueWithSize:NSMakeSize(bounds.width(), bounds.height())];
}
@@ -2019,8 +2073,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
int sortDirection;
- if (!browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kSortDirection, &sortDirection))
+ if (!owner_->GetIntAttribute(ax::mojom::IntAttribute::kSortDirection,
+ &sortDirection))
return nil;
switch (static_cast<ax::mojom::SortDirection>(sortDirection)) {
@@ -2042,8 +2096,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// Returns a text marker that points to the first character in the document that
// can be selected with VoiceOver.
- (id)startTextMarker {
- const BrowserAccessibility* root =
- browserAccessibility_->manager()->GetRoot();
+ const BrowserAccessibility* root = owner_->manager()->GetRoot();
if (!root)
return nil;
@@ -2056,8 +2109,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
- if (browserAccessibility_->IsPlainTextField() &&
- GetState(browserAccessibility_, ax::mojom::State::kProtected)) {
+ if (owner_->IsPlainTextField() &&
+ GetState(owner_, ax::mojom::State::kProtected)) {
return NSAccessibilitySecureTextFieldSubrole;
}
@@ -2095,14 +2148,16 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (ui::IsNameExposedInAXValueForRole([self internalRole]))
return @"";
+ if ([self shouldExposeNameInDescription])
+ return @"";
+
// If we're exposing the title in TitleUIElement, don't also redundantly
// expose it in AXDescription.
if ([self shouldExposeTitleUIElement])
return @"";
- ax::mojom::NameFrom nameFrom =
- static_cast<ax::mojom::NameFrom>(browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kNameFrom));
+ ax::mojom::NameFrom nameFrom = static_cast<ax::mojom::NameFrom>(
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kNameFrom));
// On Mac OS X, cell titles are "" if it it came from content.
NSString* role = [self role];
@@ -2116,7 +2171,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (nameFrom == ax::mojom::NameFrom::kContents ||
nameFrom == ax::mojom::NameFrom::kRelatedElement ||
nameFrom == ax::mojom::NameFrom::kValue) {
- return NSStringForStringAttribute(browserAccessibility_,
+ return NSStringForStringAttribute(owner_,
ax::mojom::StringAttribute::kName);
}
@@ -2130,15 +2185,13 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
std::vector<int32_t> labelledby_ids =
- browserAccessibility_->GetIntListAttribute(
- ax::mojom::IntListAttribute::kLabelledbyIds);
- ax::mojom::NameFrom nameFrom =
- static_cast<ax::mojom::NameFrom>(browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kNameFrom));
+ owner_->GetIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds);
+ ax::mojom::NameFrom nameFrom = static_cast<ax::mojom::NameFrom>(
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kNameFrom));
if (nameFrom == ax::mojom::NameFrom::kRelatedElement &&
labelledby_ids.size() == 1) {
BrowserAccessibility* titleElement =
- browserAccessibility_->manager()->GetFromID(labelledby_ids[0]);
+ owner_->manager()->GetFromID(labelledby_ids[0]);
if (titleElement)
return ToBrowserAccessibilityCocoa(titleElement);
}
@@ -2151,10 +2204,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
std::string url;
if ([[self role] isEqualToString:@"AXWebArea"])
- url = browserAccessibility_->manager()->GetTreeData().url;
+ url = owner_->manager()->GetTreeData().url;
else
- url = browserAccessibility_->GetStringAttribute(
- ax::mojom::StringAttribute::kUrl);
+ url = owner_->GetStringAttribute(ax::mojom::StringAttribute::kUrl);
if (url.empty())
return nil;
@@ -2167,26 +2219,24 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
if (ui::IsNameExposedInAXValueForRole([self internalRole]))
- return NSStringForStringAttribute(browserAccessibility_,
+ return NSStringForStringAttribute(owner_,
ax::mojom::StringAttribute::kName);
NSString* role = [self role];
if ([role isEqualToString:@"AXHeading"]) {
int level = 0;
- if (browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kHierarchicalLevel, &level)) {
+ if (owner_->GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel,
+ &level)) {
return [NSNumber numberWithInt:level];
}
} else if ([role isEqualToString:NSAccessibilityButtonRole]) {
// AXValue does not make sense for pure buttons.
return @"";
- } else if (browserAccessibility_->HasIntAttribute(
- ax::mojom::IntAttribute::kCheckedState) ||
+ } else if (owner_->HasIntAttribute(ax::mojom::IntAttribute::kCheckedState) ||
[role isEqualToString:NSAccessibilityRadioButtonRole]) {
int value;
const auto checkedState = static_cast<ax::mojom::CheckedState>(
- browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kCheckedState));
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kCheckedState));
switch (checkedState) {
case ax::mojom::CheckedState::kTrue:
value = 1;
@@ -2195,8 +2245,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
value = 2;
break;
default:
- value = browserAccessibility_->GetBoolAttribute(
- ax::mojom::BoolAttribute::kSelected)
+ value = owner_->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected)
? 1
: 0;
break;
@@ -2207,16 +2256,15 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
[role isEqualToString:NSAccessibilityIncrementorRole] ||
[role isEqualToString:NSAccessibilityScrollBarRole] ||
([role isEqualToString:NSAccessibilitySplitterRole] &&
- browserAccessibility_->HasState(ax::mojom::State::kFocusable))) {
+ owner_->HasState(ax::mojom::State::kFocusable))) {
float floatValue;
- if (browserAccessibility_->GetFloatAttribute(
- ax::mojom::FloatAttribute::kValueForRange, &floatValue)) {
+ if (owner_->GetFloatAttribute(ax::mojom::FloatAttribute::kValueForRange,
+ &floatValue)) {
return [NSNumber numberWithFloat:floatValue];
}
} else if ([role isEqualToString:NSAccessibilityColorWellRole]) {
- unsigned int color =
- static_cast<unsigned int>(browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kColorValue));
+ unsigned int color = static_cast<unsigned int>(
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kColorValue));
unsigned int red = SkColorGetR(color);
unsigned int green = SkColorGetG(color);
unsigned int blue = SkColorGetB(color);
@@ -2225,21 +2273,47 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
red / 255., green / 255., blue / 255.];
}
- return base::SysUTF16ToNSString(browserAccessibility_->GetValue());
+ return base::SysUTF16ToNSString(owner_->GetValue());
}
+- (BOOL)isFocusedInputWithSuggestions {
+ if (!owner_->IsPlainTextField())
+ return false;
+ BrowserAccessibilityManager* manager = owner_->manager();
+ if (manager->GetFocus() != owner_)
+ return false;
+ return ui::AXPlatformNode::HasInputSuggestions();
+}
+
+- (NSNumber*)valueAutofillAvailable {
+ if (![self instanceActive])
+ return nil;
+ return [self isFocusedInputWithSuggestions] ? @YES : @NO;
+}
+
+// Not currently supported, as Chrome does not store whether an autofill
+// occurred. We could have autofill fire an event, however, and set an
+// "is_autofilled" flag until the next edit. - (NSNumber*)valueAutofilled {
+// return @NO;
+// }
+
+// Not currently supported, as Chrome's autofill types aren't like Safari's.
+// - (NSString*)valueAutofillType {
+// return @"none";
+//}
+
- (NSString*)valueDescription {
if (![self instanceActive])
return nil;
- if (browserAccessibility_)
- return base::SysUTF16ToNSString(browserAccessibility_->GetValue());
+ if (owner_)
+ return base::SysUTF16ToNSString(owner_->GetValue());
return nil;
}
- (NSValue*)visibleCharacterRange {
if (![self instanceActive])
return nil;
- base::string16 value = browserAccessibility_->GetValue();
+ base::string16 value = owner_->GetValue();
return [NSValue valueWithRange:NSMakeRange(0, value.size())];
}
@@ -2248,16 +2322,14 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
ui::AXTableInfo* table_info =
- browserAccessibility_->manager()->ax_tree()->GetTableInfo(
- browserAccessibility_->node());
+ owner_->manager()->ax_tree()->GetTableInfo(owner_->node());
if (!table_info)
return nil;
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
for (size_t i = 0; i < table_info->unique_cell_ids.size(); ++i) {
int id = table_info->unique_cell_ids[i];
- BrowserAccessibility* cell =
- browserAccessibility_->manager()->GetFromID(id);
+ BrowserAccessibility* cell = owner_->manager()->GetFromID(id);
if (cell)
[ret addObject:ToBrowserAccessibilityCocoa(cell)];
}
@@ -2285,8 +2357,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)visited {
if (![self instanceActive])
return nil;
- return [NSNumber numberWithBool:GetState(browserAccessibility_,
- ax::mojom::State::kVisited)];
+ return [NSNumber numberWithBool:GetState(owner_, ax::mojom::State::kVisited)];
}
- (id)window {
@@ -2294,8 +2365,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
BrowserAccessibilityManagerMac* manager =
- browserAccessibility_->manager()->GetRootManager()
- ->ToBrowserAccessibilityManagerMac();
+ owner_->manager()->GetRootManager()->ToBrowserAccessibilityManagerMac();
if (!manager || !manager->GetParentView())
return nil;
@@ -2314,7 +2384,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
- base::string16 value = browserAccessibility_->GetValue();
+ base::string16 value = owner_->GetValue();
if (NSMaxRange(range) > value.length())
return nil;
@@ -2325,9 +2395,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
- base::string16 text = browserAccessibility_->GetValue();
- if (browserAccessibility_->IsTextOnlyObject() && text.empty())
- text = browserAccessibility_->GetText();
+ base::string16 text = owner_->GetValue();
+ if (owner_->IsTextOnlyObject() && text.empty())
+ text = owner_->GetText();
// We need to get the whole text because a spelling mistake might start or end
// outside our range.
@@ -2335,10 +2405,10 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
NSMutableAttributedString* attributedValue =
[[[NSMutableAttributedString alloc] initWithString:value] autorelease];
- if (!browserAccessibility_->IsTextOnlyObject()) {
+ if (!owner_->IsTextOnlyObject()) {
std::vector<const BrowserAccessibility*> textOnlyObjects =
- BrowserAccessibilityManager::FindTextOnlyObjectsInRange(
- *browserAccessibility_, *browserAccessibility_);
+ BrowserAccessibilityManager::FindTextOnlyObjectsInRange(*owner_,
+ *owner_);
AddMisspelledTextAttributes(textOnlyObjects, attributedValue);
}
@@ -2366,9 +2436,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
- const std::vector<int> line_breaks =
- browserAccessibility_->GetLineStartOffsets();
- base::string16 value = browserAccessibility_->GetValue();
+ const std::vector<int> line_breaks = owner_->GetLineStartOffsets();
+ base::string16 value = owner_->GetValue();
int len = static_cast<int>(value.size());
if ([attribute isEqualToString:
@@ -2417,18 +2486,16 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
NSArray* array = parameter;
int column = [[array objectAtIndex:0] intValue];
int row = [[array objectAtIndex:1] intValue];
- int num_columns = browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableColumnCount);
- int num_rows = browserAccessibility_->GetIntAttribute(
- ax::mojom::IntAttribute::kTableRowCount);
+ int num_columns =
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableColumnCount);
+ int num_rows =
+ owner_->GetIntAttribute(ax::mojom::IntAttribute::kTableRowCount);
if (column < 0 || column >= num_columns ||
row < 0 || row >= num_rows) {
return nil;
}
- for (size_t i = 0;
- i < browserAccessibility_->PlatformChildCount();
- ++i) {
- BrowserAccessibility* child = browserAccessibility_->PlatformGetChild(i);
+ for (size_t i = 0; i < owner_->PlatformChildCount(); ++i) {
+ BrowserAccessibility* child = owner_->PlatformGetChild(i);
if (child->GetRole() != ax::mojom::Role::kRow)
continue;
int rowIndex;
@@ -2471,7 +2538,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) {
BrowserAccessibilityPositionInstance startPosition =
- browserAccessibility_->CreatePositionAt(0);
+ owner_->CreatePositionAt(0);
BrowserAccessibilityPositionInstance endPosition =
startPosition->CreatePositionAtEndOfAnchor();
AXPlatformRange range =
@@ -2643,8 +2710,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if ([self internalRole] != ax::mojom::Role::kStaticText)
return nil;
NSRange range = [(NSValue*)parameter rangeValue];
- gfx::Rect rect = browserAccessibility_->GetScreenBoundsForRange(
- range.location, range.length);
+ gfx::Rect rect =
+ owner_->GetScreenBoundsForRange(range.location, range.length);
NSPoint origin = NSMakePoint(rect.x(), rect.y());
NSSize size = NSMakeSize(rect.width(), rect.height());
NSPoint pointInScreen = [self pointInScreen:origin size:size];
@@ -2654,14 +2721,14 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
}
if ([attribute isEqualToString:@"AXUIElementCountForSearchPredicate"]) {
- OneShotAccessibilityTreeSearch search(browserAccessibility_);
+ OneShotAccessibilityTreeSearch search(owner_);
if (InitializeAccessibilityTreeSearch(&search, parameter))
return [NSNumber numberWithInt:search.CountMatches()];
return nil;
}
if ([attribute isEqualToString:@"AXUIElementsForSearchPredicate"]) {
- OneShotAccessibilityTreeSearch search(browserAccessibility_);
+ OneShotAccessibilityTreeSearch search(owner_);
if (InitializeAccessibilityTreeSearch(&search, parameter)) {
size_t count = search.CountMatches();
NSMutableArray* result = [NSMutableArray arrayWithCapacity:count];
@@ -2744,11 +2811,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
BrowserAccessibilityCocoa* childCocoaObj =
(BrowserAccessibilityCocoa*)parameter;
- BrowserAccessibility* child = [childCocoaObj browserAccessibility];
+ BrowserAccessibility* child = [childCocoaObj owner];
if (!child)
return nil;
- if (child->PlatformGetParent() != browserAccessibility_)
+ if (child->PlatformGetParent() != owner_)
return nil;
return @(child->GetIndexInParent());
@@ -2806,7 +2873,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
]];
}
- if (browserAccessibility_->HasState(ax::mojom::State::kEditable)) {
+ if (owner_->HasState(ax::mojom::State::kEditable)) {
[ret addObjectsFromArray:@[
NSAccessibilityLineForIndexParameterizedAttribute,
NSAccessibilityRangeForLineParameterizedAttribute,
@@ -2847,10 +2914,10 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
NSAccessibilityScrollToVisibleAction, nil];
// VoiceOver expects the "press" action to be first.
- if (browserAccessibility_->IsClickable())
+ if (owner_->IsClickable())
[actions insertObject:NSAccessibilityPressAction atIndex:0];
- if (ui::IsMenuRelated(browserAccessibility_->GetRole()))
+ if (ui::IsMenuRelated(owner_->GetRole()))
[actions addObject:NSAccessibilityCancelAction];
if ([self internalRole] == ax::mojom::Role::kSlider ||
@@ -2910,12 +2977,10 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
NSAccessibilityChildrenAttribute,
NSAccessibilityDescriptionAttribute,
NSAccessibilityDOMIdentifierAttribute,
- NSAccessibilityEditableAncestorAttribute,
NSAccessibilityEnabledAttribute,
NSAccessibilityEndTextMarkerAttribute,
NSAccessibilityFocusedAttribute,
NSAccessibilityHelpAttribute,
- NSAccessibilityHighestEditableAncestorAttribute,
NSAccessibilityInvalidAttribute,
NSAccessibilityLinkedUIElementsAttribute,
NSAccessibilityParentAttribute,
@@ -2981,7 +3046,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
[role isEqualToString:NSAccessibilityIncrementorRole] ||
[role isEqualToString:NSAccessibilityScrollBarRole] ||
([role isEqualToString:NSAccessibilitySplitterRole] &&
- browserAccessibility_->HasState(ax::mojom::State::kFocusable))) {
+ owner_->HasState(ax::mojom::State::kFocusable))) {
[ret addObjectsFromArray:@[
NSAccessibilityMaxValueAttribute, NSAccessibilityMinValueAttribute,
NSAccessibilityValueDescriptionAttribute
@@ -2994,10 +3059,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
NSAccessibilityDisclosedRowsAttribute
]];
} else if ([role isEqualToString:NSAccessibilityRowRole]) {
- if (browserAccessibility_->PlatformGetParent()) {
+ if (owner_->PlatformGetParent()) {
base::string16 parentRole;
- browserAccessibility_->PlatformGetParent()->GetHtmlAttribute("role",
- &parentRole);
+ owner_->PlatformGetParent()->GetHtmlAttribute("role", &parentRole);
const base::string16 treegridRole(base::ASCIIToUTF16("treegrid"));
if (parentRole == treegridRole) {
[ret addObjectsFromArray:@[
@@ -3018,13 +3082,28 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
}
// Caret navigation and text selection attributes.
- if (browserAccessibility_->HasState(ax::mojom::State::kEditable)) {
+ if (owner_->HasState(ax::mojom::State::kEditable)) {
[ret addObjectsFromArray:@[
+ NSAccessibilityAutocompleteValueAttribute,
NSAccessibilityInsertionPointLineNumberAttribute,
NSAccessibilityNumberOfCharactersAttribute,
NSAccessibilitySelectedTextAttribute,
NSAccessibilitySelectedTextRangeAttribute,
- NSAccessibilityVisibleCharacterRangeAttribute
+ NSAccessibilityVisibleCharacterRangeAttribute,
+ NSAccessibilityValueAutofillAvailableAttribute,
+ // Not currently supported by Chrome:
+ // NSAccessibilityValueAutofilledAttribute,
+ // Not currently supported by Chrome:
+ // NSAccessibilityValueAutofillTypeAttribute
+ ]];
+ }
+
+ // Add ancestor attributes if not a web area.
+ if (![role isEqualToString:@"AXWebArea"]) {
+ [ret addObjectsFromArray:@[
+ NSAccessibilityEditableAncestorAttribute,
+ NSAccessibilityFocusableAncestorAttribute,
+ NSAccessibilityHighestEditableAncestorAttribute
]];
}
@@ -3034,69 +3113,67 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
}
// Position in set and Set size
- if (browserAccessibility_->HasIntAttribute(
- ax::mojom::IntAttribute::kPosInSet)) {
+ if (owner_->HasIntAttribute(ax::mojom::IntAttribute::kPosInSet)) {
[ret addObjectsFromArray:@[ NSAccessibilityARIAPosInSetAttribute ]];
}
- if (browserAccessibility_->HasIntAttribute(
- ax::mojom::IntAttribute::kSetSize)) {
+ if (owner_->HasIntAttribute(ax::mojom::IntAttribute::kSetSize)) {
[ret addObjectsFromArray:@[ NSAccessibilityARIASetSizeAttribute ]];
}
// Live regions.
- if (browserAccessibility_->HasStringAttribute(
- ax::mojom::StringAttribute::kLiveStatus)) {
+ if (owner_->HasStringAttribute(ax::mojom::StringAttribute::kLiveStatus)) {
[ret addObjectsFromArray:@[ NSAccessibilityARIALiveAttribute ]];
}
- if (browserAccessibility_->HasStringAttribute(
- ax::mojom::StringAttribute::kLiveRelevant)) {
+ if (owner_->HasStringAttribute(ax::mojom::StringAttribute::kLiveRelevant)) {
[ret addObjectsFromArray:@[ NSAccessibilityARIARelevantAttribute ]];
}
- if (browserAccessibility_->HasBoolAttribute(
- ax::mojom::BoolAttribute::kLiveAtomic)) {
+ if (owner_->HasBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic)) {
[ret addObjectsFromArray:@[ NSAccessibilityARIAAtomicAttribute ]];
}
- if (browserAccessibility_->HasBoolAttribute(
- ax::mojom::BoolAttribute::kBusy)) {
+ if (owner_->HasBoolAttribute(ax::mojom::BoolAttribute::kBusy)) {
[ret addObjectsFromArray:@[ NSAccessibilityARIABusyAttribute ]];
}
std::string dropEffect;
- if (browserAccessibility_->GetHtmlAttribute("aria-dropeffect", &dropEffect)) {
+ if (owner_->GetHtmlAttribute("aria-dropeffect", &dropEffect)) {
[ret addObjectsFromArray:@[ NSAccessibilityDropEffectsAttribute ]];
}
std::string grabbed;
- if (browserAccessibility_->GetHtmlAttribute("aria-grabbed", &grabbed)) {
+ if (owner_->GetHtmlAttribute("aria-grabbed", &grabbed)) {
[ret addObjectsFromArray:@[ NSAccessibilityGrabbedAttribute ]];
}
- if (browserAccessibility_->HasState(ax::mojom::State::kHasPopup)) {
- [ret addObjectsFromArray:@[ NSAccessibilityHasPopupAttribute ]];
+ if (owner_->HasIntAttribute(ax::mojom::IntAttribute::kHasPopup)) {
+ [ret addObjectsFromArray:@[
+ NSAccessibilityHasPopupAttribute, NSAccessibilityHasPopupValueAttribute
+ ]];
+ }
+
+ if (owner_->HasBoolAttribute(ax::mojom::BoolAttribute::kSelected)) {
+ [ret addObjectsFromArray:@[ NSAccessibilitySelectedAttribute ]];
}
// Add expanded attribute only if it has expanded or collapsed state.
- if (GetState(browserAccessibility_, ax::mojom::State::kExpanded) ||
- GetState(browserAccessibility_, ax::mojom::State::kCollapsed)) {
+ if (GetState(owner_, ax::mojom::State::kExpanded) ||
+ GetState(owner_, ax::mojom::State::kCollapsed)) {
[ret addObjectsFromArray:@[ NSAccessibilityExpandedAttribute ]];
}
- if (GetState(browserAccessibility_, ax::mojom::State::kVertical) ||
- GetState(browserAccessibility_, ax::mojom::State::kHorizontal)) {
+ if (GetState(owner_, ax::mojom::State::kVertical) ||
+ GetState(owner_, ax::mojom::State::kHorizontal)) {
[ret addObjectsFromArray:@[ NSAccessibilityOrientationAttribute ]];
}
- if (browserAccessibility_->HasStringAttribute(
- ax::mojom::StringAttribute::kPlaceholder)) {
+ if (owner_->HasStringAttribute(ax::mojom::StringAttribute::kPlaceholder)) {
[ret addObjectsFromArray:@[ NSAccessibilityPlaceholderValueAttribute ]];
}
- if (GetState(browserAccessibility_, ax::mojom::State::kRequired)) {
+ if (GetState(owner_, ax::mojom::State::kRequired)) {
[ret addObjectsFromArray:@[ @"AXRequired" ]];
}
- if (browserAccessibility_->HasStringAttribute(
- ax::mojom::StringAttribute::kLanguage)) {
+ if (owner_->HasStringAttribute(ax::mojom::StringAttribute::kLanguage)) {
[ret addObjectsFromArray:@[ NSAccessibilityLanguageAttribute ]];
}
@@ -3107,10 +3184,9 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
}
// Title UI Element.
- if (browserAccessibility_->HasIntListAttribute(
+ if (owner_->HasIntListAttribute(
ax::mojom::IntListAttribute::kLabelledbyIds) &&
- browserAccessibility_
- ->GetIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds)
+ owner_->GetIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds)
.size() > 0) {
[ret addObjectsFromArray:@[ NSAccessibilityTitleUIElementAttribute ]];
}
@@ -3144,14 +3220,14 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if ([self internalRole] == ax::mojom::Role::kDateTime)
return NO;
- return GetState(browserAccessibility_, ax::mojom::State::kFocusable);
+ return GetState(owner_, ax::mojom::State::kFocusable);
}
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
- return browserAccessibility_->HasAction(ax::mojom::Action::kSetValue);
+ return owner_->HasAction(ax::mojom::Action::kSetValue);
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute] &&
- browserAccessibility_->HasState(ax::mojom::State::kEditable)) {
+ owner_->HasState(ax::mojom::State::kEditable)) {
return YES;
}
@@ -3174,18 +3250,17 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return;
// TODO(dmazzoni): Support more actions.
- BrowserAccessibilityManager* manager = browserAccessibility_->manager();
+ BrowserAccessibilityManager* manager = owner_->manager();
if ([action isEqualToString:NSAccessibilityPressAction]) {
- manager->DoDefaultAction(*browserAccessibility_);
+ manager->DoDefaultAction(*owner_);
} else if ([action isEqualToString:NSAccessibilityShowMenuAction]) {
- manager->ShowContextMenu(*browserAccessibility_);
+ manager->ShowContextMenu(*owner_);
} else if ([action isEqualToString:NSAccessibilityScrollToVisibleAction]) {
- manager->ScrollToMakeVisible(
- *browserAccessibility_, gfx::Rect());
+ manager->ScrollToMakeVisible(*owner_, gfx::Rect());
} else if ([action isEqualToString:NSAccessibilityIncrementAction]) {
- manager->Increment(*browserAccessibility_);
+ manager->Increment(*owner_);
} else if ([action isEqualToString:NSAccessibilityDecrementAction]) {
- manager->Decrement(*browserAccessibility_);
+ manager->Decrement(*owner_);
}
}
@@ -3212,18 +3287,18 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
- BrowserAccessibilityManager* manager = browserAccessibility_->manager();
+ BrowserAccessibilityManager* manager = owner_->manager();
NSNumber* focusedNumber = value;
BOOL focused = [focusedNumber intValue];
if (focused)
- manager->SetFocus(*browserAccessibility_);
+ manager->SetFocus(*owner_);
}
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
NSRange range = [(NSValue*)value rangeValue];
- BrowserAccessibilityManager* manager = browserAccessibility_->manager();
- manager->SetSelection(AXPlatformRange(
- browserAccessibility_->CreatePositionAt(range.location),
- browserAccessibility_->CreatePositionAt(NSMaxRange(range))));
+ BrowserAccessibilityManager* manager = owner_->manager();
+ manager->SetSelection(
+ AXPlatformRange(owner_->CreatePositionAt(range.location),
+ owner_->CreatePositionAt(NSMaxRange(range))));
}
}
@@ -3235,7 +3310,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
- BrowserAccessibilityManager* manager = browserAccessibility_->manager();
+ BrowserAccessibilityManager* manager = owner_->manager();
gfx::Point screen_point(point.x, point.y);
screen_point += manager->GetViewBounds().OffsetFromOrigin();
@@ -3256,7 +3331,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// Potentially called during dealloc.
if (![self instanceActive])
return [super hash];
- return browserAccessibility_->GetId();
+ return owner_->GetId();
}
- (BOOL)accessibilityNotifiesWhenDestroyed {
diff --git a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
index 0cd7fd5a2d0..ce687913fb2 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -4,9 +4,6 @@
#include "content/browser/accessibility/browser_accessibility_com_win.h"
-#include <UIAutomationClient.h>
-#include <UIAutomationCoreApi.h>
-
#include <algorithm>
#include <iterator>
#include <utility>
@@ -1550,97 +1547,10 @@ STDMETHODIMP BrowserAccessibilityComWin::QueryService(REFGUID guid_service,
return QueryInterface(riid, object);
}
- // We only support the IAccessibleEx interface on Windows 8 and above. This
- // is needed for the on-screen Keyboard to show up in metro mode, when the
- // user taps an editable portion on the page.
- // All methods in the IAccessibleEx interface are unimplemented.
- if (riid == IID_IAccessibleEx &&
- base::win::GetVersion() >= base::win::VERSION_WIN8) {
- return QueryInterface(riid, object);
- }
-
*object = NULL;
return E_FAIL;
}
-STDMETHODIMP
-BrowserAccessibilityComWin::GetObjectForChild(long child_id,
- IAccessibleEx** ret) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_OBJECT_FOR_CHILD);
- return E_NOTIMPL;
-}
-
-STDMETHODIMP
-BrowserAccessibilityComWin::GetIAccessiblePair(IAccessible** acc,
- long* child_id) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_IACCESSIBLE_PAIR);
- return E_NOTIMPL;
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::GetRuntimeId(SAFEARRAY** runtime_id) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_RUNTIME_ID);
- return E_NOTIMPL;
-}
-
-STDMETHODIMP
-BrowserAccessibilityComWin::ConvertReturnedElement(
- IRawElementProviderSimple* element,
- IAccessibleEx** acc) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_CONVERT_RETURNED_ELEMENT);
- return E_NOTIMPL;
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::GetPatternProvider(
- PATTERNID id,
- IUnknown** provider) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_PATTERN_PROVIDER);
- DVLOG(1) << "In Function: " << __func__ << " for pattern id: " << id;
- if (!owner())
- return E_FAIL;
-
- if (id == UIA_ValuePatternId || id == UIA_TextPatternId) {
- if (owner()->HasState(ax::mojom::State::kEditable)) {
- DVLOG(1) << "Returning UIA text provider";
- base::win::UIATextProvider::CreateTextProvider(GetRangeValueText(), true,
- provider);
- return S_OK;
- }
- }
- return E_NOTIMPL;
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::GetPropertyValue(PROPERTYID id,
- VARIANT* ret) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_PROPERTY_VALUE);
- DVLOG(1) << "In Function: " << __func__ << " for property id: " << id;
- if (!owner())
- return E_FAIL;
-
- V_VT(ret) = VT_EMPTY;
- if (id == UIA_ControlTypePropertyId) {
- if (owner()->HasState(ax::mojom::State::kEditable)) {
- V_VT(ret) = VT_I4;
- ret->lVal = UIA_EditControlTypeId;
- DVLOG(1) << "Returning Edit control type";
- } else {
- DVLOG(1) << "Returning empty control type";
- }
- }
- return S_OK;
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_ProviderOptions(
- ProviderOptions* ret) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_PROVIDER_OPTIONS);
- return E_NOTIMPL;
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_HostRawElementProvider(
- IRawElementProviderSimple** provider) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_HOST_RAW_ELEMENT_PROVIDER);
- return E_NOTIMPL;
-}
-
//
// CComObjectRootEx methods.
//
@@ -1807,16 +1717,26 @@ void BrowserAccessibilityComWin::UpdateStep2ComputeHypertext() {
void BrowserAccessibilityComWin::UpdateStep3FireEvents(
bool is_subtree_creation) {
+ int32_t state = MSAAState();
+
// Fire an event when a new subtree is created.
if (is_subtree_creation)
FireNativeEvent(EVENT_OBJECT_SHOW);
// The rest of the events only fire on changes, not on new objects.
+
+ bool did_fire_namechange = false;
+
if (old_win_attributes_->ia_role != 0 ||
!old_win_attributes_->role_name.empty()) {
// Fire an event if the name, description, help, or value changes.
- if (name() != old_win_attributes_->name)
+ if (name() != old_win_attributes_->name &&
+ GetData().GetNameFrom() != ax::mojom::NameFrom::kContents) {
+ // Only fire name changes when the name comes from an attribute, otherwise
+ // name changes are redundant with text removed/inserted events.
FireNativeEvent(EVENT_OBJECT_NAMECHANGE);
+ did_fire_namechange = true;
+ }
if (description() != old_win_attributes_->description)
FireNativeEvent(EVENT_OBJECT_DESCRIPTIONCHANGE);
if (value() != old_win_attributes_->value)
@@ -1824,14 +1744,14 @@ void BrowserAccessibilityComWin::UpdateStep3FireEvents(
// Do not fire EVENT_OBJECT_STATECHANGE if the change was due to a focus
// change.
- if ((MSAAState() & ~STATE_SYSTEM_FOCUSED) !=
+ if ((state & ~STATE_SYSTEM_FOCUSED) !=
(old_win_attributes_->ia_state & ~STATE_SYSTEM_FOCUSED) ||
ComputeIA2State() != old_win_attributes_->ia2_state) {
FireNativeEvent(EVENT_OBJECT_STATECHANGE);
}
// Handle selection being added or removed.
- bool is_selected_now = (MSAAState() & STATE_SYSTEM_SELECTED) != 0;
+ bool is_selected_now = (state & STATE_SYSTEM_SELECTED) != 0;
bool was_selected_before =
(old_win_attributes_->ia_state & STATE_SYSTEM_SELECTED) != 0;
if (is_selected_now || was_selected_before) {
@@ -1866,17 +1786,22 @@ void BrowserAccessibilityComWin::UpdateStep3FireEvents(
}
// Fire hypertext-related events.
- int start, old_len, new_len;
- ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len);
- if (old_len > 0) {
- // In-process screen readers may call IAccessibleText::get_oldText
- // in reaction to this event to retrieve the text that was removed.
- FireNativeEvent(IA2_EVENT_TEXT_REMOVED);
- }
- if (new_len > 0) {
- // In-process screen readers may call IAccessibleText::get_newText
- // in reaction to this event to retrieve the text that was inserted.
- FireNativeEvent(IA2_EVENT_TEXT_INSERTED);
+ // Do not fire removed/inserted when a name change event was also fired, as
+ // they are providing redundant information and will lead to duplicate
+ // announcements.
+ if (!did_fire_namechange) {
+ int start, old_len, new_len;
+ ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len);
+ if (old_len > 0) {
+ // In-process screen readers may call IAccessibleText::get_oldText
+ // in reaction to this event to retrieve the text that was removed.
+ FireNativeEvent(IA2_EVENT_TEXT_REMOVED);
+ }
+ if (new_len > 0) {
+ // In-process screen readers may call IAccessibleText::get_newText
+ // in reaction to this event to retrieve the text that was inserted.
+ FireNativeEvent(IA2_EVENT_TEXT_INSERTED);
+ }
}
// Changing a static text node can affect the IA2 hypertext of its parent
diff --git a/chromium/content/browser/accessibility/browser_accessibility_com_win.h b/chromium/content/browser/accessibility/browser_accessibility_com_win.h
index debd107f060..4ce9c39ccf7 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.h
@@ -12,8 +12,6 @@
#include <stdint.h>
#include <vector>
-#include <UIAutomationCore.h>
-
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -69,19 +67,15 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
public IAccessibleValue,
public ISimpleDOMDocument,
public ISimpleDOMNode,
- public ISimpleDOMText,
- public IAccessibleEx,
- public IRawElementProviderSimple {
+ public ISimpleDOMText {
public:
BEGIN_COM_MAP(BrowserAccessibilityComWin)
COM_INTERFACE_ENTRY(IAccessibleAction)
COM_INTERFACE_ENTRY(IAccessibleApplication)
- COM_INTERFACE_ENTRY(IAccessibleEx)
COM_INTERFACE_ENTRY(IAccessibleHyperlink)
COM_INTERFACE_ENTRY(IAccessibleHypertext)
COM_INTERFACE_ENTRY(IAccessibleImage)
COM_INTERFACE_ENTRY(IAccessibleValue)
- COM_INTERFACE_ENTRY(IRawElementProviderSimple)
COM_INTERFACE_ENTRY(ISimpleDOMDocument)
COM_INTERFACE_ENTRY(ISimpleDOMNode)
COM_INTERFACE_ENTRY(ISimpleDOMText)
@@ -378,37 +372,6 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
REFIID riid,
void** object) override;
- // IAccessibleEx methods not implemented.
- CONTENT_EXPORT STDMETHODIMP GetObjectForChild(long child_id,
- IAccessibleEx** ret) override;
-
- CONTENT_EXPORT STDMETHODIMP GetIAccessiblePair(IAccessible** acc,
- long* child_id) override;
-
- CONTENT_EXPORT STDMETHODIMP GetRuntimeId(SAFEARRAY** runtime_id) override;
-
- CONTENT_EXPORT STDMETHODIMP
- ConvertReturnedElement(IRawElementProviderSimple* element,
- IAccessibleEx** acc) override;
-
- //
- // IRawElementProviderSimple methods.
- //
- // The GetPatternProvider/GetPropertyValue methods need to be implemented for
- // the on-screen keyboard to show up in Windows 8 metro.
- CONTENT_EXPORT STDMETHODIMP GetPatternProvider(PATTERNID id,
- IUnknown** provider) override;
- CONTENT_EXPORT STDMETHODIMP GetPropertyValue(PROPERTYID id,
- VARIANT* ret) override;
-
- //
- // IRawElementProviderSimple methods not implemented
- //
- CONTENT_EXPORT STDMETHODIMP
- get_ProviderOptions(enum ProviderOptions* ret) override;
- CONTENT_EXPORT STDMETHODIMP
- get_HostRawElementProvider(IRawElementProviderSimple** provider) override;
-
//
// CComObjectRootEx methods.
//
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac.h b/chromium/content/browser/accessibility/browser_accessibility_mac.h
index d5160243274..d2cc8d75974 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac.h
@@ -30,6 +30,8 @@ class BrowserAccessibilityMac : public BrowserAccessibility {
void NativeReleaseReference() override;
bool IsNative() const override;
void OnDataChanged() override;
+ uint32_t PlatformChildCount() const override;
+ BrowserAccessibility* PlatformGetChild(uint32_t child_index) const override;
// The BrowserAccessibilityCocoa associated with us.
BrowserAccessibilityCocoa* native_view() const {
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_mac.mm
index 34475bdc309..1c5d9171a4f 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac.mm
@@ -8,6 +8,7 @@
#import "content/browser/accessibility/browser_accessibility_cocoa.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
+#include "ui/accessibility/ax_table_info.h"
namespace content {
@@ -48,6 +49,39 @@ void BrowserAccessibilityMac::OnDataChanged() {
[[BrowserAccessibilityCocoa alloc] initWithObject:this];
}
+uint32_t BrowserAccessibilityMac::PlatformChildCount() const {
+ uint32_t child_count = BrowserAccessibility::PlatformChildCount();
+
+ // If this is a table, include the extra fake nodes generated by
+ // AXTableInfo, for the column nodes and the table header container, all of
+ // which are only important on macOS.
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (!table_info)
+ return child_count;
+
+ return child_count + table_info->extra_mac_nodes.size();
+}
+
+BrowserAccessibility* BrowserAccessibilityMac::PlatformGetChild(
+ uint32_t child_index) const {
+ uint32_t child_count = BrowserAccessibility::PlatformChildCount();
+ if (child_index < child_count)
+ return BrowserAccessibility::PlatformGetChild(child_index);
+
+ // If this is a table, include the extra fake nodes generated by
+ // AXTableInfo, for the column nodes and the table header container, all of
+ // which are only important on macOS.
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (!table_info)
+ return nullptr;
+
+ child_index -= child_count;
+ if (child_index < table_info->extra_mac_nodes.size())
+ return manager_->GetFromAXNode(table_info->extra_mac_nodes[child_index]);
+
+ return nullptr;
+}
+
void BrowserAccessibilityMac::RecreateNativeObject() {
if (!browser_accessibility_cocoa_)
return;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
index 217faec21d1..afdf10051f3 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
@@ -23,7 +23,51 @@
namespace content {
-class BrowserAccessibilityTest : public ui::CocoaTest {
+namespace {
+
+void MakeTable(ui::AXNodeData* table, int id, int row_count, int col_count) {
+ table->id = id;
+ table->role = ax::mojom::Role::kTable;
+ table->AddIntAttribute(ax::mojom::IntAttribute::kTableRowCount, row_count);
+ table->AddIntAttribute(ax::mojom::IntAttribute::kTableColumnCount, col_count);
+}
+
+void MakeRow(ui::AXNodeData* row, int id) {
+ row->id = id;
+ row->role = ax::mojom::Role::kRow;
+}
+
+void MakeCell(ui::AXNodeData* cell,
+ int id,
+ int row_index,
+ int col_index,
+ int row_span = 1,
+ int col_span = 1) {
+ cell->id = id;
+ cell->role = ax::mojom::Role::kCell;
+ cell->AddIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex, row_index);
+ cell->AddIntAttribute(ax::mojom::IntAttribute::kTableCellColumnIndex,
+ col_index);
+ if (row_span > 1)
+ cell->AddIntAttribute(ax::mojom::IntAttribute::kTableCellRowSpan, row_span);
+ if (col_span > 1)
+ cell->AddIntAttribute(ax::mojom::IntAttribute::kTableCellColumnSpan,
+ col_span);
+}
+
+void MakeColumnHeader(ui::AXNodeData* cell,
+ int id,
+ int row_index,
+ int col_index,
+ int row_span = 1,
+ int col_span = 1) {
+ MakeCell(cell, id, row_index, col_index, row_span, col_span);
+ cell->role = ax::mojom::Role::kColumnHeader;
+}
+
+} // namespace
+
+class BrowserAccessibilityMacTest : public ui::CocoaTest {
public:
void SetUp() override {
CocoaTest::SetUp();
@@ -68,12 +112,10 @@ class BrowserAccessibilityTest : public ui::CocoaTest {
if (!manager_)
return;
root_.SetValue(value);
- AXEventNotificationDetails param;
- param.update.nodes.push_back(root_);
- param.event_type = ax::mojom::Event::kValueChanged;
- param.id = root_.id;
- std::vector<AXEventNotificationDetails> events{param};
- manager_->OnAccessibilityEvents(events);
+ AXEventNotificationDetails event_bundle;
+ event_bundle.updates.resize(1);
+ event_bundle.updates[0].nodes.push_back(root_);
+ manager_->OnAccessibilityEvents(event_bundle);
}
ui::AXNodeData root_;
@@ -82,7 +124,7 @@ class BrowserAccessibilityTest : public ui::CocoaTest {
};
// Standard hit test.
-TEST_F(BrowserAccessibilityTest, HitTestTest) {
+TEST_F(BrowserAccessibilityMacTest, HitTestTest) {
BrowserAccessibilityCocoa* firstChild =
[accessibility_ accessibilityHitTest:NSMakePoint(50, 50)];
EXPECT_NSEQ(@"Child1",
@@ -91,7 +133,7 @@ TEST_F(BrowserAccessibilityTest, HitTestTest) {
}
// Test doing a hit test on the edge of a child.
-TEST_F(BrowserAccessibilityTest, EdgeHitTest) {
+TEST_F(BrowserAccessibilityMacTest, EdgeHitTest) {
BrowserAccessibilityCocoa* firstChild =
[accessibility_ accessibilityHitTest:NSZeroPoint];
EXPECT_NSEQ(@"Child1",
@@ -102,27 +144,27 @@ TEST_F(BrowserAccessibilityTest, EdgeHitTest) {
// This will test a hit test with invalid coordinates. It is assumed that
// the hit test has been narrowed down to this object or one of its children
// so it should return itself since it has no better hit result.
-TEST_F(BrowserAccessibilityTest, InvalidHitTestCoordsTest) {
+TEST_F(BrowserAccessibilityMacTest, InvalidHitTestCoordsTest) {
BrowserAccessibilityCocoa* hitTestResult =
[accessibility_ accessibilityHitTest:NSMakePoint(-50, 50)];
EXPECT_NSEQ(accessibility_, hitTestResult);
}
// Test to ensure querying standard attributes works.
-TEST_F(BrowserAccessibilityTest, BasicAttributeTest) {
+TEST_F(BrowserAccessibilityMacTest, BasicAttributeTest) {
NSString* helpText = [accessibility_
accessibilityAttributeValue:NSAccessibilityHelpAttribute];
EXPECT_NSEQ(@"HelpText", helpText);
}
// Test querying for an invalid attribute to ensure it doesn't crash.
-TEST_F(BrowserAccessibilityTest, InvalidAttributeTest) {
+TEST_F(BrowserAccessibilityMacTest, InvalidAttributeTest) {
NSString* shouldBeNil = [accessibility_
accessibilityAttributeValue:@"NSAnInvalidAttribute"];
EXPECT_TRUE(shouldBeNil == nil);
}
-TEST_F(BrowserAccessibilityTest, RetainedDetachedObjectsReturnNil) {
+TEST_F(BrowserAccessibilityMacTest, RetainedDetachedObjectsReturnNil) {
// Get the first child.
BrowserAccessibilityCocoa* retainedFirstChild =
[accessibility_ accessibilityHitTest:NSMakePoint(50, 50)];
@@ -144,9 +186,9 @@ TEST_F(BrowserAccessibilityTest, RetainedDetachedObjectsReturnNil) {
[retainedFirstChild release];
}
-TEST_F(BrowserAccessibilityTest, TestComputeTextEdit) {
- BrowserAccessibility* wrapper = [accessibility_ browserAccessibility];
- ASSERT_NE(nullptr, wrapper);
+TEST_F(BrowserAccessibilityMacTest, TestComputeTextEdit) {
+ BrowserAccessibility* owner = [accessibility_ owner];
+ ASSERT_NE(nullptr, owner);
// Insertion but no deletion.
@@ -212,4 +254,51 @@ TEST_F(BrowserAccessibilityTest, TestComputeTextEdit) {
EXPECT_EQ(base::UTF8ToUTF16("old"), text_edit.inserted_text);
}
+// Test Mac-specific table APIs.
+TEST_F(BrowserAccessibilityMacTest, TableAPIs) {
+ ui::AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(7);
+ MakeTable(&initial_state.nodes[0], 1, 0, 0);
+ initial_state.nodes[0].child_ids = {2, 3};
+ MakeRow(&initial_state.nodes[1], 2);
+ initial_state.nodes[1].child_ids = {4, 5};
+ MakeRow(&initial_state.nodes[2], 3);
+ initial_state.nodes[2].child_ids = {6, 7};
+ MakeColumnHeader(&initial_state.nodes[3], 4, 0, 0);
+ MakeColumnHeader(&initial_state.nodes[4], 5, 0, 1);
+ MakeCell(&initial_state.nodes[5], 6, 1, 0);
+ MakeCell(&initial_state.nodes[6], 7, 1, 1);
+
+ manager_.reset(new BrowserAccessibilityManagerMac(initial_state, nullptr));
+ base::scoped_nsobject<BrowserAccessibilityCocoa> ax_table_(
+ [ToBrowserAccessibilityCocoa(manager_->GetRoot()) retain]);
+ id children = [ax_table_ children];
+ EXPECT_EQ(5U, [children count]);
+
+ EXPECT_NSEQ(@"AXRow", [children[0] role]);
+ EXPECT_EQ(2U, [[children[0] children] count]);
+
+ EXPECT_NSEQ(@"AXRow", [children[1] role]);
+ EXPECT_EQ(2U, [[children[1] children] count]);
+
+ EXPECT_NSEQ(@"AXColumn", [children[2] role]);
+ EXPECT_EQ(2U, [[children[2] children] count]);
+ id col_children = [children[2] children];
+ EXPECT_NSEQ(@"AXCell", [col_children[0] role]);
+ EXPECT_NSEQ(@"AXCell", [col_children[1] role]);
+
+ EXPECT_NSEQ(@"AXColumn", [children[3] role]);
+ EXPECT_EQ(2U, [[children[3] children] count]);
+ col_children = [children[3] children];
+ EXPECT_NSEQ(@"AXCell", [col_children[0] role]);
+ EXPECT_NSEQ(@"AXCell", [col_children[1] role]);
+
+ EXPECT_NSEQ(@"AXGroup", [children[4] role]);
+ EXPECT_EQ(2U, [[children[4] children] count]);
+ col_children = [children[4] children];
+ EXPECT_NSEQ(@"AXCell", [col_children[0] role]);
+ EXPECT_NSEQ(@"AXCell", [col_children[1] role]);
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index f15f0305256..2cfe76080a1 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -351,7 +351,7 @@ bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() {
}
void BrowserAccessibilityManager::OnAccessibilityEvents(
- const std::vector<AXEventNotificationDetails>& details) {
+ const AXEventNotificationDetails& details) {
TRACE_EVENT0("accessibility",
"BrowserAccessibilityManager::OnAccessibilityEvents");
@@ -360,9 +360,8 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
device_scale_factor_ = delegate_->AccessibilityGetDeviceScaleFactor();
// Process all changes to the accessibility tree first.
- for (uint32_t index = 0; index < details.size(); ++index) {
- const AXEventNotificationDetails& detail = details[index];
- if (!tree_->Unserialize(detail.update)) {
+ for (uint32_t index = 0; index < details.updates.size(); ++index) {
+ if (!tree_->Unserialize(details.updates[index])) {
if (delegate_) {
LOG(ERROR) << tree_->error();
delegate_->AccessibilityFatalError();
@@ -405,23 +404,23 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
if (!event_target)
continue;
- FireGeneratedEvent(targeted_event.event, event_target);
+ FireGeneratedEvent(targeted_event.event_params.event, event_target);
}
ClearEvents();
// Fire events from Blink.
- for (uint32_t index = 0; index < details.size(); index++) {
- const AXEventNotificationDetails& detail = details[index];
+ for (uint32_t index = 0; index < details.events.size(); index++) {
+ const ui::AXEvent& event = details.events[index];
// Fire the native event.
- BrowserAccessibility* event_target = GetFromID(detail.id);
+ BrowserAccessibility* event_target = GetFromID(event.id);
if (!event_target)
return;
- if (detail.event_type == ax::mojom::Event::kHover)
+ if (event.event_type == ax::mojom::Event::kHover)
GetRootManager()->CacheHitTestResult(event_target);
- FireBlinkEvent(detail.event_type, event_target);
+ FireBlinkEvent(event.event_type, event_target);
}
}
@@ -674,9 +673,8 @@ void BrowserAccessibilityManager::SetScrollOffset(
delegate_->AccessibilityPerformAction(action_data);
}
-void BrowserAccessibilityManager::SetValue(
- const BrowserAccessibility& node,
- const base::string16& value) {
+void BrowserAccessibilityManager::SetValue(const BrowserAccessibility& node,
+ const std::string& value) {
if (!delegate_)
return;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index b1b47d25878..6279fdbe5f5 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <memory>
+#include <string>
#include <vector>
#include "base/callback_forward.h"
@@ -218,8 +219,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
void SetAccessibilityFocus(const BrowserAccessibility& node);
void SetFocus(const BrowserAccessibility& node);
void SetScrollOffset(const BrowserAccessibility& node, gfx::Point offset);
- void SetValue(
- const BrowserAccessibility& node, const base::string16& value);
+ void SetValue(const BrowserAccessibility& node, const std::string& value);
void SetSelection(
ui::AXRange<
BrowserAccessibilityPosition::AXPositionInstance::element_type>
@@ -234,8 +234,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
void ActivateFindInPageResult(int request_id, int match_index);
// Called when the renderer process has notified us of about tree changes.
- virtual void OnAccessibilityEvents(
- const std::vector<AXEventNotificationDetails>& details);
+ virtual void OnAccessibilityEvents(const AXEventNotificationDetails& details);
// Called when the renderer process updates the location of accessibility
// objects. Calls SendLocationChangeEvents(), which can be overridden.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
index 8f88334ea98..2d97c89fa38 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -41,7 +41,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
BrowserAccessibility* node) override;
void OnAccessibilityEvents(
- const std::vector<AXEventNotificationDetails>& details) override;
+ const AXEventNotificationDetails& details) override;
NSView* GetParentView();
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 134f855de65..8e32a082260 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -125,6 +125,7 @@ BrowserAccessibilityManagerMac::BrowserAccessibilityManagerMac(
BrowserAccessibilityFactory* factory)
: BrowserAccessibilityManager(delegate, factory) {
Initialize(initial_tree);
+ tree_->SetEnableExtraMacNodes(true);
}
BrowserAccessibilityManagerMac::~BrowserAccessibilityManagerMac() {}
@@ -144,15 +145,10 @@ ui::AXTreeUpdate
BrowserAccessibility* BrowserAccessibilityManagerMac::GetFocus() {
BrowserAccessibility* focus = BrowserAccessibilityManager::GetFocus();
- // On Mac, list boxes should always get focus on the whole list, otherwise
- // information about the number of selected items will never be reported.
// For editable combo boxes, focus should stay on the combo box so the user
// will not be taken out of the combo box while typing.
- if (focus &&
- (focus->GetRole() == ax::mojom::Role::kListBox ||
- (focus->GetRole() == ax::mojom::Role::kTextFieldWithComboBox))) {
+ if (focus && focus->GetRole() == ax::mojom::Role::kTextFieldWithComboBox)
return focus;
- }
// For other roles, follow the active descendant.
return GetActiveDescendant(focus);
@@ -386,7 +382,7 @@ void BrowserAccessibilityManagerMac::FireNativeMacNotification(
}
void BrowserAccessibilityManagerMac::OnAccessibilityEvents(
- const std::vector<AXEventNotificationDetails>& details) {
+ const AXEventNotificationDetails& details) {
text_edits_.clear();
// Call the base method last as it might delete the tree if it receives an
// invalid message.
@@ -415,7 +411,7 @@ void BrowserAccessibilityManagerMac::OnAtomicUpdateFinished(
DCHECK(obj);
const AXTextEdit text_edit = [obj computeTextEdit];
if (!text_edit.IsEmpty())
- text_edits_[[obj browserAccessibility]->GetId()] = text_edit;
+ text_edits_[[obj owner]->GetId()] = text_edit;
}
}
@@ -489,10 +485,7 @@ BrowserAccessibilityManagerMac::GetUserInfoForValueChangedNotification(
}
NSView* BrowserAccessibilityManagerMac::GetParentView() {
- gfx::AcceleratedWidget accelerated_widget =
- delegate() ? delegate()->AccessibilityGetAcceleratedWidget()
- : gfx::kNullAcceleratedWidget;
- return ui::AcceleratedWidgetMac::GetNSView(accelerated_widget);
+ return delegate()->AccessibilityGetNativeViewAccessible();
}
} // 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 dcd5699b675..80c55653e84 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -238,14 +238,11 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) {
EXPECT_EQ(2, child3_accessible->GetIndexInParent());
// Process a notification containing the changed subtree.
- std::vector<AXEventNotificationDetails> params;
- params.push_back(AXEventNotificationDetails());
- AXEventNotificationDetails* msg = &params[0];
- msg->event_type = ax::mojom::Event::kChildrenChanged;
- msg->update.nodes.push_back(tree2_root);
- msg->update.nodes.push_back(tree2_child0);
- msg->id = tree2_root.id;
- manager->OnAccessibilityEvents(params);
+ AXEventNotificationDetails notification;
+ notification.updates.resize(1);
+ notification.updates[0].nodes.push_back(tree2_root);
+ notification.updates[0].nodes.push_back(tree2_child0);
+ manager->OnAccessibilityEvents(notification);
// There should be 5 objects now: the 4 from the new tree, plus the
// reference to child3 we kept.
@@ -403,15 +400,12 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
// Process a notification containing the changed subtree rooted at
// the container.
- std::vector<AXEventNotificationDetails> params;
- params.push_back(AXEventNotificationDetails());
- AXEventNotificationDetails* msg = &params[0];
- msg->event_type = ax::mojom::Event::kChildrenChanged;
- msg->update.nodes.push_back(tree2_container);
- msg->update.nodes.push_back(tree2_child0);
- msg->update.nodes.push_back(tree2_grandchild0);
- msg->id = tree2_container.id;
- manager->OnAccessibilityEvents(params);
+ AXEventNotificationDetails notification;
+ notification.updates.resize(1);
+ notification.updates[0].nodes.push_back(tree2_container);
+ notification.updates[0].nodes.push_back(tree2_child0);
+ notification.updates[0].nodes.push_back(tree2_grandchild0);
+ manager->OnAccessibilityEvents(notification);
// There should be 9 objects now: the 8 from the new tree, plus the
// reference to child3 we kept.
@@ -501,16 +495,13 @@ TEST(BrowserAccessibilityManagerTest, TestMoveChildUp) {
ASSERT_EQ(4, CountedBrowserAccessibility::global_obj_count_);
// Process a notification containing the changed subtree.
- std::vector<AXEventNotificationDetails> params;
- params.push_back(AXEventNotificationDetails());
- AXEventNotificationDetails* msg = &params[0];
- msg->event_type = ax::mojom::Event::kChildrenChanged;
- msg->update.nodes.push_back(tree2_1);
- msg->update.nodes.push_back(tree2_4);
- msg->update.nodes.push_back(tree2_5);
- msg->update.nodes.push_back(tree2_6);
- msg->id = tree2_1.id;
- manager->OnAccessibilityEvents(params);
+ AXEventNotificationDetails notification;
+ notification.updates.resize(1);
+ notification.updates[0].nodes.push_back(tree2_1);
+ notification.updates[0].nodes.push_back(tree2_4);
+ notification.updates[0].nodes.push_back(tree2_5);
+ notification.updates[0].nodes.push_back(tree2_6);
+ manager->OnAccessibilityEvents(notification);
// There should be 4 objects now.
EXPECT_EQ(4, CountedBrowserAccessibility::global_obj_count_);
@@ -1515,11 +1506,9 @@ TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash) {
root2.id = 3;
root2.role = ax::mojom::Role::kRootWebArea;
- std::vector<AXEventNotificationDetails> events2;
- events2.push_back(AXEventNotificationDetails());
- events2[0].update = MakeAXTreeUpdate(root2);
- events2[0].id = -1;
- events2[0].event_type = ax::mojom::Event::kNone;
+ AXEventNotificationDetails events2;
+ events2.updates.resize(1);
+ events2.updates[0] = MakeAXTreeUpdate(root2);
manager->OnAccessibilityEvents(events2);
// Make sure that the focused node was updated to the new root and
@@ -1562,12 +1551,10 @@ TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash2) {
root2.role = ax::mojom::Role::kRootWebArea;
// Make an update the explicitly clears the previous root.
- std::vector<AXEventNotificationDetails> events2;
- events2.push_back(AXEventNotificationDetails());
- events2[0].update = MakeAXTreeUpdate(root2);
- events2[0].update.node_id_to_clear = 1;
- events2[0].id = -1;
- events2[0].event_type = ax::mojom::Event::kNone;
+ AXEventNotificationDetails events2;
+ events2.updates.resize(1);
+ events2.updates[0] = MakeAXTreeUpdate(root2);
+ events2.updates[0].node_id_to_clear = 1;
manager->OnAccessibilityEvents(events2);
// Make sure that the focused node was updated to the new root and
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index ea5cf31693a..2251fd1696d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -151,7 +151,10 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
FireWinAccessibilityEvent(EVENT_OBJECT_REORDER, node);
break;
case Event::LIVE_REGION_CHANGED:
- FireWinAccessibilityEvent(EVENT_OBJECT_LIVEREGIONCHANGED, node);
+ // NVDA and JAWS are inconsistent about speaking this event in content.
+ // Because of this, and because Firefox does not currently fire it, we
+ // are avoiding this event for now.
+ // FireWinAccessibilityEvent(EVENT_OBJECT_LIVEREGIONCHANGED, node);
break;
case Event::LOAD_COMPLETE:
FireWinAccessibilityEvent(IA2_EVENT_DOCUMENT_LOAD_COMPLETE, node);
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index f81b59ee00a..611d6959723 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -166,13 +166,10 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
text2.id = 2;
text2.role = ax::mojom::Role::kStaticText;
text2.SetName("new text");
- AXEventNotificationDetails param;
- param.event_type = ax::mojom::Event::kChildrenChanged;
- param.update.nodes.push_back(text2);
- param.id = text2.id;
- std::vector<AXEventNotificationDetails> events;
- events.push_back(param);
- manager->OnAccessibilityEvents(events);
+ AXEventNotificationDetails event_bundle;
+ event_bundle.updates.resize(1);
+ event_bundle.updates[0].nodes.push_back(text2);
+ manager->OnAccessibilityEvents(event_bundle);
// Query for the text IAccessible and verify that it now returns "new text"
// as its value.
@@ -232,13 +229,10 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
// Notify the BrowserAccessibilityManager that the div node and its children
// were removed and ensure that only one BrowserAccessibility instance exists.
root.child_ids.clear();
- AXEventNotificationDetails param;
- param.event_type = ax::mojom::Event::kChildrenChanged;
- param.update.nodes.push_back(root);
- param.id = root.id;
- std::vector<AXEventNotificationDetails> events;
- events.push_back(param);
- manager->OnAccessibilityEvents(events);
+ AXEventNotificationDetails event_bundle;
+ event_bundle.updates.resize(1);
+ event_bundle.updates[0].nodes.push_back(root);
+ manager->OnAccessibilityEvents(event_bundle);
// Delete the manager and test that all BrowserAccessibility instances are
// deleted.
@@ -659,15 +653,12 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
tree1_2.role = ax::mojom::Role::kTextField;
// Process a load complete.
- std::vector<AXEventNotificationDetails> params;
- params.push_back(AXEventNotificationDetails());
- AXEventNotificationDetails* msg = &params[0];
- msg->event_type = ax::mojom::Event::kLoadComplete;
- msg->update.root_id = tree1_1.id;
- msg->update.nodes.push_back(tree1_1);
- msg->update.nodes.push_back(tree1_2);
- msg->id = tree1_1.id;
- manager->OnAccessibilityEvents(params);
+ AXEventNotificationDetails event_bundle;
+ event_bundle.updates.resize(1);
+ event_bundle.updates[0].root_id = tree1_1.id;
+ event_bundle.updates[0].nodes.push_back(tree1_1);
+ event_bundle.updates[0].nodes.push_back(tree1_2);
+ manager->OnAccessibilityEvents(event_bundle);
// Save for later comparison.
BrowserAccessibility* acc1_2 = manager->GetFromID(2);
@@ -689,13 +680,12 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
tree2_2.id = 3;
tree2_2.role = ax::mojom::Role::kButton;
- msg->update.nodes.clear();
- msg->update.nodes.push_back(tree2_1);
- msg->update.nodes.push_back(tree2_2);
- msg->id = tree2_1.id;
+ event_bundle.updates[0].nodes.clear();
+ event_bundle.updates[0].nodes.push_back(tree2_1);
+ event_bundle.updates[0].nodes.push_back(tree2_2);
// Fire another load complete.
- manager->OnAccessibilityEvents(params);
+ manager->OnAccessibilityEvents(event_bundle);
BrowserAccessibility* acc2_2 = manager->GetFromID(3);
@@ -2491,12 +2481,10 @@ TEST_F(BrowserAccessibilityTest, TestIAccessible2Relations) {
std::vector<int32_t> labelledby_ids = {3};
child1.AddIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds,
labelledby_ids);
- AXEventNotificationDetails event;
- event.event_type = ax::mojom::Event::kAriaAttributeChanged;
- event.update.nodes.push_back(child1);
- event.id = child1.id;
- std::vector<AXEventNotificationDetails> events = {event};
- manager->OnAccessibilityEvents(events);
+ AXEventNotificationDetails event_bundle;
+ event_bundle.updates.resize(1);
+ event_bundle.updates[0].nodes.push_back(child1);
+ manager->OnAccessibilityEvents(event_bundle);
EXPECT_HRESULT_SUCCEEDED(ax_child1->GetCOM()->get_nRelations(&n_relations));
EXPECT_EQ(2, n_relations);
diff --git a/chromium/content/browser/accessibility/captioning_controller.cc b/chromium/content/browser/accessibility/captioning_controller.cc
index f0511fc03ae..0bd9b69d539 100644
--- a/chromium/content/browser/accessibility/captioning_controller.cc
+++ b/chromium/content/browser/accessibility/captioning_controller.cc
@@ -23,7 +23,7 @@ int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
DCHECK(host);
RenderProcessHost* render_process = host->GetProcess();
DCHECK(render_process);
- if (render_process->HasConnection())
+ if (render_process->IsInitializedAndNotDead())
return render_process->GetProcess().Handle();
return 0;
}
diff --git a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 6a812bdaa34..4541b57ade6 100644
--- a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -254,54 +254,8 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
}
IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
- MultipleInheritanceAccessibility) {
- // In a WebKit accessibility render tree for a table, each cell is a
- // child of both a row and a column, so it appears to use multiple
- // inheritance. Make sure that the ui::AXNodeDataObject tree only
- // keeps one copy of each cell, and uses an indirect child id for the
- // additional reference to it.
- const char url_str[] =
- "data:text/html,"
- "<!doctype html>"
- "<table border=1><tr><td>1</td><td>2</td></tr></table>";
- GURL url(url_str);
- NavigateToURL(shell(), url);
-
- const ui::AXTree& tree = GetAXTree();
- const ui::AXNode* root = tree.root();
- ASSERT_EQ(1, root->child_count());
- const ui::AXNode* table = root->ChildAtIndex(0);
- EXPECT_EQ(ax::mojom::Role::kTable, table->data().role);
- const ui::AXNode* row = table->ChildAtIndex(0);
- EXPECT_EQ(ax::mojom::Role::kRow, row->data().role);
- const ui::AXNode* cell1 = row->ChildAtIndex(0);
- EXPECT_EQ(ax::mojom::Role::kCell, cell1->data().role);
- const ui::AXNode* cell2 = row->ChildAtIndex(1);
- EXPECT_EQ(ax::mojom::Role::kCell, cell2->data().role);
- const ui::AXNode* column1 = table->ChildAtIndex(1);
- EXPECT_EQ(ax::mojom::Role::kColumn, column1->data().role);
- EXPECT_EQ(0, column1->child_count());
- EXPECT_EQ(1U, column1->data().intlist_attributes.size());
- EXPECT_EQ(ax::mojom::IntListAttribute::kIndirectChildIds,
- column1->data().intlist_attributes[0].first);
- const std::vector<int32_t> column1_indirect_child_ids =
- column1->data().intlist_attributes[0].second;
- EXPECT_EQ(1U, column1_indirect_child_ids.size());
- EXPECT_EQ(cell1->id(), column1_indirect_child_ids[0]);
- const ui::AXNode* column2 = table->ChildAtIndex(2);
- EXPECT_EQ(ax::mojom::Role::kColumn, column2->data().role);
- EXPECT_EQ(0, column2->child_count());
- EXPECT_EQ(ax::mojom::IntListAttribute::kIndirectChildIds,
- column2->data().intlist_attributes[0].first);
- const std::vector<int32_t> column2_indirect_child_ids =
- column2->data().intlist_attributes[0].second;
- EXPECT_EQ(1U, column2_indirect_child_ids.size());
- EXPECT_EQ(cell2->id(), column2_indirect_child_ids[0]);
-}
-
-IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
MultipleInheritanceAccessibility2) {
- // Here's another html snippet where WebKit puts the same node as a child
+ // Here's a html snippet where Blink puts the same node as a child
// of two different parents. Instead of checking the exact output, just
// make sure that no id is reused in the resulting tree.
const char url_str[] =
@@ -416,12 +370,9 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const ui::AXNode* root = tree.root();
const ui::AXNode* table = root->ChildAtIndex(0);
EXPECT_EQ(ax::mojom::Role::kTable, table->data().role);
- ASSERT_GE(table->child_count(), 5);
+ ASSERT_GE(table->child_count(), 2);
EXPECT_EQ(ax::mojom::Role::kRow, table->ChildAtIndex(0)->data().role);
EXPECT_EQ(ax::mojom::Role::kRow, table->ChildAtIndex(1)->data().role);
- EXPECT_EQ(ax::mojom::Role::kColumn, table->ChildAtIndex(2)->data().role);
- EXPECT_EQ(ax::mojom::Role::kColumn, table->ChildAtIndex(3)->data().role);
- EXPECT_EQ(ax::mojom::Role::kColumn, table->ChildAtIndex(4)->data().role);
EXPECT_EQ(3, GetIntAttr(table, ax::mojom::IntAttribute::kTableColumnCount));
EXPECT_EQ(2, GetIntAttr(table, ax::mojom::IntAttribute::kTableRowCount));
diff --git a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index 4d30edf5a69..bc91d524e85 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -195,6 +195,16 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaComboBoxDelayAddList) {
+ RunEventTest(FILE_PATH_LITERAL("aria-combo-box-delay-add-list.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaComboBoxDelayShowList) {
+ RunEventTest(FILE_PATH_LITERAL("aria-combo-box-delay-show-list.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
AccessibilityEventsAriaComboBoxNext) {
RunEventTest(FILE_PATH_LITERAL("aria-combo-box-next.html"));
}
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 263cc2387f5..b0c2af3f667 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -194,7 +194,11 @@ void DumpAccessibilityTreeTest::AddDefaultFilters(
AddFilter(filters, "FOCUSED", Filter::DENY);
AddFilter(filters, "HOTTRACKED", Filter::DENY);
AddFilter(filters, "OFFSCREEN", Filter::DENY);
- // Object attributes.
+ AddFilter(filters, "value='*'");
+ // The value attribute on the document object contains the URL of the current
+ // page which will not be the same every time the test is run.
+ AddFilter(filters, "value='http*'", Filter::DENY);
+ // Object attributes.value
AddFilter(filters, "layout-guess:*", Filter::ALLOW);
//
@@ -235,12 +239,14 @@ void DumpAccessibilityTreeTest::AddDefaultFilters(
AddFilter(filters, "invalidState=*");
AddFilter(filters, "invalidState=false",
Filter::DENY); // Don't show false value
+ AddFilter(filters, "roleDescription=*");
//
// OS X
//
- AddFilter(filters, "roleDescription=*");
+ AddFilter(filters, "AXValueAutofill*");
+ AddFilter(filters, "AXAutocomplete*");
//
// Android
@@ -287,6 +293,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunCSSTest(FILE_PATH_LITERAL("table-incomplete.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCSSTransform) {
+ RunCSSTest(FILE_PATH_LITERAL("transform.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityA) {
RunHtmlTest(FILE_PATH_LITERAL("a.html"));
}
@@ -548,6 +558,11 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaGrid) {
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaGridDynamicAddRow) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-grid-dynamic-add-row.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityAriaGridExtraWrapElems) {
RunAriaTest(FILE_PATH_LITERAL("aria-grid-extra-wrap-elems.html"));
}
@@ -980,7 +995,7 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBoundsInherits) {
RunHtmlTest(FILE_PATH_LITERAL("bounds-inherits.html"));
}
-IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibiltyBoundsClips) {
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBoundsClips) {
RunHtmlTest(FILE_PATH_LITERAL("bounds-clips.html"));
}
@@ -1000,6 +1015,16 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityButton) {
RunHtmlTest(FILE_PATH_LITERAL("button.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityButtonAltChanged) {
+ RunHtmlTest(FILE_PATH_LITERAL("button-alt-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityButtonContentChanged) {
+ RunHtmlTest(FILE_PATH_LITERAL("button-content-changed.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityButtonNameCalc) {
RunHtmlTest(FILE_PATH_LITERAL("button-name-calc.html"));
}
@@ -1471,6 +1496,11 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityLandmark) {
RunHtmlTest(FILE_PATH_LITERAL("landmark.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityLayoutTableInButton) {
+ RunHtmlTest(FILE_PATH_LITERAL("layout-table-in-button.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityLegend) {
RunHtmlTest(FILE_PATH_LITERAL("legend.html"));
}
@@ -1609,6 +1639,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityQ) {
RunHtmlTest(FILE_PATH_LITERAL("q.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityReparentCrash) {
+ RunHtmlTest(FILE_PATH_LITERAL("reparent-crash.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityReplaceData) {
RunHtmlTest(FILE_PATH_LITERAL("replace-data.html"));
}
@@ -1729,6 +1763,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTitle) {
RunHtmlTest(FILE_PATH_LITERAL("title.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTitleChanged) {
+ RunHtmlTest(FILE_PATH_LITERAL("title-changed.html"));
+}
+
#if defined(OS_WIN) || defined(OS_MACOSX)
// Flaky on Win/Mac: crbug.com/508532
#define MAYBE_AccessibilityTransition DISABLED_AccessibilityTransition
@@ -1740,6 +1778,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("transition.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTruncateLabel) {
+ RunHtmlTest(FILE_PATH_LITERAL("truncate-label.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityUl) {
RunHtmlTest(FILE_PATH_LITERAL("ul.html"));
}
diff --git a/chromium/content/browser/accessibility/hit_testing_browsertest.cc b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
index acecaaec8b1..1e2e9d6959d 100644
--- a/chromium/content/browser/accessibility/hit_testing_browsertest.cc
+++ b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
@@ -3,9 +3,11 @@
// found in the LICENSE file.
#include "base/logging.h"
+#include "build/build_config.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/use_zoom_for_dsf_policy.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -59,6 +61,28 @@ class AccessibilityHitTestingBrowserTest : public ContentBrowserTest {
return HitTestAndWaitForResultWithEvent(point, ax::mojom::Event::kHover);
}
+ BrowserAccessibility* TapAndWaitForResult(const gfx::Point& point) {
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTree* frame_tree = web_contents->GetFrameTree();
+
+ AccessibilityNotificationWaiter event_waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kClicked);
+ for (FrameTreeNode* node : frame_tree->Nodes())
+ event_waiter.ListenToAdditionalFrame(node->current_frame_host());
+
+ SimulateTapAt(shell()->web_contents(), point);
+ event_waiter.WaitForNotification();
+
+ RenderFrameHostImpl* target_frame = event_waiter.event_render_frame_host();
+ BrowserAccessibilityManager* target_manager =
+ target_frame->browser_accessibility_manager();
+ int event_target_id = event_waiter.event_target_id();
+ BrowserAccessibility* hit_node = target_manager->GetFromID(event_target_id);
+ return hit_node;
+ }
+
BrowserAccessibility* CallCachingAsyncHitTest(const gfx::Point& point) {
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
@@ -78,6 +102,18 @@ class AccessibilityHitTestingBrowserTest : public ContentBrowserTest {
hover_waiter.WaitForNotification();
return result;
}
+
+ RenderWidgetHostImpl* GetRenderWidgetHost() {
+ return RenderWidgetHostImpl::From(shell()
+ ->web_contents()
+ ->GetRenderWidgetHostView()
+ ->GetRenderWidgetHost());
+ }
+
+ void SynchronizeThreads() {
+ MainThreadFrameObserver observer(GetRenderWidgetHost());
+ observer.Wait();
+ }
};
IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
@@ -129,8 +165,15 @@ IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
// wait for the hover event in response, verifying we hit the
// correct object.
- // (50, 50) -> "Button"
+ // (26, 26) -> "Button"
BrowserAccessibility* hit_node;
+ hit_node = HitTestAndWaitForResult(gfx::Point(26, 26));
+ ASSERT_TRUE(hit_node != nullptr);
+ ASSERT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ ASSERT_EQ("Button",
+ hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+
+ // (50, 50) -> "Button"
hit_node = HitTestAndWaitForResult(gfx::Point(50, 50));
ASSERT_TRUE(hit_node != nullptr);
ASSERT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
@@ -199,42 +242,197 @@ IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
BrowserAccessibility* hit_node;
hit_node = CallCachingAsyncHitTest(gfx::Point(50, 50));
ASSERT_TRUE(hit_node != nullptr);
- ASSERT_NE(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_NE(ax::mojom::Role::kButton, hit_node->GetRole());
hit_node = CallCachingAsyncHitTest(gfx::Point(50, 50));
- ASSERT_EQ("Button",
+ EXPECT_EQ("Button",
hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
// (50, 305) -> div in first iframe
hit_node = CallCachingAsyncHitTest(gfx::Point(50, 305));
ASSERT_TRUE(hit_node != nullptr);
- ASSERT_NE(ax::mojom::Role::kGenericContainer, hit_node->GetRole());
+ EXPECT_NE(ax::mojom::Role::kGenericContainer, hit_node->GetRole());
hit_node = CallCachingAsyncHitTest(gfx::Point(50, 305));
- ASSERT_EQ(ax::mojom::Role::kGenericContainer, hit_node->GetRole());
+ EXPECT_EQ(ax::mojom::Role::kGenericContainer, hit_node->GetRole());
// (50, 350) -> "Ordinary Button"
hit_node = CallCachingAsyncHitTest(gfx::Point(50, 350));
ASSERT_TRUE(hit_node != nullptr);
- ASSERT_NE(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_NE(ax::mojom::Role::kButton, hit_node->GetRole());
hit_node = CallCachingAsyncHitTest(gfx::Point(50, 350));
- ASSERT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
- ASSERT_EQ("Ordinary Button",
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Ordinary Button",
hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
// (50, 455) -> "Scrolled Button"
hit_node = CallCachingAsyncHitTest(gfx::Point(50, 455));
ASSERT_TRUE(hit_node != nullptr);
- ASSERT_NE(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_NE(ax::mojom::Role::kButton, hit_node->GetRole());
hit_node = CallCachingAsyncHitTest(gfx::Point(50, 455));
- ASSERT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
- ASSERT_EQ("Scrolled Button",
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Scrolled Button",
hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
// (50, 505) -> div in second iframe
hit_node = CallCachingAsyncHitTest(gfx::Point(50, 505));
ASSERT_TRUE(hit_node != nullptr);
- ASSERT_NE(ax::mojom::Role::kGenericContainer, hit_node->GetRole());
+ EXPECT_NE(ax::mojom::Role::kGenericContainer, hit_node->GetRole());
hit_node = CallCachingAsyncHitTest(gfx::Point(50, 505));
- ASSERT_EQ(ax::mojom::Role::kGenericContainer, hit_node->GetRole());
+ EXPECT_EQ(ax::mojom::Role::kGenericContainer, hit_node->GetRole());
}
+#if !defined(OS_ANDROID) && !defined(OS_MACOSX)
+IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
+ HitTestingWithPinchZoom) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ NavigateToURL(shell(), GURL(url::kAboutBlankURL));
+
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLoadComplete);
+
+ const char url_str[] =
+ "data:text/html,"
+ "<!doctype html>"
+ "<html>"
+ "<head><title>Accessibility Test</title>"
+ "<style>body {margin: 0px;}"
+ "button {display: block; height: 50px; width: 50px}</style>"
+ "</head>"
+ "<body>"
+ "<button>Button 1</button>"
+ "<button>Button 2</button>"
+ "</body></html>";
+
+ GURL url(url_str);
+ NavigateToURL(shell(), url);
+ SynchronizeThreads();
+ waiter.WaitForNotification();
+
+ BrowserAccessibility* hit_node;
+
+ // Use a tap event instead of a hittest to make sure that we are using
+ // px as input, rather than dips.
+
+ // (10, 10) -> "Button 1"
+ hit_node = TapAndWaitForResult(gfx::Point(10, 10));
+ ASSERT_TRUE(hit_node != nullptr);
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Button 1",
+ hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+
+ // (60, 60) -> No button there
+ hit_node = TapAndWaitForResult(gfx::Point(60, 60));
+ EXPECT_TRUE(hit_node == nullptr);
+
+ // (10, 60) -> "Button 2"
+ hit_node = TapAndWaitForResult(gfx::Point(10, 60));
+ ASSERT_TRUE(hit_node != nullptr);
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Button 2",
+ hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+
+ content::TestPageScaleObserver scale_observer(shell()->web_contents());
+ const gfx::Rect contents_rect = shell()->web_contents()->GetContainerBounds();
+ const gfx::Point pinch_position(contents_rect.x(), contents_rect.y());
+ SimulateGesturePinchSequence(shell()->web_contents(), pinch_position, 2.0f,
+ blink::kWebGestureDeviceTouchscreen);
+ scale_observer.WaitForPageScaleUpdate();
+
+ // (10, 10) -> "Button 1"
+ hit_node = TapAndWaitForResult(gfx::Point(10, 10));
+ ASSERT_TRUE(hit_node != nullptr);
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Button 1",
+ hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+
+ // (60, 60) -> "Button 1"
+ hit_node = TapAndWaitForResult(gfx::Point(60, 60));
+ ASSERT_TRUE(hit_node != nullptr);
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Button 1",
+ hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+
+ // (10, 60) -> "Button 1"
+ hit_node = TapAndWaitForResult(gfx::Point(10, 60));
+ ASSERT_TRUE(hit_node != nullptr);
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Button 1",
+ hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+
+ // (10, 110) -> "Button 2"
+ hit_node = TapAndWaitForResult(gfx::Point(10, 110));
+ ASSERT_TRUE(hit_node != nullptr);
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Button 2",
+ hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+
+ // (190, 190) -> "Button 2"
+ hit_node = TapAndWaitForResult(gfx::Point(90, 190));
+ ASSERT_TRUE(hit_node != nullptr);
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Button 2",
+ hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
+ HitTestingWithPinchZoomAndIframes) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ NavigateToURL(shell(), GURL(url::kAboutBlankURL));
+
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLoadComplete);
+
+ GURL url(embedded_test_server()->GetURL(
+ "/accessibility/html/iframe-coordinates.html"));
+ NavigateToURL(shell(), url);
+ SynchronizeThreads();
+ waiter.WaitForNotification();
+
+ WaitForAccessibilityTreeToContainNodeWithName(shell()->web_contents(),
+ "Ordinary Button");
+ WaitForAccessibilityTreeToContainNodeWithName(shell()->web_contents(),
+ "Scrolled Button");
+
+ content::TestPageScaleObserver scale_observer(shell()->web_contents());
+ const gfx::Rect contents_rect = shell()->web_contents()->GetContainerBounds();
+ const gfx::Point pinch_position(contents_rect.x(), contents_rect.y());
+
+ SimulateGesturePinchSequence(shell()->web_contents(), pinch_position, 1.25f,
+ blink::kWebGestureDeviceTouchscreen);
+ scale_observer.WaitForPageScaleUpdate();
+
+ BrowserAccessibility* hit_node;
+
+ // (26, 26) -> No button because of pinch.
+ hit_node = TapAndWaitForResult(gfx::Point(26, 26));
+ ASSERT_TRUE(hit_node != nullptr);
+ EXPECT_NE(ax::mojom::Role::kButton, hit_node->GetRole());
+
+ // (63, 63) -> "Button"
+ hit_node = TapAndWaitForResult(gfx::Point(63, 63));
+ ASSERT_TRUE(hit_node != nullptr);
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Button",
+ hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+
+ // (63, 438) -> "Ordinary Button"
+ hit_node = TapAndWaitForResult(gfx::Point(63, 438));
+ ASSERT_TRUE(hit_node != nullptr);
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Ordinary Button",
+ hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+
+ // (63, 569) -> "Scrolled Button"
+ hit_node = TapAndWaitForResult(gfx::Point(63, 569));
+ ASSERT_TRUE(hit_node != nullptr);
+ EXPECT_EQ(ax::mojom::Role::kButton, hit_node->GetRole());
+ EXPECT_EQ("Scrolled Button",
+ hit_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+}
+
+#endif // !defined(OS_ANDROID) && !defined(OS_MACOSX)
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/line_layout_browsertest.cc b/chromium/content/browser/accessibility/line_layout_browsertest.cc
new file mode 100644
index 00000000000..e6d0bd40311
--- /dev/null
+++ b/chromium/content/browser/accessibility/line_layout_browsertest.cc
@@ -0,0 +1,97 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class AccessibilityLineLayoutBrowserTest : public ContentBrowserTest {
+ public:
+ AccessibilityLineLayoutBrowserTest() = default;
+ ~AccessibilityLineLayoutBrowserTest() override = default;
+
+ protected:
+ BrowserAccessibility* FindButton(BrowserAccessibility* node) {
+ if (node->GetRole() == ax::mojom::Role::kButton)
+ return node;
+ for (unsigned i = 0; i < node->PlatformChildCount(); i++) {
+ if (BrowserAccessibility* button = FindButton(node->PlatformGetChild(i)))
+ return button;
+ }
+ return nullptr;
+ }
+
+ int CountNextPreviousOnLineLinks(BrowserAccessibility* node) {
+ int line_link_count = 0;
+
+ int next_on_line_id =
+ node->GetIntAttribute(ax::mojom::IntAttribute::kNextOnLineId);
+ if (next_on_line_id) {
+ BrowserAccessibility* other = node->manager()->GetFromID(next_on_line_id);
+ EXPECT_TRUE(other) << "Next on line link is invalid.";
+ line_link_count++;
+ }
+ int previous_on_line_id =
+ node->GetIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId);
+ if (previous_on_line_id) {
+ BrowserAccessibility* other =
+ node->manager()->GetFromID(previous_on_line_id);
+ EXPECT_TRUE(other) << "Previous on line link is invalid.";
+ line_link_count++;
+ }
+
+ for (unsigned i = 0; i < node->InternalChildCount(); i++)
+ line_link_count +=
+ CountNextPreviousOnLineLinks(node->InternalGetChild(i));
+
+ return line_link_count;
+ }
+};
+
+// http://crbug.com/868830 - the patch that enabled this test to pass
+// caused a performance regression.
+IN_PROC_BROWSER_TEST_F(AccessibilityLineLayoutBrowserTest,
+ DISABLED_WholeBlockIsUpdated) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLoadComplete);
+ GURL url(embedded_test_server()->GetURL("/accessibility/lines/lines.html"));
+ NavigateToURL(shell(), url);
+ waiter.WaitForNotification();
+
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ BrowserAccessibilityManager* manager =
+ web_contents->GetRootBrowserAccessibilityManager();
+
+ // There should be at least 2 links between nodes on the same line.
+ int line_link_count = CountNextPreviousOnLineLinks(manager->GetRoot());
+ ASSERT_GE(line_link_count, 2);
+
+ // Find the button and click it.
+ BrowserAccessibility* button = FindButton(manager->GetRoot());
+ ASSERT_NE(nullptr, button);
+ manager->DoDefaultAction(*button);
+
+ // When done the page will change the button text to "Done".
+ WaitForAccessibilityTreeToContainNodeWithName(web_contents, "Done");
+
+ // There should be at least 2 links between nodes on the same line,
+ // though not necessarily the same as before.
+ line_link_count = CountNextPreviousOnLineLinks(manager->GetRoot());
+ ASSERT_GE(line_link_count, 2);
+}
+
+} // 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 a088ec91be7..0a80995df02 100644
--- a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
+++ b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
@@ -443,7 +443,7 @@ bool AccessibilityTextStyleItalicPredicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
int32_t style = node->GetIntAttribute(ax::mojom::IntAttribute::kTextStyle);
return 0 !=
- (style & static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleBold));
+ (style & static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleItalic));
}
bool AccessibilityTextStyleUnderlinePredicate(
diff --git a/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc b/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
index 94d6a730b04..0ec7810518f 100644
--- a/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
+++ b/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
@@ -10,6 +10,7 @@
#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/hit_test_region_observer.h"
#include "content/shell/browser/shell.h"
#include "content/test/accessibility_browser_test_utils.h"
#include "content/test/content_browser_test_utils_internal.h"
@@ -169,10 +170,11 @@ IN_PROC_BROWSER_TEST_F(TouchAccessibilityBrowserTest,
child_frame->GetOrCreateBrowserAccessibilityManager();
ASSERT_NE(nullptr, child_manager);
- // If OOPIFs are enabled, wait until compositor frames are all properly
- // displayed, otherwise the touch event will not get sent to the correct
- // renderer process.
- WaitForChildFrameSurfaceReady(child_frame);
+ // If OOPIFs are enabled, wait until hit testing data is ready, otherwise the
+ // touch event will not get sent to the correct renderer process. However the
+ // |child_frame| being used here is not actually a
+ // RenderWidgetHostViewChildFrame.
+ WaitForHitTestDataOrChildSurfaceReady(child_frame);
// Send a touch exploration event to the button in the first iframe.
// A touch exploration event is just a mouse move event with
diff --git a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
index c1be0a5d63f..ee2bfb27fd3 100644
--- a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -855,7 +855,7 @@ void WebContentsAccessibilityAndroid::SetTextFieldValue(
BrowserAccessibilityAndroid* node = GetAXFromUniqueID(unique_id);
if (node) {
node->manager()->SetValue(
- *node, base::android::ConvertJavaStringToUTF16(env, value));
+ *node, base::android::ConvertJavaStringToUTF8(env, value));
}
}
@@ -909,7 +909,7 @@ jboolean WebContentsAccessibilityAndroid::AdjustSlider(
value += (increment ? delta : -delta);
value = std::max(std::min(value, max), min);
if (value != original_value) {
- node->manager()->SetValue(*node, base::NumberToString16(value));
+ node->manager()->SetValue(*node, base::NumberToString(value));
return true;
}
return false;
diff --git a/chromium/content/browser/android/browser_startup_controller.cc b/chromium/content/browser/android/browser_startup_controller.cc
index 67c5bb1167e..7ca03b04ad9 100644
--- a/chromium/content/browser/android/browser_startup_controller.cc
+++ b/chromium/content/browser/android/browser_startup_controller.cc
@@ -10,7 +10,7 @@
#include "content/browser/browser_main_loop.h"
#include "ppapi/buildflags/buildflags.h"
-#include "jni/BrowserStartupController_jni.h"
+#include "jni/BrowserStartupControllerImpl_jni.h"
using base::android::JavaParamRef;
@@ -18,28 +18,28 @@ namespace content {
void BrowserStartupComplete(int result) {
JNIEnv* env = base::android::AttachCurrentThread();
- Java_BrowserStartupController_browserStartupComplete(env, result);
+ Java_BrowserStartupControllerImpl_browserStartupComplete(env, result);
+}
+
+void ServiceManagerStartupComplete() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_BrowserStartupControllerImpl_serviceManagerStartupComplete(env);
}
bool ShouldStartGpuProcessOnBrowserStartup() {
JNIEnv* env = base::android::AttachCurrentThread();
- return Java_BrowserStartupController_shouldStartGpuProcessOnBrowserStartup(
+ return Java_BrowserStartupControllerImpl_shouldStartGpuProcessOnBrowserStartup(
env);
}
-static void JNI_BrowserStartupController_SetCommandLineFlags(
+static void JNI_BrowserStartupControllerImpl_SetCommandLineFlags(
JNIEnv* env,
const JavaParamRef<jclass>& clazz,
- jboolean single_process,
- const JavaParamRef<jstring>& plugin_descriptor) {
- std::string plugin_str =
- (plugin_descriptor == NULL
- ? std::string()
- : base::android::ConvertJavaStringToUTF8(env, plugin_descriptor));
- SetContentCommandLineFlags(static_cast<bool>(single_process), plugin_str);
+ jboolean single_process) {
+ SetContentCommandLineFlags(static_cast<bool>(single_process));
}
-static jboolean JNI_BrowserStartupController_IsOfficialBuild(
+static jboolean JNI_BrowserStartupControllerImpl_IsOfficialBuild(
JNIEnv* env,
const JavaParamRef<jclass>& clazz) {
#if defined(OFFICIAL_BUILD)
@@ -49,17 +49,7 @@ static jboolean JNI_BrowserStartupController_IsOfficialBuild(
#endif
}
-static jboolean JNI_BrowserStartupController_IsPluginEnabled(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
-#if BUILDFLAG(ENABLE_PLUGINS)
- return true;
-#else
- return false;
-#endif
-}
-
-static void JNI_BrowserStartupController_FlushStartupTasks(
+static void JNI_BrowserStartupControllerImpl_FlushStartupTasks(
JNIEnv* env,
const JavaParamRef<jclass>& clazz) {
BrowserMainLoop::GetInstance()->SynchronouslyFlushStartupTasks();
diff --git a/chromium/content/browser/android/browser_startup_controller.h b/chromium/content/browser/android/browser_startup_controller.h
index 162f1e82501..6db34d157da 100644
--- a/chromium/content/browser/android/browser_startup_controller.h
+++ b/chromium/content/browser/android/browser_startup_controller.h
@@ -9,6 +9,7 @@ namespace content {
void BrowserStartupComplete(int result);
bool ShouldStartGpuProcessOnBrowserStartup();
+void ServiceManagerStartupComplete();
} // namespace content
#endif // CONTENT_BROWSER_ANDROID_BROWSER_STARTUP_CONTROLLER_H_
diff --git a/chromium/content/browser/android/content_feature_list.cc b/chromium/content/browser/android/content_feature_list.cc
index 2cff63192ea..a3b57a91db0 100644
--- a/chromium/content/browser/android/content_feature_list.cc
+++ b/chromium/content/browser/android/content_feature_list.cc
@@ -22,6 +22,7 @@ namespace {
// this array may either refer to features defined in the header of this file or
// in other locations in the code base (e.g. content_features.h).
const base::Feature* kFeaturesExposedToJava[] = {
+ &features::kBackgroundMediaRendererHasModerateBinding,
&kEnhancedSelectionInsertionHandle,
};
diff --git a/chromium/content/browser/android/content_startup_flags.cc b/chromium/content/browser/android/content_startup_flags.cc
index 9fbc4f0adb6..dfd962dbef9 100644
--- a/chromium/content/browser/android/content_startup_flags.cc
+++ b/chromium/content/browser/android/content_startup_flags.cc
@@ -17,8 +17,7 @@
namespace content {
-void SetContentCommandLineFlags(bool single_process,
- const std::string& plugin_descriptor) {
+void SetContentCommandLineFlags(bool single_process) {
// May be called multiple times, to cover all possible program entry points.
static bool already_initialized = false;
if (already_initialized)
@@ -59,11 +58,6 @@ void SetContentCommandLineFlags(bool single_process,
// Disable anti-aliasing.
parsed_command_line->AppendSwitch(
cc::switches::kDisableCompositedAntialiasing);
-
- if (!plugin_descriptor.empty()) {
- parsed_command_line->AppendSwitchNative(
- switches::kRegisterPepperPlugins, plugin_descriptor);
- }
}
} // namespace content
diff --git a/chromium/content/browser/android/content_startup_flags.h b/chromium/content/browser/android/content_startup_flags.h
index 8f55a0c2cf4..0f90db8cef6 100644
--- a/chromium/content/browser/android/content_startup_flags.h
+++ b/chromium/content/browser/android/content_startup_flags.h
@@ -12,8 +12,7 @@ namespace content {
// Force-appends flags to the command line turning on Android-specific
// features owned by Content. This is called as soon as possible during
// initialization to make sure code sees the new flags.
-void SetContentCommandLineFlags(bool single_process,
- const std::string& plugin_descriptor);
+void SetContentCommandLineFlags(bool single_process);
} // namespace content
diff --git a/chromium/content/browser/android/content_video_view.cc b/chromium/content/browser/android/content_video_view.cc
deleted file mode 100644
index 15011da9bd3..00000000000
--- a/chromium/content/browser/android/content_video_view.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/android/content_video_view.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "content/public/browser/web_contents.h"
-#include "jni/ContentVideoViewImpl_jni.h"
-
-using base::android::AttachCurrentThread;
-using base::android::JavaParamRef;
-using base::android::JavaRef;
-using base::android::ScopedJavaGlobalRef;
-using base::android::ScopedJavaLocalRef;
-
-namespace content {
-
-namespace {
-// There can only be one content video view at a time, this holds onto that
-// singleton instance.
-ContentVideoView* g_content_video_view = NULL;
-
-} // namespace
-
-static ScopedJavaLocalRef<jobject>
-JNI_ContentVideoViewImpl_GetSingletonJavaContentVideoView(
- JNIEnv* env,
- const JavaParamRef<jclass>&) {
- if (g_content_video_view)
- return g_content_video_view->GetJavaObject(env);
- else
- return ScopedJavaLocalRef<jobject>();
-}
-
-ContentVideoView* ContentVideoView::GetInstance() {
- return g_content_video_view;
-}
-
-ContentVideoView::ContentVideoView(Client* client,
- WebContents* web_contents,
- const JavaRef<jobject>& video_embedder,
- const gfx::Size& video_natural_size)
- : client_(client), weak_factory_(this) {
- DCHECK(!g_content_video_view);
- j_content_video_view_ =
- CreateJavaObject(web_contents, video_embedder, video_natural_size);
- g_content_video_view = this;
-}
-
-ContentVideoView::~ContentVideoView() {
- DCHECK(g_content_video_view);
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
- if (!content_video_view.is_null()) {
- Java_ContentVideoViewImpl_destroyContentVideoView(env, content_video_view,
- true);
- j_content_video_view_.reset();
- }
- g_content_video_view = NULL;
-}
-
-void ContentVideoView::OpenVideo() {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
- if (!content_video_view.is_null()) {
- Java_ContentVideoViewImpl_openVideo(env, content_video_view);
- }
-}
-
-void ContentVideoView::OnMediaPlayerError(int error_type) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
- if (!content_video_view.is_null()) {
- Java_ContentVideoViewImpl_onMediaPlayerError(env, content_video_view,
- error_type);
- }
-}
-
-void ContentVideoView::OnVideoSizeChanged(int width, int height) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
- if (!content_video_view.is_null()) {
- Java_ContentVideoViewImpl_onVideoSizeChanged(env, content_video_view, width,
- height);
- }
-}
-
-void ContentVideoView::ExitFullscreen() {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
- bool release_media_player = false;
- if (!content_video_view.is_null())
- Java_ContentVideoViewImpl_exitFullscreen(env, content_video_view,
- release_media_player);
-}
-
-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(
- gl::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*,
- const JavaParamRef<jobject>&,
- bool is_portrait_video,
- bool is_orientation_portrait) {
- UMA_HISTOGRAM_BOOLEAN("MobileFullscreenVideo.OrientationPortrait",
- is_orientation_portrait);
- UMA_HISTOGRAM_BOOLEAN("MobileFullscreenVideo.VideoPortrait",
- is_portrait_video);
-}
-
-void ContentVideoView::RecordExitFullscreenPlayback(
- JNIEnv*,
- const JavaParamRef<jobject>&,
- bool is_portrait_video,
- long playback_duration_in_milliseconds_before_orientation_change,
- long playback_duration_in_milliseconds_after_orientation_change) {
- bool orientation_changed = (
- playback_duration_in_milliseconds_after_orientation_change != 0);
- if (is_portrait_video) {
- UMA_HISTOGRAM_COUNTS(
- "MobileFullscreenVideo.PortraitDuration",
- playback_duration_in_milliseconds_before_orientation_change);
- UMA_HISTOGRAM_COUNTS(
- "MobileFullscreenVideo.PortraitRotation", orientation_changed);
- if (orientation_changed) {
- UMA_HISTOGRAM_COUNTS(
- "MobileFullscreenVideo.DurationAfterPotraitRotation",
- playback_duration_in_milliseconds_after_orientation_change);
- }
- } else {
- UMA_HISTOGRAM_COUNTS(
- "MobileFullscreenVideo.LandscapeDuration",
- playback_duration_in_milliseconds_before_orientation_change);
- UMA_HISTOGRAM_COUNTS(
- "MobileFullscreenVideo.LandscapeRotation", orientation_changed);
- }
-}
-
-JavaObjectWeakGlobalRef ContentVideoView::CreateJavaObject(
- WebContents* web_contents,
- const JavaRef<jobject>& j_content_video_view_embedder,
- const gfx::Size& video_natural_size) {
- JNIEnv* env = AttachCurrentThread();
- base::android::ScopedJavaLocalRef<jobject> j_web_contents =
- web_contents->GetJavaWebContents();
-
- if (j_web_contents.is_null())
- return JavaObjectWeakGlobalRef(env, nullptr);
-
- return JavaObjectWeakGlobalRef(
- env, Java_ContentVideoViewImpl_createContentVideoView(
- env, j_web_contents, j_content_video_view_embedder,
- reinterpret_cast<intptr_t>(this), video_natural_size.width(),
- video_natural_size.height())
- .obj());
-}
-} // namespace content
diff --git a/chromium/content/browser/android/content_video_view.h b/chromium/content/browser/android/content_video_view.h
deleted file mode 100644
index e070327c1a7..00000000000
--- a/chromium/content/browser/android/content_video_view.h
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_CONTENT_VIDEO_VIEW_H_
-#define CONTENT_BROWSER_ANDROID_CONTENT_VIDEO_VIEW_H_
-
-#include <jni.h>
-
-#include "base/android/jni_weak_ref.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "ui/gl/android/scoped_java_surface.h"
-
-namespace gfx {
-class Size;
-}
-
-namespace content {
-
-class WebContents;
-
-// Native mirror of ContentVideoView.java. This class is responsible for
-// 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:
- // 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(gl::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,
- WebContents* web_contents,
- const base::android::JavaRef<jobject>& embedder,
- const gfx::Size& video_natural_size);
- ~ContentVideoView();
-
- // To open another video on existing ContentVideoView.
- void OpenVideo();
-
- // Display an error dialog to the user.
- void OnMediaPlayerError(int error_type);
-
- // Update the video size.
- void OnVideoSizeChanged(int width, int height);
-
- // Exit fullscreen and notify |client_| with |DidExitFullscreen|.
- void ExitFullscreen();
-
- // Returns the corresponding ContentVideoView Java object if any.
- base::android::ScopedJavaLocalRef<jobject> GetJavaObject(JNIEnv* env);
-
- // 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);
-
- // 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*,
- const base::android::JavaParamRef<jobject>&,
- bool is_portrait_video,
- bool is_orientation_portrait);
- void RecordExitFullscreenPlayback(
- JNIEnv*,
- const base::android::JavaParamRef<jobject>&,
- bool is_portrait_video,
- long playback_duration_in_milliseconds_before_orientation_change,
- long playback_duration_in_milliseconds_after_orientation_change);
-
- private:
- // Creates the corresponding ContentVideoView Java object.
- JavaObjectWeakGlobalRef CreateJavaObject(
- WebContents* web_contents,
- const base::android::JavaRef<jobject>& j_content_video_view_embedder,
- const gfx::Size& video_natural_size);
-
- Client* client_;
-
- // Weak reference to corresponding Java object.
- JavaObjectWeakGlobalRef j_content_video_view_;
-
- // Weak pointer for posting tasks.
- base::WeakPtrFactory<ContentVideoView> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ContentVideoView);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_CONTENT_VIDEO_VIEW_H_
diff --git a/chromium/content/browser/android/content_view_core.cc b/chromium/content/browser/android/content_view_core.cc
deleted file mode 100644
index abcb9272529..00000000000
--- a/chromium/content/browser/android/content_view_core.cc
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights 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/content_view_core.h"
-
-#include "content/browser/frame_host/interstitial_page_impl.h"
-#include "content/browser/renderer_host/render_widget_host_view_android.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/web_contents/web_contents_view_android.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/user_agent.h"
-#include "jni/ContentViewCoreImpl_jni.h"
-#include "ui/android/window_android.h"
-
-using base::android::AttachCurrentThread;
-using base::android::JavaParamRef;
-using base::android::JavaRef;
-using base::android::ScopedJavaLocalRef;
-
-namespace content {
-
-namespace {
-
-RenderWidgetHostViewAndroid* GetRenderWidgetHostViewFromHost(
- RenderViewHost* host) {
- return static_cast<RenderWidgetHostViewAndroid*>(
- host->GetWidget()->GetView());
-}
-
-} // namespace
-
-ContentViewCore::ContentViewCore(JNIEnv* env,
- const JavaRef<jobject>& obj,
- WebContents* web_contents)
- : WebContentsObserver(web_contents),
- java_ref_(env, obj),
- web_contents_(static_cast<WebContentsImpl*>(web_contents)) {
- // Currently, the only use case we have for overriding a user agent involves
- // spoofing a desktop Linux user agent for "Request desktop site".
- // Automatically set it for all WebContents so that it is available when a
- // NavigationEntry requires the user agent to be overridden.
- const char kLinuxInfoStr[] = "X11; Linux x86_64";
- std::string product = content::GetContentClient()->GetProduct();
- std::string spoofed_ua =
- BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
- web_contents->SetUserAgentOverride(spoofed_ua, false);
-}
-
-ContentViewCore::~ContentViewCore() {
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
- java_ref_.reset();
- if (!j_obj.is_null()) {
- Java_ContentViewCoreImpl_onNativeContentViewCoreDestroyed(
- env, j_obj, reinterpret_cast<intptr_t>(this));
- }
-}
-
-void ContentViewCore::OnJavaContentViewCoreDestroyed(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
- java_ref_.reset();
- // Java peer has gone, ContentViewCore is not functional and waits to
- // be destroyed with WebContents.
- DCHECK(web_contents_);
-}
-
-void ContentViewCore::RenderViewReady() {
- WebContentsViewAndroid* view =
- static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
- if (view->device_orientation() == 0)
- return;
- RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
- if (rwhva)
- rwhva->UpdateScreenInfo(GetViewAndroid());
-
- web_contents_->OnScreenOrientationChange();
-}
-
-void ContentViewCore::WebContentsDestroyed() {
- delete this;
-}
-
-void ContentViewCore::RenderViewHostChanged(RenderViewHost* old_host,
- RenderViewHost* new_host) {
- if (old_host) {
- auto* view = GetRenderWidgetHostViewFromHost(old_host);
- if (view)
- view->UpdateNativeViewTree(nullptr);
-
- view = GetRenderWidgetHostViewFromHost(new_host);
- if (view)
- view->UpdateNativeViewTree(GetViewAndroid());
- }
- SetFocusInternal(GetViewAndroid()->HasFocus());
-}
-
-RenderWidgetHostViewAndroid* ContentViewCore::GetRenderWidgetHostViewAndroid()
- const {
- RenderWidgetHostView* rwhv = NULL;
- if (web_contents_) {
- rwhv = web_contents_->GetRenderWidgetHostView();
- if (web_contents_->ShowingInterstitialPage()) {
- rwhv = web_contents_->GetInterstitialPage()
- ->GetMainFrame()
- ->GetRenderViewHost()
- ->GetWidget()
- ->GetView();
- }
- }
- return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
-}
-
-ui::ViewAndroid* ContentViewCore::GetViewAndroid() const {
- return web_contents_->GetView()->GetNativeView();
-}
-
-// ----------------------------------------------------------------------------
-// Methods called from Java via JNI
-// ----------------------------------------------------------------------------
-
-void ContentViewCore::SetFocus(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jboolean focused) {
- SetFocusInternal(focused);
-}
-
-void ContentViewCore::SetFocusInternal(bool focused) {
- if (!GetRenderWidgetHostViewAndroid())
- return;
-
- if (focused)
- GetRenderWidgetHostViewAndroid()->GotFocus();
- else
- GetRenderWidgetHostViewAndroid()->LostFocus();
-}
-
-// This is called for each ContentView.
-jlong JNI_ContentViewCoreImpl_Init(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& jweb_contents) {
- WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
- WebContents::FromJavaWebContents(jweb_contents));
- CHECK(web_contents)
- << "A ContentViewCore should be created with a valid WebContents.";
- return reinterpret_cast<intptr_t>(
- new ContentViewCore(env, obj, web_contents));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/android/content_view_core.h b/chromium/content/browser/android/content_view_core.h
deleted file mode 100644
index f41a9a56497..00000000000
--- a/chromium/content/browser/android/content_view_core.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2017 The Chromium Authors. All 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_H_
-#define CONTENT_BROWSER_ANDROID_CONTENT_VIEW_CORE_H_
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_weak_ref.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/macros.h"
-#include "content/public/browser/web_contents_observer.h"
-
-namespace ui {
-class ViewAndroid;
-}
-
-namespace content {
-
-class RenderWidgetHostViewAndroid;
-class WebContentsImpl;
-
-class ContentViewCore : public WebContentsObserver {
- public:
- ContentViewCore(JNIEnv* env,
- const base::android::JavaRef<jobject>& obj,
- WebContents* web_contents);
-
- ~ContentViewCore() override;
-
- // --------------------------------------------------------------------------
- // Methods called from Java via JNI
- // --------------------------------------------------------------------------
-
- void OnJavaContentViewCoreDestroyed(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
-
- void SetFocus(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jboolean focused);
-
- private:
-
- // WebContentsObserver implementation.
- void RenderViewReady() override;
- void RenderViewHostChanged(RenderViewHost* old_host,
- RenderViewHost* new_host) override;
- void WebContentsDestroyed() override;
-
- // --------------------------------------------------------------------------
- // Other private methods and data
- // --------------------------------------------------------------------------
-
- ui::ViewAndroid* GetViewAndroid() const;
-
- RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid() const;
-
- // Update focus state of the RenderWidgetHostView.
- void SetFocusInternal(bool focused);
-
- // A weak reference to the Java ContentViewCore object.
- JavaObjectWeakGlobalRef java_ref_;
-
- // Reference to the current WebContents used to determine how and what to
- // display in the ContentViewCore.
- WebContentsImpl* web_contents_;
-
- DISALLOW_COPY_AND_ASSIGN(ContentViewCore);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_CONTENT_VIEW_CORE_H_
diff --git a/chromium/content/browser/android/content_view_render_view.cc b/chromium/content/browser/android/content_view_render_view.cc
deleted file mode 100644
index afaefd7c88b..00000000000
--- a/chromium/content/browser/android/content_view_render_view.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/android/content_view_render_view.h"
-
-#include <android/bitmap.h>
-#include <android/native_window_jni.h>
-
-#include <memory>
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "cc/layers/layer.h"
-#include "content/public/browser/android/compositor.h"
-#include "content/public/browser/android/content_view_layer_renderer.h"
-#include "content/public/browser/web_contents.h"
-#include "jni/ContentViewRenderView_jni.h"
-#include "ui/android/view_android.h"
-#include "ui/android/window_android.h"
-#include "ui/gfx/android/java_bitmap.h"
-#include "ui/gfx/geometry/size.h"
-
-using base::android::JavaParamRef;
-using base::android::ScopedJavaLocalRef;
-
-namespace content {
-
-ContentViewRenderView::ContentViewRenderView(JNIEnv* env,
- jobject obj,
- gfx::NativeWindow root_window)
- : root_window_(root_window), current_surface_format_(0) {
- java_obj_.Reset(env, obj);
-}
-
-ContentViewRenderView::~ContentViewRenderView() {
-}
-
-// static
-static jlong JNI_ContentViewRenderView_Init(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& jroot_window_android) {
- gfx::NativeWindow root_window =
- ui::WindowAndroid::FromJavaWindowAndroid(jroot_window_android);
- ContentViewRenderView* content_view_render_view =
- new ContentViewRenderView(env, obj, root_window);
- return reinterpret_cast<intptr_t>(content_view_render_view);
-}
-
-void ContentViewRenderView::Destroy(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- delete this;
-}
-
-void ContentViewRenderView::SetCurrentWebContents(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& jweb_contents) {
- InitCompositor();
- WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
- compositor_->SetRootLayer(web_contents
- ? web_contents->GetNativeView()->GetLayer()
- : scoped_refptr<cc::Layer>());
-}
-
-void ContentViewRenderView::OnPhysicalBackingSizeChanged(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& jweb_contents,
- jint width,
- jint height) {
- WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
- gfx::Size size(width, height);
- web_contents->GetNativeView()->OnPhysicalBackingSizeChanged(size);
-}
-
-void ContentViewRenderView::SurfaceCreated(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- current_surface_format_ = 0;
- InitCompositor();
-}
-
-void ContentViewRenderView::SurfaceDestroyed(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- compositor_->SetSurface(NULL);
- current_surface_format_ = 0;
-}
-
-void ContentViewRenderView::SurfaceChanged(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jint format,
- jint width,
- jint height,
- const JavaParamRef<jobject>& surface) {
- if (current_surface_format_ != format) {
- current_surface_format_ = format;
- compositor_->SetSurface(surface);
- }
- compositor_->SetWindowBounds(gfx::Size(width, height));
-}
-
-void ContentViewRenderView::SetOverlayVideoMode(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- bool enabled) {
- compositor_->SetRequiresAlphaChannel(enabled);
- compositor_->SetBackgroundColor(enabled ? SK_ColorTRANSPARENT
- : SK_ColorWHITE);
- compositor_->SetNeedsComposite();
-}
-
-void ContentViewRenderView::SetNeedsComposite(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj) {
- compositor_->SetNeedsComposite();
-}
-
-void ContentViewRenderView::UpdateLayerTreeHost() {
- // TODO(wkorman): Rename Layout to UpdateLayerTreeHost in all Android
- // Compositor related classes.
-}
-
-void ContentViewRenderView::DidSwapFrame(int pending_frames) {
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_ContentViewRenderView_didSwapFrame(env, java_obj_);
-}
-
-void ContentViewRenderView::InitCompositor() {
- if (!compositor_)
- compositor_.reset(Compositor::Create(this, root_window_));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/android/content_view_render_view.h b/chromium/content/browser/android/content_view_render_view.h
deleted file mode 100644
index 97916d3a300..00000000000
--- a/chromium/content/browser/android/content_view_render_view.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_BROWSER_ANDROID_CONTENT_VIEW_RENDER_VIEW_H_
-#define CONTENT_BROWSER_ANDROID_CONTENT_VIEW_RENDER_VIEW_H_
-
-#include <memory>
-
-#include "base/android/jni_weak_ref.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/public/browser/android/compositor_client.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace content {
-class Compositor;
-
-class ContentViewRenderView : public CompositorClient {
- public:
- ContentViewRenderView(JNIEnv* env,
- jobject obj,
- gfx::NativeWindow root_window);
-
- // Methods called from Java via JNI -----------------------------------------
- void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
- void SetCurrentWebContents(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- const base::android::JavaParamRef<jobject>& jweb_contents);
- void OnPhysicalBackingSizeChanged(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- const base::android::JavaParamRef<jobject>& jweb_contents,
- jint width,
- jint height);
- void SurfaceCreated(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
- void SurfaceDestroyed(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
- void SurfaceChanged(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jint format,
- jint width,
- jint height,
- const base::android::JavaParamRef<jobject>& surface);
- void SetOverlayVideoMode(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- bool enabled);
- void SetNeedsComposite(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
-
- // CompositorClient implementation
- void UpdateLayerTreeHost() override;
- void DidSwapFrame(int pending_frames) override;
-
- private:
- ~ContentViewRenderView() override;
-
- void InitCompositor();
-
- base::android::ScopedJavaGlobalRef<jobject> java_obj_;
-
- std::unique_ptr<content::Compositor> compositor_;
-
- gfx::NativeWindow root_window_;
- int current_surface_format_;
-
- DISALLOW_COPY_AND_ASSIGN(ContentViewRenderView);
-};
-
-
-
-}
-
-#endif // CONTENT_BROWSER_ANDROID_CONTENT_VIEW_RENDER_VIEW_H_
diff --git a/chromium/content/browser/android/dialog_overlay_impl.cc b/chromium/content/browser/android/dialog_overlay_impl.cc
index 8335d3bf14e..70457ba7490 100644
--- a/chromium/content/browser/android/dialog_overlay_impl.cc
+++ b/chromium/content/browser/android/dialog_overlay_impl.cc
@@ -38,14 +38,14 @@ static jlong JNI_DialogOverlayImpl_Init(JNIEnv* env,
// reprojection video surface.
RenderWidgetHostViewBase* rwhvb =
static_cast<RenderWidgetHostViewBase*>(rfhi->GetView());
- if (rwhvb->IsInVR())
+ if (!rwhvb || rwhvb->IsInVR())
return 0;
WebContentsImpl* web_contents_impl = static_cast<WebContentsImpl*>(
content::WebContents::FromRenderFrameHost(rfhi));
// If the overlay would not be immediately used, fail the request.
- if (!rfhi->IsCurrent() || web_contents_impl->IsHidden())
+ if (!rfhi->IsCurrent() || !web_contents_impl || web_contents_impl->IsHidden())
return 0;
// Dialog-based overlays are not supported for persistent video.
diff --git a/chromium/content/browser/android/gesture_listener_manager.cc b/chromium/content/browser/android/gesture_listener_manager.cc
index 2cee9bf9e34..676329795a4 100644
--- a/chromium/content/browser/android/gesture_listener_manager.cc
+++ b/chromium/content/browser/android/gesture_listener_manager.cc
@@ -114,11 +114,6 @@ GestureListenerManager::~GestureListenerManager() {
Java_GestureListenerManagerImpl_onDestroy(env, j_obj);
}
-void GestureListenerManager::Reset(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- java_ref_.reset();
-}
-
void GestureListenerManager::ResetGestureDetection(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
@@ -145,52 +140,17 @@ void GestureListenerManager::SetMultiTouchZoomSupportEnabled(
void GestureListenerManager::GestureEventAck(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
+ // This is called to fix crash happening while WebContents is being
+ // destroyed. See https://crbug.com/803244#c20
+ if (web_contents_->IsBeingDestroyed())
+ return;
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
if (j_obj.is_null())
return;
-
- // TODO(jinsukkim): Define WebInputEvent in Java.
- switch (event.GetType()) {
- case WebInputEvent::kGestureFlingStart:
- if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
- // The view expects the fling velocity in pixels/s.
- Java_GestureListenerManagerImpl_onFlingStartEventConsumed(env, j_obj);
- } else {
- // If a scroll ends with a fling, a SCROLL_END event is never sent.
- // However, if that fling went unconsumed, we still need to let the
- // listeners know that scrolling has ended.
- Java_GestureListenerManagerImpl_onScrollEndEventAck(env, j_obj);
- }
- break;
- case WebInputEvent::kGestureScrollBegin:
- Java_GestureListenerManagerImpl_onScrollBeginEventAck(env, j_obj);
- break;
- case WebInputEvent::kGestureScrollUpdate:
- if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
- Java_GestureListenerManagerImpl_onScrollUpdateGestureConsumed(env,
- j_obj);
- break;
- case WebInputEvent::kGestureScrollEnd:
- Java_GestureListenerManagerImpl_onScrollEndEventAck(env, j_obj);
- break;
- case WebInputEvent::kGesturePinchBegin:
- Java_GestureListenerManagerImpl_onPinchBeginEventAck(env, j_obj);
- break;
- case WebInputEvent::kGesturePinchEnd:
- Java_GestureListenerManagerImpl_onPinchEndEventAck(env, j_obj);
- break;
- case WebInputEvent::kGestureTap:
- Java_GestureListenerManagerImpl_onSingleTapEventAck(
- env, j_obj, ack_result == INPUT_EVENT_ACK_STATE_CONSUMED);
- break;
- case WebInputEvent::kGestureLongPress:
- if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
- Java_GestureListenerManagerImpl_onLongPressAck(env, j_obj);
- break;
- default:
- break;
- }
+ Java_GestureListenerManagerImpl_onEventAck(
+ env, j_obj, event.GetType(),
+ ack_result == INPUT_EVENT_ACK_STATE_CONSUMED);
}
void GestureListenerManager::DidStopFlinging() {
diff --git a/chromium/content/browser/android/gesture_listener_manager.h b/chromium/content/browser/android/gesture_listener_manager.h
index 59121618e4c..90bd6e43c1d 100644
--- a/chromium/content/browser/android/gesture_listener_manager.h
+++ b/chromium/content/browser/android/gesture_listener_manager.h
@@ -33,7 +33,6 @@ class GestureListenerManager : public RenderWidgetHostConnector {
WebContentsImpl* web_contents);
~GestureListenerManager() override;
- void Reset(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
void ResetGestureDetection(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
void SetDoubleTapSupportEnabled(
diff --git a/chromium/content/browser/android/overscroll_controller_android.cc b/chromium/content/browser/android/overscroll_controller_android.cc
index c9d2bd85183..6c843ed9c1c 100644
--- a/chromium/content/browser/android/overscroll_controller_android.cc
+++ b/chromium/content/browser/android/overscroll_controller_android.cc
@@ -287,26 +287,30 @@ bool OverscrollControllerAndroid::Animate(base::TimeTicks current_time,
}
void OverscrollControllerAndroid::OnFrameMetadataUpdated(
- const viz::CompositorFrameMetadata& frame_metadata) {
+ float page_scale_factor,
+ float device_scale_factor,
+ const gfx::SizeF& scrollable_viewport_size,
+ const gfx::SizeF& root_layer_size,
+ const gfx::Vector2dF& root_scroll_offset,
+ bool root_overflow_y_hidden) {
if (!refresh_effect_ && !glow_effect_)
return;
// When use-zoom-for-dsf is enabled, frame_metadata.page_scale_factor was
// already scaled by the device scale factor.
- float scale_factor = frame_metadata.page_scale_factor;
+ float scale_factor = page_scale_factor;
if (!IsUseZoomForDSFEnabled()) {
- scale_factor *= frame_metadata.device_scale_factor;
+ scale_factor *= device_scale_factor;
}
gfx::SizeF viewport_size =
- gfx::ScaleSize(frame_metadata.scrollable_viewport_size, scale_factor);
- gfx::SizeF content_size =
- gfx::ScaleSize(frame_metadata.root_layer_size, scale_factor);
+ gfx::ScaleSize(scrollable_viewport_size, scale_factor);
+ gfx::SizeF content_size = gfx::ScaleSize(root_layer_size, scale_factor);
gfx::Vector2dF content_scroll_offset =
- gfx::ScaleVector2d(frame_metadata.root_scroll_offset, scale_factor);
+ gfx::ScaleVector2d(root_scroll_offset, scale_factor);
if (refresh_effect_) {
refresh_effect_->OnFrameUpdated(content_scroll_offset,
- frame_metadata.root_overflow_y_hidden);
+ root_overflow_y_hidden);
}
if (glow_effect_) {
diff --git a/chromium/content/browser/android/overscroll_controller_android.h b/chromium/content/browser/android/overscroll_controller_android.h
index d3def7a5443..42bbdd76aee 100644
--- a/chromium/content/browser/android/overscroll_controller_android.h
+++ b/chromium/content/browser/android/overscroll_controller_android.h
@@ -29,10 +29,6 @@ class WindowAndroidCompositor;
struct DidOverscrollParams;
}
-namespace viz {
-class CompositorFrameMetadata;
-}
-
namespace content {
// Glue class for handling all inputs into Android-specific overscroll effects,
@@ -70,7 +66,12 @@ class CONTENT_EXPORT OverscrollControllerAndroid
bool Animate(base::TimeTicks current_time, cc::Layer* parent_layer);
// To be called whenever the content frame has been updated.
- void OnFrameMetadataUpdated(const viz::CompositorFrameMetadata& metadata);
+ void OnFrameMetadataUpdated(float page_scale_factor,
+ float device_scale_factor,
+ const gfx::SizeF& scrollable_viewport_size,
+ const gfx::SizeF& root_layer_size,
+ const gfx::Vector2dF& root_scroll_offset,
+ bool root_overflow_y_hidden);
// Toggle activity of any overscroll effects. When disabled, events will be
// ignored until the controller is re-enabled.
diff --git a/chromium/content/browser/android/selection/composited_touch_handle_drawable.cc b/chromium/content/browser/android/selection/composited_touch_handle_drawable.cc
index 30651710d63..2fa5bb83c66 100644
--- a/chromium/content/browser/android/selection/composited_touch_handle_drawable.cc
+++ b/chromium/content/browser/android/selection/composited_touch_handle_drawable.cc
@@ -7,11 +7,10 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/trace_event/trace_event.h"
#include "cc/layers/ui_resource_layer.h"
#include "content/public/browser/android/compositor.h"
-#include "jni/HandleViewResources_jni.h"
-#include "ui/gfx/android/java_bitmap.h"
+#include "ui/android/handle_view_resources.h"
+#include "ui/android/view_android.h"
using base::android::JavaRef;
@@ -19,88 +18,21 @@ namespace content {
namespace {
-static SkBitmap CreateSkBitmapFromJavaBitmap(
- base::android::ScopedJavaLocalRef<jobject> jbitmap) {
- return jbitmap.is_null()
- ? SkBitmap()
- : CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jbitmap));
-}
-
-class HandleResources {
- public:
- HandleResources() : loaded_(false) {
- }
-
- void LoadIfNecessary(const JavaRef<jobject>& context) {
- if (loaded_)
- return;
-
- loaded_ = true;
-
- TRACE_EVENT0("browser", "HandleResources::Create");
- JNIEnv* env = base::android::AttachCurrentThread();
-
- left_bitmap_ = CreateSkBitmapFromJavaBitmap(
- Java_HandleViewResources_getLeftHandleBitmap(env, context));
- right_bitmap_ = CreateSkBitmapFromJavaBitmap(
- Java_HandleViewResources_getRightHandleBitmap(env, context));
- center_bitmap_ = CreateSkBitmapFromJavaBitmap(
- Java_HandleViewResources_getCenterHandleBitmap(env, context));
-
- left_bitmap_.setImmutable();
- right_bitmap_.setImmutable();
- center_bitmap_.setImmutable();
-
- drawable_horizontal_padding_ratio_ =
- Java_HandleViewResources_getHandleHorizontalPaddingRatio(env);
- }
-
- const SkBitmap& GetBitmap(ui::TouchHandleOrientation orientation) {
- DCHECK(loaded_);
- switch (orientation) {
- case ui::TouchHandleOrientation::LEFT:
- return left_bitmap_;
- case ui::TouchHandleOrientation::RIGHT:
- return right_bitmap_;
- case ui::TouchHandleOrientation::CENTER:
- return center_bitmap_;
- case ui::TouchHandleOrientation::UNDEFINED:
- NOTREACHED() << "Invalid touch handle orientation.";
- };
- return center_bitmap_;
- }
-
- float GetDrawableHorizontalPaddingRatio() const {
- DCHECK(loaded_);
- return drawable_horizontal_padding_ratio_;
- }
-
- private:
- SkBitmap left_bitmap_;
- SkBitmap right_bitmap_;
- SkBitmap center_bitmap_;
- float drawable_horizontal_padding_ratio_;
- bool loaded_;
-
- DISALLOW_COPY_AND_ASSIGN(HandleResources);
-};
-
-base::LazyInstance<HandleResources>::Leaky g_selection_resources;
+base::LazyInstance<ui::HandleViewResources>::Leaky g_selection_resources;
} // namespace
CompositedTouchHandleDrawable::CompositedTouchHandleDrawable(
- cc::Layer* root_layer,
- float dpi_scale,
+ gfx::NativeView view,
const JavaRef<jobject>& context)
- : dpi_scale_(dpi_scale),
+ : view_(view),
orientation_(ui::TouchHandleOrientation::UNDEFINED),
layer_(cc::UIResourceLayer::Create()) {
g_selection_resources.Get().LoadIfNecessary(context);
drawable_horizontal_padding_ratio_ =
g_selection_resources.Get().GetDrawableHorizontalPaddingRatio();
- DCHECK(root_layer);
- root_layer->AddChild(layer_.get());
+ DCHECK(view->GetLayer());
+ view->GetLayer()->AddChild(layer_.get());
}
CompositedTouchHandleDrawable::~CompositedTouchHandleDrawable() {
@@ -146,7 +78,7 @@ void CompositedTouchHandleDrawable::SetOrientation(
}
void CompositedTouchHandleDrawable::SetOrigin(const gfx::PointF& origin) {
- origin_position_ = gfx::ScalePoint(origin, dpi_scale_);
+ origin_position_ = origin;
UpdateLayerPosition();
}
@@ -159,11 +91,10 @@ void CompositedTouchHandleDrawable::SetAlpha(float alpha) {
}
gfx::RectF CompositedTouchHandleDrawable::GetVisibleBounds() const {
- return gfx::ScaleRect(gfx::RectF(layer_->position().x(),
- layer_->position().y(),
- layer_->bounds().width(),
- layer_->bounds().height()),
- 1.f / dpi_scale_);
+ return gfx::ScaleRect(
+ gfx::RectF(layer_->position().x(), layer_->position().y(),
+ layer_->bounds().width(), layer_->bounds().height()),
+ 1.f / view_->GetDipScale());
}
float CompositedTouchHandleDrawable::GetDrawableHorizontalPaddingRatio() const {
@@ -175,7 +106,7 @@ void CompositedTouchHandleDrawable::DetachLayer() {
}
void CompositedTouchHandleDrawable::UpdateLayerPosition() {
- layer_->SetPosition(origin_position_);
+ layer_->SetPosition(gfx::ScalePoint(origin_position_, view_->GetDipScale()));
}
} // namespace content
diff --git a/chromium/content/browser/android/selection/composited_touch_handle_drawable.h b/chromium/content/browser/android/selection/composited_touch_handle_drawable.h
index 0e4b6a23933..e16b8065a68 100644
--- a/chromium/content/browser/android/selection/composited_touch_handle_drawable.h
+++ b/chromium/content/browser/android/selection/composited_touch_handle_drawable.h
@@ -5,20 +5,22 @@
#ifndef CONTENT_BROWSER_ANDROID_SELECTION_COMPOSITED_TOUCH_HANDLE_DRAWABLE_H_
#define CONTENT_BROWSER_ANDROID_SELECTION_COMPOSITED_TOUCH_HANDLE_DRAWABLE_H_
-#include "ui/touch_selection/touch_handle.h"
-
-#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
-#include "cc/layers/ui_resource_layer.h"
+#include "base/memory/scoped_refptr.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/touch_selection/touch_handle.h"
+
+namespace cc {
+class UIResourceLayer;
+} // namespace cc
namespace content {
// Touch handle drawable implementation backed by a cc layer.
class CompositedTouchHandleDrawable : public ui::TouchHandleDrawable {
public:
- CompositedTouchHandleDrawable(cc::Layer* root_layer,
- float dpi_scale,
+ CompositedTouchHandleDrawable(gfx::NativeView view,
const base::android::JavaRef<jobject>& context);
~CompositedTouchHandleDrawable() override;
@@ -36,7 +38,7 @@ class CompositedTouchHandleDrawable : public ui::TouchHandleDrawable {
void DetachLayer();
void UpdateLayerPosition();
- const float dpi_scale_;
+ gfx::NativeView view_;
float drawable_horizontal_padding_ratio_;
ui::TouchHandleOrientation orientation_;
gfx::PointF origin_position_;
diff --git a/chromium/content/browser/android/selection/selection_popup_controller.cc b/chromium/content/browser/android/selection/selection_popup_controller.cc
index b36782f64f8..8a30f1a2d9f 100644
--- a/chromium/content/browser/android/selection/selection_popup_controller.cc
+++ b/chromium/content/browser/android/selection/selection_popup_controller.cc
@@ -74,8 +74,7 @@ SelectionPopupController::CreateTouchHandleDrawable() {
// the java side in CompositedTouchHandleDrawable.
auto* view = web_contents()->GetNativeView();
return std::unique_ptr<ui::TouchHandleDrawable>(
- new CompositedTouchHandleDrawable(view->GetLayer(), view->GetDipScale(),
- activityContext));
+ new CompositedTouchHandleDrawable(view, activityContext));
}
void SelectionPopupController::MoveRangeSelectionExtent(
diff --git a/chromium/content/browser/android/synchronous_compositor_host.cc b/chromium/content/browser/android/synchronous_compositor_host.cc
index 39672258292..953c10ab3a4 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.cc
+++ b/chromium/content/browser/android/synchronous_compositor_host.cc
@@ -119,6 +119,7 @@ SynchronousCompositorHost::SynchronousCompositorHost(
renderer_param_version_(0u),
need_animate_scroll_(false),
need_invalidate_count_(0u),
+ invalidate_needs_draw_(false),
did_activate_pending_tree_count_(0u) {
client_->DidInitializeCompositor(this, process_id_, routing_id_);
bridge_ = new SynchronousCompositorSyncCallBridge(this);
@@ -158,6 +159,7 @@ SynchronousCompositorHost::DemandDrawHwAsync(
const gfx::Size& viewport_size,
const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) {
+ invalidate_needs_draw_ = false;
scoped_refptr<FrameFuture> frame_future = new FrameFuture();
if (compute_scroll_needs_synchronous_draw_ || !allow_async_draw_) {
allow_async_draw_ = allow_async_draw_ || IsReadyForSynchronousCall();
@@ -258,6 +260,7 @@ bool SynchronousCompositorHost::DemandDrawSwInProc(SkCanvas* canvas) {
ScopedSetSkCanvas set_sk_canvas(canvas);
SyncCompositorDemandDrawSwParams params; // Unused.
uint32_t metadata_version = 0u;
+ invalidate_needs_draw_ = false;
if (!IsReadyForSynchronousCall() ||
!GetSynchronousCompositor()->DemandDrawSw(params, &common_renderer_params,
&metadata_version, &metadata))
@@ -501,10 +504,15 @@ void SynchronousCompositorHost::UpdateState(
renderer_param_version_ = params.version;
need_animate_scroll_ = params.need_animate_scroll;
root_scroll_offset_ = params.total_scroll_offset;
+ invalidate_needs_draw_ |= params.invalidate_needs_draw;
if (need_invalidate_count_ != params.need_invalidate_count) {
need_invalidate_count_ = params.need_invalidate_count;
- client_->PostInvalidate(this);
+ if (invalidate_needs_draw_) {
+ client_->PostInvalidate(this);
+ } else {
+ GetSynchronousCompositor()->WillSkipDraw();
+ }
}
if (did_activate_pending_tree_count_ !=
diff --git a/chromium/content/browser/android/synchronous_compositor_host.h b/chromium/content/browser/android/synchronous_compositor_host.h
index 7333ee6a263..6990380f9c5 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.h
+++ b/chromium/content/browser/android/synchronous_compositor_host.h
@@ -141,6 +141,7 @@ class SynchronousCompositorHost : public SynchronousCompositor,
uint32_t renderer_param_version_;
bool need_animate_scroll_;
uint32_t need_invalidate_count_;
+ bool invalidate_needs_draw_;
uint32_t did_activate_pending_tree_count_;
uint32_t frame_metadata_version_ = 0u;
diff --git a/chromium/content/browser/android/url_request_content_job.cc b/chromium/content/browser/android/url_request_content_job.cc
index 7ea404b10e2..cebe3e0455e 100644
--- a/chromium/content/browser/android/url_request_content_job.cc
+++ b/chromium/content/browser/android/url_request_content_job.cc
@@ -81,8 +81,10 @@ int URLRequestContentJob::ReadRawData(net::IOBuffer* dest, int dest_size) {
return rv;
}
-bool URLRequestContentJob::IsRedirectResponse(GURL* location,
- int* http_status_code) {
+bool URLRequestContentJob::IsRedirectResponse(
+ GURL* location,
+ int* http_status_code,
+ bool* insecure_scheme_was_upgraded) {
return false;
}
diff --git a/chromium/content/browser/android/url_request_content_job.h b/chromium/content/browser/android/url_request_content_job.h
index 9f6b379b2c8..40a97470a83 100644
--- a/chromium/content/browser/android/url_request_content_job.h
+++ b/chromium/content/browser/android/url_request_content_job.h
@@ -43,7 +43,9 @@ class CONTENT_EXPORT URLRequestContentJob : public net::URLRequestJob {
void Start() override;
void Kill() override;
int ReadRawData(net::IOBuffer* buf, int buf_size) override;
- bool IsRedirectResponse(GURL* location, int* http_status_code) override;
+ bool IsRedirectResponse(GURL* location,
+ int* http_status_code,
+ bool* insecure_scheme_was_upgraded) override;
bool GetMimeType(std::string* mime_type) const override;
void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
diff --git a/chromium/content/browser/android/web_contents_observer_proxy.cc b/chromium/content/browser/android/web_contents_observer_proxy.cc
index 2aa3ab1f1ba..988ede89422 100644
--- a/chromium/content/browser/android/web_contents_observer_proxy.cc
+++ b/chromium/content/browser/android/web_contents_observer_proxy.cc
@@ -270,4 +270,11 @@ void WebContentsObserverProxy::SetToBaseURLForDataURLIfNeeded(
}
}
+void WebContentsObserverProxy::ViewportFitChanged(
+ blink::mojom::ViewportFit value) {
+ JNIEnv* env = AttachCurrentThread();
+ Java_WebContentsObserverProxy_viewportFitChanged(
+ env, java_observer_, as_jint(static_cast<int>(value)));
+}
+
} // namespace content
diff --git a/chromium/content/browser/android/web_contents_observer_proxy.h b/chromium/content/browser/android/web_contents_observer_proxy.h
index 2278b030e92..e79ad3edb59 100644
--- a/chromium/content/browser/android/web_contents_observer_proxy.h
+++ b/chromium/content/browser/android/web_contents_observer_proxy.h
@@ -58,6 +58,7 @@ class WebContentsObserverProxy : public WebContentsObserver {
void DidChangeThemeColor(SkColor color) override;
void MediaEffectivelyFullscreenChanged(bool is_fullscreen) override;
void SetToBaseURLForDataURLIfNeeded(std::string* url);
+ void ViewportFitChanged(blink::mojom::ViewportFit value) override;
base::android::ScopedJavaGlobalRef<jobject> java_observer_;
GURL base_url_of_last_started_data_url_;
diff --git a/chromium/content/browser/appcache/appcache_backend_impl.cc b/chromium/content/browser/appcache/appcache_backend_impl.cc
index f0150fb78aa..c2d1dee5f0e 100644
--- a/chromium/content/browser/appcache/appcache_backend_impl.cc
+++ b/chromium/content/browser/appcache/appcache_backend_impl.cc
@@ -126,39 +126,8 @@ void AppCacheBackendImpl::GetResourceList(
host->GetResourceList(resource_infos);
}
-std::unique_ptr<AppCacheHost> AppCacheBackendImpl::TransferHostOut(
- int host_id) {
- auto found = hosts_.find(host_id);
- if (found == hosts_.end()) {
- NOTREACHED();
- return std::unique_ptr<AppCacheHost>();
- }
-
- std::unique_ptr<AppCacheHost> transferree = std::move(found->second);
-
- // Put a new empty host in its place.
- found->second = std::make_unique<AppCacheHost>(host_id, frontend_, service_);
-
- // We give up ownership.
- transferree->PrepareForTransfer();
- return transferree;
-}
-
-void AppCacheBackendImpl::TransferHostIn(int new_host_id,
- std::unique_ptr<AppCacheHost> host) {
- auto found = hosts_.find(new_host_id);
- if (found == hosts_.end()) {
- NOTREACHED();
- return;
- }
-
- host->CompleteTransfer(new_host_id, frontend_);
- found->second = std::move(host);
-}
-
void AppCacheBackendImpl::RegisterPrecreatedHost(
std::unique_ptr<AppCacheHost> host) {
- DCHECK(IsBrowserSideNavigationEnabled());
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(host.get());
diff --git a/chromium/content/browser/appcache/appcache_backend_impl.h b/chromium/content/browser/appcache/appcache_backend_impl.h
index cf6d4352546..cf5b8e8e737 100644
--- a/chromium/content/browser/appcache/appcache_backend_impl.h
+++ b/chromium/content/browser/appcache/appcache_backend_impl.h
@@ -59,13 +59,6 @@ class CONTENT_EXPORT AppCacheBackendImpl {
using HostMap = base::hash_map<int, std::unique_ptr<AppCacheHost>>;
const HostMap& hosts() { return hosts_; }
- // Methods to support cross site navigations. Hosts are transferred
- // from process to process accordingly, deparented from the old
- // processes backend and reparented to the new.
- std::unique_ptr<AppCacheHost> TransferHostOut(int host_id);
- void TransferHostIn(int new_host_id, std::unique_ptr<AppCacheHost> host);
-
- // PlzNavigate
// The AppCacheHost is precreated by the AppCacheNavigationHandleCore class
// when a navigation is initiated. We register the host with the backend in
// this function and ignore registrations for this host id from the renderer.
diff --git a/chromium/content/browser/appcache/appcache_database.cc b/chromium/content/browser/appcache/appcache_database.cc
index 8e21b82f900..0f747557abb 100644
--- a/chromium/content/browser/appcache/appcache_database.cc
+++ b/chromium/content/browser/appcache/appcache_database.cc
@@ -250,8 +250,7 @@ bool AppCacheDatabase::FindOriginsWithGroups(std::set<url::Origin>* origins) {
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
- "SELECT DISTINCT(origin) FROM Groups";
+ static const char kSql[] = "SELECT DISTINCT(origin) FROM Groups";
sql::Statement statement(db_->GetUniqueStatement(kSql));
@@ -277,13 +276,13 @@ bool AppCacheDatabase::FindLastStorageIds(
if (!LazyOpen(kDontCreate))
return false;
- const char kMaxGroupIdSql[] = "SELECT MAX(group_id) FROM Groups";
- const char kMaxCacheIdSql[] = "SELECT MAX(cache_id) FROM Caches";
- const char kMaxResponseIdFromEntriesSql[] =
+ static const char kMaxGroupIdSql[] = "SELECT MAX(group_id) FROM Groups";
+ static const char kMaxCacheIdSql[] = "SELECT MAX(cache_id) FROM Caches";
+ static const char kMaxResponseIdFromEntriesSql[] =
"SELECT MAX(response_id) FROM Entries";
- const char kMaxResponseIdFromDeletablesSql[] =
+ static const char kMaxResponseIdFromDeletablesSql[] =
"SELECT MAX(response_id) FROM DeletableResponseIds";
- const char kMaxDeletableResponseRowIdSql[] =
+ static const char kMaxDeletableResponseRowIdSql[] =
"SELECT MAX(rowid) FROM DeletableResponseIds";
int64_t max_group_id;
int64_t max_cache_id;
@@ -314,7 +313,7 @@ bool AppCacheDatabase::FindGroup(int64_t group_id, GroupRecord* record) {
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT group_id, origin, manifest_url,"
" creation_time, last_access_time,"
" last_full_update_check_time,"
@@ -338,7 +337,7 @@ bool AppCacheDatabase::FindGroupForManifestUrl(
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT group_id, origin, manifest_url,"
" creation_time, last_access_time,"
" last_full_update_check_time,"
@@ -362,7 +361,7 @@ bool AppCacheDatabase::FindGroupsForOrigin(const url::Origin& origin,
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT group_id, origin, manifest_url,"
" creation_time, last_access_time,"
" last_full_update_check_time,"
@@ -387,7 +386,7 @@ bool AppCacheDatabase::FindGroupForCache(int64_t cache_id,
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT g.group_id, g.origin, g.manifest_url,"
" g.creation_time, g.last_access_time,"
" g.last_full_update_check_time,"
@@ -409,7 +408,7 @@ bool AppCacheDatabase::InsertGroup(const GroupRecord* record) {
if (!LazyOpen(kCreateIfNeeded))
return false;
- const char kSql[] =
+ static const char kSql[] =
"INSERT INTO Groups"
" (group_id, origin, manifest_url, creation_time, last_access_time,"
" last_full_update_check_time, first_evictable_error_time)"
@@ -429,8 +428,7 @@ bool AppCacheDatabase::DeleteGroup(int64_t group_id) {
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
- "DELETE FROM Groups WHERE group_id = ?";
+ static const char kSql[] = "DELETE FROM Groups WHERE group_id = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, group_id);
return statement.Run();
@@ -460,7 +458,7 @@ bool AppCacheDatabase::CommitLazyLastAccessTimes() {
if (!transaction.Begin())
return false;
for (const auto& pair : lazy_last_access_times_) {
- const char kSql[] =
+ static const char kSql[] =
"UPDATE Groups SET last_access_time = ? WHERE group_id = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, pair.second.ToInternalValue()); // time
@@ -478,7 +476,7 @@ bool AppCacheDatabase::UpdateEvictionTimes(
if (!LazyOpen(kCreateIfNeeded))
return false;
- const char kSql[] =
+ static const char kSql[] =
"UPDATE Groups"
" SET last_full_update_check_time = ?, first_evictable_error_time = ?"
" WHERE group_id = ?";
@@ -494,7 +492,7 @@ bool AppCacheDatabase::FindCache(int64_t cache_id, CacheRecord* record) {
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT cache_id, group_id, online_wildcard, update_time, cache_size"
" FROM Caches WHERE cache_id = ?";
@@ -514,7 +512,7 @@ bool AppCacheDatabase::FindCacheForGroup(int64_t group_id,
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT cache_id, group_id, online_wildcard, update_time, cache_size"
" FROM Caches WHERE group_id = ?";
@@ -547,7 +545,7 @@ bool AppCacheDatabase::InsertCache(const CacheRecord* record) {
if (!LazyOpen(kCreateIfNeeded))
return false;
- const char kSql[] =
+ static const char kSql[] =
"INSERT INTO Caches (cache_id, group_id, online_wildcard,"
" update_time, cache_size)"
" VALUES(?, ?, ?, ?, ?)";
@@ -566,8 +564,7 @@ bool AppCacheDatabase::DeleteCache(int64_t cache_id) {
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
- "DELETE FROM Caches WHERE cache_id = ?";
+ static const char kSql[] = "DELETE FROM Caches WHERE cache_id = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, cache_id);
@@ -581,7 +578,7 @@ bool AppCacheDatabase::FindEntriesForCache(int64_t cache_id,
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT cache_id, url, flags, response_id, response_size FROM Entries"
" WHERE cache_id = ?";
@@ -603,7 +600,7 @@ bool AppCacheDatabase::FindEntriesForUrl(
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT cache_id, url, flags, response_id, response_size FROM Entries"
" WHERE url = ?";
@@ -626,7 +623,7 @@ bool AppCacheDatabase::FindEntry(int64_t cache_id,
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT cache_id, url, flags, response_id, response_size FROM Entries"
" WHERE cache_id = ? AND url = ?";
@@ -647,7 +644,7 @@ bool AppCacheDatabase::InsertEntry(const EntryRecord* record) {
if (!LazyOpen(kCreateIfNeeded))
return false;
- const char kSql[] =
+ static const char kSql[] =
"INSERT INTO Entries (cache_id, url, flags, response_id, response_size)"
" VALUES(?, ?, ?, ?, ?)";
@@ -679,8 +676,7 @@ bool AppCacheDatabase::DeleteEntriesForCache(int64_t cache_id) {
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
- "DELETE FROM Entries WHERE cache_id = ?";
+ static const char kSql[] = "DELETE FROM Entries WHERE cache_id = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, cache_id);
@@ -694,7 +690,7 @@ bool AppCacheDatabase::AddEntryFlags(const GURL& entry_url,
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"UPDATE Entries SET flags = flags | ? WHERE cache_id = ? AND url = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
@@ -714,7 +710,7 @@ bool AppCacheDatabase::FindNamespacesForOrigin(
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT cache_id, origin, type, namespace_url, target_url, is_pattern"
" FROM Namespaces WHERE origin = ?";
@@ -735,7 +731,7 @@ bool AppCacheDatabase::FindNamespacesForCache(
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT cache_id, origin, type, namespace_url, target_url, is_pattern"
" FROM Namespaces WHERE cache_id = ?";
@@ -752,7 +748,7 @@ bool AppCacheDatabase::InsertNamespace(
if (!LazyOpen(kCreateIfNeeded))
return false;
- const char kSql[] =
+ static const char kSql[] =
"INSERT INTO Namespaces"
" (cache_id, origin, type, namespace_url, target_url, is_pattern)"
" VALUES (?, ?, ?, ?, ?, ?)";
@@ -785,8 +781,7 @@ bool AppCacheDatabase::DeleteNamespacesForCache(int64_t cache_id) {
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
- "DELETE FROM Namespaces WHERE cache_id = ?";
+ static const char kSql[] = "DELETE FROM Namespaces WHERE cache_id = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, cache_id);
@@ -801,7 +796,7 @@ bool AppCacheDatabase::FindOnlineWhiteListForCache(
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT cache_id, namespace_url, is_pattern FROM OnlineWhiteLists"
" WHERE cache_id = ?";
@@ -821,7 +816,7 @@ bool AppCacheDatabase::InsertOnlineWhiteList(
if (!LazyOpen(kCreateIfNeeded))
return false;
- const char kSql[] =
+ static const char kSql[] =
"INSERT INTO OnlineWhiteLists (cache_id, namespace_url, is_pattern)"
" VALUES (?, ?, ?)";
@@ -851,8 +846,7 @@ bool AppCacheDatabase::DeleteOnlineWhiteListForCache(int64_t cache_id) {
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
- "DELETE FROM OnlineWhiteLists WHERE cache_id = ?";
+ static const char kSql[] = "DELETE FROM OnlineWhiteLists WHERE cache_id = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, cache_id);
@@ -867,7 +861,7 @@ bool AppCacheDatabase::GetDeletableResponseIds(
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT response_id FROM DeletableResponseIds "
" WHERE rowid <= ?"
" LIMIT ?";
@@ -883,20 +877,20 @@ bool AppCacheDatabase::GetDeletableResponseIds(
bool AppCacheDatabase::InsertDeletableResponseIds(
const std::vector<int64_t>& response_ids) {
- const char kSql[] =
+ static const char kSql[] =
"INSERT INTO DeletableResponseIds (response_id) VALUES (?)";
return RunCachedStatementWithIds(SQL_FROM_HERE, kSql, response_ids);
}
bool AppCacheDatabase::DeleteDeletableResponseIds(
const std::vector<int64_t>& response_ids) {
- const char kSql[] =
+ static const char kSql[] =
"DELETE FROM DeletableResponseIds WHERE response_id = ?";
return RunCachedStatementWithIds(SQL_FROM_HERE, kSql, response_ids);
}
bool AppCacheDatabase::RunCachedStatementWithIds(
- const sql::StatementID& statement_id,
+ sql::StatementID statement_id,
const char* sql,
const std::vector<int64_t>& ids) {
DCHECK(sql);
@@ -939,7 +933,7 @@ bool AppCacheDatabase::FindResponseIdsForCacheHelper(
if (!LazyOpen(kDontCreate))
return false;
- const char kSql[] =
+ static const char kSql[] =
"SELECT response_id FROM Entries WHERE cache_id = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
diff --git a/chromium/content/browser/appcache/appcache_database.h b/chromium/content/browser/appcache/appcache_database.h
index 1150724619e..164f6b58772 100644
--- a/chromium/content/browser/appcache/appcache_database.h
+++ b/chromium/content/browser/appcache/appcache_database.h
@@ -18,6 +18,7 @@
#include "base/time/time.h"
#include "content/common/appcache_interfaces.h"
#include "content/common/content_export.h"
+#include "sql/statement_id.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -25,7 +26,6 @@ namespace sql {
class Connection;
class MetaTable;
class Statement;
-class StatementID;
}
namespace content {
@@ -196,7 +196,7 @@ class CONTENT_EXPORT AppCacheDatabase {
}
private:
- bool RunCachedStatementWithIds(const sql::StatementID& statement_id,
+ bool RunCachedStatementWithIds(sql::StatementID statement_id,
const char* sql,
const std::vector<int64_t>& ids);
bool RunUniqueStatementWithInt64Result(const char* sql, int64_t* result);
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.cc b/chromium/content/browser/appcache/appcache_disk_cache.cc
index d718034f704..8c28d1862d7 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache.cc
@@ -126,7 +126,7 @@ class AppCacheDiskCache::ActiveCall
scoped_refptr<ActiveCall> active_call(
new ActiveCall(owner, entry, callback));
int rv = owner->disk_cache()->CreateEntry(
- base::Int64ToString(key), &active_call->entry_ptr_,
+ base::Int64ToString(key), net::HIGHEST, &active_call->entry_ptr_,
base::Bind(&ActiveCall::OnAsyncCompletion, active_call));
return active_call->HandleImmediateReturnValue(rv);
}
@@ -138,7 +138,7 @@ class AppCacheDiskCache::ActiveCall
scoped_refptr<ActiveCall> active_call(
new ActiveCall(owner, entry, callback));
int rv = owner->disk_cache()->OpenEntry(
- base::Int64ToString(key), &active_call->entry_ptr_,
+ base::Int64ToString(key), net::HIGHEST, &active_call->entry_ptr_,
base::Bind(&ActiveCall::OnAsyncCompletion, active_call));
return active_call->HandleImmediateReturnValue(rv);
}
@@ -149,7 +149,7 @@ class AppCacheDiskCache::ActiveCall
scoped_refptr<ActiveCall> active_call(
new ActiveCall(owner, nullptr, callback));
int rv = owner->disk_cache()->DoomEntry(
- base::Int64ToString(key),
+ base::Int64ToString(key), net::HIGHEST,
base::Bind(&ActiveCall::OnAsyncCompletion, active_call));
return active_call->HandleImmediateReturnValue(rv);
}
diff --git a/chromium/content/browser/appcache/appcache_dispatcher_host.cc b/chromium/content/browser/appcache/appcache_dispatcher_host.cc
index d5c6a6f1266..966ab0e1271 100644
--- a/chromium/content/browser/appcache/appcache_dispatcher_host.cc
+++ b/chromium/content/browser/appcache/appcache_dispatcher_host.cc
@@ -32,24 +32,30 @@ AppCacheDispatcherHost::~AppCacheDispatcherHost() = default;
void AppCacheDispatcherHost::Create(ChromeAppCacheService* appcache_service,
int process_id,
mojom::AppCacheBackendRequest request) {
+ // The process_id is the id of the RenderProcessHost, which can be reused for
+ // a new renderer process if the previous renderer process was shutdown.
+ // It can take some time after shutdown for the pipe error to propagate
+ // and unregister the previous backend. Since the AppCacheService assumes
+ // that there is one backend per process_id, we need to ensure that the
+ // previous backend is unregistered by eagerly unbinding the pipe.
+ appcache_service->Unbind(process_id);
+
appcache_service->Bind(
std::make_unique<AppCacheDispatcherHost>(appcache_service, process_id),
- std::move(request));
+ std::move(request), process_id);
}
void AppCacheDispatcherHost::RegisterHost(int32_t host_id) {
if (appcache_service_) {
- // PlzNavigate
// The AppCacheHost could have been precreated in which case we want to
// register it with the backend here.
- if (IsBrowserSideNavigationEnabled()) {
- std::unique_ptr<content::AppCacheHost> host =
- AppCacheNavigationHandleCore::GetPrecreatedHost(host_id);
- if (host.get()) {
- backend_impl_.RegisterPrecreatedHost(std::move(host));
- return;
- }
+ std::unique_ptr<content::AppCacheHost> host =
+ AppCacheNavigationHandleCore::GetPrecreatedHost(host_id);
+ if (host.get()) {
+ backend_impl_.RegisterPrecreatedHost(std::move(host));
+ return;
}
+
if (!backend_impl_.RegisterHost(host_id)) {
mojo::ReportBadMessage("ACDH_REGISTER");
}
diff --git a/chromium/content/browser/appcache/appcache_host.cc b/chromium/content/browser/appcache/appcache_host.cc
index eb88a3b00d8..2b27d83d316 100644
--- a/chromium/content/browser/appcache/appcache_host.cc
+++ b/chromium/content/browser/appcache/appcache_host.cc
@@ -509,20 +509,6 @@ void AppCacheHost::NotifyMainResourceBlocked(const GURL& manifest_url) {
blocked_manifest_url_ = manifest_url;
}
-void AppCacheHost::PrepareForTransfer() {
- // This can only happen prior to the document having been loaded.
- DCHECK(!associated_cache());
- DCHECK(!is_selection_pending());
- DCHECK(!group_being_updated_.get());
- host_id_ = kAppCacheNoHostId;
- frontend_ = nullptr;
-}
-
-void AppCacheHost::CompleteTransfer(int host_id, AppCacheFrontend* frontend) {
- host_id_ = host_id;
- frontend_ = frontend;
-}
-
base::WeakPtr<AppCacheHost> AppCacheHost::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
@@ -539,7 +525,8 @@ void AppCacheHost::MaybePassSubresourceFactory() {
network::mojom::URLLoaderFactoryPtr factory_ptr = nullptr;
AppCacheSubresourceURLFactory::CreateURLLoaderFactory(
- service()->url_loader_factory_getter(), GetWeakPtr(), &factory_ptr);
+ service()->url_loader_factory_getter()->GetNetworkFactory(), GetWeakPtr(),
+ &factory_ptr);
frontend_->OnSetSubresourceFactory(host_id(), std::move(factory_ptr));
}
diff --git a/chromium/content/browser/appcache/appcache_host.h b/chromium/content/browser/appcache/appcache_host.h
index 7da6f38ede7..e5d29763fda 100644
--- a/chromium/content/browser/appcache/appcache_host.h
+++ b/chromium/content/browser/appcache/appcache_host.h
@@ -191,10 +191,6 @@ class CONTENT_EXPORT AppCacheHost
const GURL& first_party_url() const { return first_party_url_; }
- // Methods to support cross site navigations.
- void PrepareForTransfer();
- void CompleteTransfer(int host_id, AppCacheFrontend* frontend);
-
// Returns a weak pointer reference to the host.
base::WeakPtr<AppCacheHost> GetWeakPtr();
diff --git a/chromium/content/browser/appcache/appcache_internals_ui.cc b/chromium/content/browser/appcache/appcache_internals_ui.cc
index 3a34269fbc0..f33713440f4 100644
--- a/chromium/content/browser/appcache/appcache_internals_ui.cc
+++ b/chromium/content/browser/appcache/appcache_internals_ui.cc
@@ -350,6 +350,8 @@ AppCacheInternalsUI::AppCacheInternalsUI(WebUI* web_ui)
WebUIDataSource* source =
WebUIDataSource::Create(kChromeUIAppCacheInternalsHost);
+ source->OverrideContentSecurityPolicyScriptSrc(
+ "script-src chrome://resources 'self' 'unsafe-eval';");
source->SetJsonPath("strings.js");
source->AddResourcePath("appcache_internals.js", IDR_APPCACHE_INTERNALS_JS);
diff --git a/chromium/content/browser/appcache/appcache_navigation_handle.cc b/chromium/content/browser/appcache/appcache_navigation_handle.cc
index 6c47bf8a415..b6bf5de3d8f 100644
--- a/chromium/content/browser/appcache/appcache_navigation_handle.cc
+++ b/chromium/content/browser/appcache/appcache_navigation_handle.cc
@@ -8,11 +8,10 @@
#include "content/browser/appcache/appcache_navigation_handle_core.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/common/appcache_info.h"
namespace {
-// PlzNavigate: Used to generate the host id for a navigation initiated by the
-// browser. Starts at -2 and keeps going down.
+// Used to generate the host id for a navigation initiated by the browser.
+// Starts at -1 and keeps going down.
static int g_next_appcache_host_id = -1;
}
@@ -20,13 +19,10 @@ namespace content {
AppCacheNavigationHandle::AppCacheNavigationHandle(
ChromeAppCacheService* appcache_service)
- : appcache_host_id_(kAppCacheNoHostId),
- core_(nullptr),
- weak_factory_(this) {
+ : appcache_host_id_(g_next_appcache_host_id--),
+ core_(std::make_unique<AppCacheNavigationHandleCore>(appcache_service,
+ appcache_host_id_)) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- appcache_host_id_ = g_next_appcache_host_id--;
- core_.reset(new AppCacheNavigationHandleCore(
- weak_factory_.GetWeakPtr(), appcache_service, appcache_host_id_));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&AppCacheNavigationHandleCore::Initialize,
diff --git a/chromium/content/browser/appcache/appcache_navigation_handle.h b/chromium/content/browser/appcache/appcache_navigation_handle.h
index 535849a7144..0b910604307 100644
--- a/chromium/content/browser/appcache/appcache_navigation_handle.h
+++ b/chromium/content/browser/appcache/appcache_navigation_handle.h
@@ -7,8 +7,6 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
namespace content {
@@ -42,7 +40,7 @@ class ChromeAppCacheService;
// update the RequestNavigationParams based on the id from the
// AppCacheNavigationHandle.
//
-// 6. The commit leads to AppCache registrations happening from the renderer.
+// 6) The commit leads to AppCache registrations happening from the renderer.
// This is via the IPC message AppCacheHostMsg_RegisterHost. The
// AppCacheDispatcherHost class which handles these IPCs will be informed
// about these hosts when the navigation commits. It will ignore the
@@ -52,24 +50,19 @@ class ChromeAppCacheService;
// 7) When the navigation finishes, the AppCacheNavigationHandle is
// destroyed. The destructor of the AppCacheNavigationHandle posts a
-// task to destroy the AppacheNavigationHandleCore on the IO thread.
+// task to destroy the AppCacheNavigationHandleCore on the IO thread.
class AppCacheNavigationHandle {
public:
- AppCacheNavigationHandle(ChromeAppCacheService* appcache_service);
+ explicit AppCacheNavigationHandle(ChromeAppCacheService* appcache_service);
~AppCacheNavigationHandle();
int appcache_host_id() const { return appcache_host_id_; }
AppCacheNavigationHandleCore* core() const { return core_.get(); }
- // Called when a navigation is committed. The |process_id| parameter is
- // is the process id of the renderer.
- void CommitNavigation(int process_id);
-
private:
- int appcache_host_id_;
+ const int appcache_host_id_;
std::unique_ptr<AppCacheNavigationHandleCore> core_;
- base::WeakPtrFactory<AppCacheNavigationHandle> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(AppCacheNavigationHandle);
};
diff --git a/chromium/content/browser/appcache/appcache_navigation_handle_core.cc b/chromium/content/browser/appcache/appcache_navigation_handle_core.cc
index 1121e40975e..0c20a8fd7a7 100644
--- a/chromium/content/browser/appcache/appcache_navigation_handle_core.cc
+++ b/chromium/content/browser/appcache/appcache_navigation_handle_core.cc
@@ -28,14 +28,10 @@ base::LazyInstance<AppCacheHandleMap>::DestructorAtExit g_appcache_handle_map =
namespace content {
-
AppCacheNavigationHandleCore::AppCacheNavigationHandleCore(
- base::WeakPtr<AppCacheNavigationHandle> ui_handle,
ChromeAppCacheService* appcache_service,
int appcache_host_id)
- : appcache_service_(appcache_service),
- appcache_host_id_(appcache_host_id),
- ui_handle_(ui_handle) {
+ : appcache_service_(appcache_service), appcache_host_id_(appcache_host_id) {
// The AppCacheNavigationHandleCore is created on the UI thread but
// should only be accessed from the IO thread afterwards.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chromium/content/browser/appcache/appcache_navigation_handle_core.h b/chromium/content/browser/appcache/appcache_navigation_handle_core.h
index 93561916a65..b50429269f8 100644
--- a/chromium/content/browser/appcache/appcache_navigation_handle_core.h
+++ b/chromium/content/browser/appcache/appcache_navigation_handle_core.h
@@ -29,7 +29,6 @@ class ChromeAppCacheService;
class AppCacheNavigationHandleCore : public AppCacheFrontend {
public:
AppCacheNavigationHandleCore(
- base::WeakPtr<AppCacheNavigationHandle> ui_handle,
ChromeAppCacheService* appcache_service,
int appcache_host_id);
~AppCacheNavigationHandleCore() override;
@@ -73,7 +72,6 @@ class AppCacheNavigationHandleCore : public AppCacheFrontend {
std::unique_ptr<AppCacheHost> precreated_host_;
scoped_refptr<ChromeAppCacheService> appcache_service_;
int appcache_host_id_;
- base::WeakPtr<AppCacheNavigationHandle> ui_handle_;
DISALLOW_COPY_AND_ASSIGN(AppCacheNavigationHandleCore);
};
diff --git a/chromium/content/browser/appcache/appcache_request_handler.cc b/chromium/content/browser/appcache/appcache_request_handler.cc
index 07d2b0573e4..7f291f904b0 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler.cc
@@ -225,13 +225,13 @@ std::unique_ptr<AppCacheRequestHandler>
AppCacheRequestHandler::InitializeForNavigationNetworkService(
const network::ResourceRequest& request,
AppCacheNavigationHandleCore* appcache_handle_core,
- URLLoaderFactoryGetter* url_loader_factory_getter) {
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory) {
std::unique_ptr<AppCacheRequestHandler> handler =
appcache_handle_core->host()->CreateRequestHandler(
AppCacheURLLoaderRequest::Create(request),
static_cast<ResourceType>(request.resource_type),
request.should_reset_appcache);
- handler->network_url_loader_factory_getter_ = url_loader_factory_getter;
+ handler->network_loader_factory_ = std::move(network_loader_factory);
handler->appcache_host_ = appcache_handle_core->host()->GetWeakPtr();
return handler;
}
@@ -600,7 +600,7 @@ AppCacheRequestHandler::MaybeCreateSubresourceLoaderParams() {
// The factory is destroyed when the renderer drops the connection.
network::mojom::URLLoaderFactoryPtr factory_ptr;
AppCacheSubresourceURLFactory::CreateURLLoaderFactory(
- network_url_loader_factory_getter_.get(), appcache_host_, &factory_ptr);
+ network_loader_factory_, appcache_host_, &factory_ptr);
SubresourceLoaderParams params;
params.loader_factory_info = factory_ptr.PassInterface();
diff --git a/chromium/content/browser/appcache/appcache_request_handler.h b/chromium/content/browser/appcache/appcache_request_handler.h
index cea61697ba8..b8b82668b0e 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.h
+++ b/chromium/content/browser/appcache/appcache_request_handler.h
@@ -18,9 +18,9 @@
#include "content/browser/appcache/appcache_request_handler.h"
#include "content/browser/appcache/appcache_service_impl.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
-#include "content/browser/url_loader_factory_getter.h"
#include "content/common/content_export.h"
#include "content/public/common/resource_type.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace net {
class NetworkDelegate;
@@ -109,7 +109,7 @@ class CONTENT_EXPORT AppCacheRequestHandler
InitializeForNavigationNetworkService(
const network::ResourceRequest& request,
AppCacheNavigationHandleCore* appcache_handle_core,
- URLLoaderFactoryGetter* url_loader_factory_getter);
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory);
static bool IsMainResourceType(ResourceType type) {
return IsResourceTypeFrame(type) || type == RESOURCE_TYPE_SHARED_WORKER;
@@ -257,8 +257,8 @@ class CONTENT_EXPORT AppCacheRequestHandler
// RequestHandler for non-error cases.
bool should_create_subresource_loader_ = false;
- // Points to the getter for the network URL loader.
- scoped_refptr<URLLoaderFactoryGetter> network_url_loader_factory_getter_;
+ // The network URL loader factory.
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
// The AppCache host instance. We pass this to the
// AppCacheSubresourceURLFactory instance on creation.
diff --git a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
index 3e742cdca67..bd3494c4aa9 100644
--- a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -22,7 +22,6 @@
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/appcache/appcache.h"
@@ -34,6 +33,7 @@
#include "content/browser/appcache/appcache_url_request_job.h"
#include "content/browser/appcache/mock_appcache_policy.h"
#include "content/browser/appcache/mock_appcache_service.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
#include "net/http/http_response_headers.h"
@@ -202,15 +202,14 @@ class AppCacheRequestHandlerTest
};
static void SetUpTestCase() {
- scoped_task_environment_.reset(new base::test::ScopedTaskEnvironment);
- io_thread_.reset(new base::Thread("AppCacheRequestHandlerTest Thread"));
- base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
- io_thread_->StartWithOptions(options);
+ thread_bundle_.reset(
+ new TestBrowserThreadBundle(TestBrowserThreadBundle::REAL_IO_THREAD));
+ io_task_runner_ = BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
}
static void TearDownTestCase() {
- io_thread_.reset();
- scoped_task_environment_.reset();
+ thread_bundle_.reset();
+ io_task_runner_ = nullptr;
}
// Test harness --------------------------------------------------
@@ -231,7 +230,7 @@ class AppCacheRequestHandlerTest
test_finished_event_.reset(new base::WaitableEvent(
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED));
- io_thread_->task_runner()->PostTask(
+ io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&AppCacheRequestHandlerTest::MethodWrapper<Method>,
base::Unretained(this), method));
@@ -239,7 +238,7 @@ class AppCacheRequestHandlerTest
}
void SetUpTest() {
- DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
+ DCHECK(io_task_runner_->BelongsToCurrentThread());
mock_service_.reset(new MockAppCacheService);
// Initializes URLRequestContext on the IO thread.
empty_context_.reset(new net::URLRequestContext);
@@ -258,7 +257,7 @@ class AppCacheRequestHandlerTest
}
void TearDownTest() {
- DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
+ DCHECK(io_task_runner_->BelongsToCurrentThread());
appcache_url_request_job_.reset();
appcache_url_loader_job_.reset();
handler_.reset();
@@ -276,7 +275,7 @@ class AppCacheRequestHandlerTest
void TestFinished() {
// We unwind the stack prior to finishing up to let stack
// based objects get deleted.
- DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
+ DCHECK(io_task_runner_->BelongsToCurrentThread());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&AppCacheRequestHandlerTest::TestFinishedUnwound,
@@ -293,7 +292,7 @@ class AppCacheRequestHandlerTest
}
void ScheduleNextTask() {
- DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
+ DCHECK(io_task_runner_->BelongsToCurrentThread());
if (task_stack_.empty()) {
TestFinished();
return;
@@ -969,18 +968,18 @@ class AppCacheRequestHandlerTest
std::unique_ptr<AppCacheURLRequestJob> appcache_url_request_job_;
base::WeakPtr<AppCacheURLLoaderJob> appcache_url_loader_job_;
- static std::unique_ptr<base::Thread> io_thread_;
- static std::unique_ptr<base::test::ScopedTaskEnvironment>
- scoped_task_environment_;
+ static std::unique_ptr<TestBrowserThreadBundle> thread_bundle_;
+ static scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
RequestHandlerType request_handler_type_;
base::test::ScopedFeatureList feature_list_;
};
// static
-std::unique_ptr<base::Thread> AppCacheRequestHandlerTest::io_thread_;
-std::unique_ptr<base::test::ScopedTaskEnvironment>
- AppCacheRequestHandlerTest::scoped_task_environment_;
+std::unique_ptr<TestBrowserThreadBundle>
+ AppCacheRequestHandlerTest::thread_bundle_;
+scoped_refptr<base::SingleThreadTaskRunner>
+ AppCacheRequestHandlerTest::io_task_runner_;
TEST_P(AppCacheRequestHandlerTest, MainResource_Miss) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Miss);
diff --git a/chromium/content/browser/appcache/appcache_service_impl.h b/chromium/content/browser/appcache/appcache_service_impl.h
index ff3bcd5153d..bf6fabe30ff 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.h
+++ b/chromium/content/browser/appcache/appcache_service_impl.h
@@ -153,7 +153,7 @@ class CONTENT_EXPORT AppCacheServiceImpl
// Each child process in chrome uses a distinct backend instance.
// See chrome/browser/AppCacheDispatcherHost.
void RegisterBackend(AppCacheBackendImpl* backend_impl);
- void UnregisterBackend(AppCacheBackendImpl* backend_impl);
+ virtual void UnregisterBackend(AppCacheBackendImpl* backend_impl);
AppCacheBackendImpl* GetBackend(int id) const {
BackendMap::const_iterator it = backends_.find(id);
return (it != backends_.end()) ? it->second : NULL;
diff --git a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
index 43400a1f726..03237c227d3 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -375,7 +375,9 @@ class AppCacheStorageImplTest : public testing::Test {
// Test harness --------------------------------------------------
- AppCacheStorageImplTest() { request_delegate_.set_quit_on_complete(false); }
+ AppCacheStorageImplTest() {
+ request_delegate_.set_on_complete(base::DoNothing());
+ }
template <class Method>
void RunTestOnIOThread(Method method) {
diff --git a/chromium/content/browser/appcache/appcache_subresource_url_factory.cc b/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
index 72bb381ee93..08336328e4e 100644
--- a/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
+++ b/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -10,7 +10,6 @@
#include "content/browser/appcache/appcache_request_handler.h"
#include "content/browser/appcache/appcache_url_loader_job.h"
#include "content/browser/appcache/appcache_url_loader_request.h"
-#include "content/browser/url_loader_factory_getter.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/binding_set.h"
@@ -38,15 +37,16 @@ namespace {
class SubresourceLoader : public network::mojom::URLLoader,
public network::mojom::URLLoaderClient {
public:
- SubresourceLoader(network::mojom::URLLoaderRequest url_loader_request,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- const network::ResourceRequest& request,
- network::mojom::URLLoaderClientPtr client,
- const net::MutableNetworkTrafficAnnotationTag& annotation,
- base::WeakPtr<AppCacheHost> appcache_host,
- scoped_refptr<URLLoaderFactoryGetter> net_factory_getter)
+ SubresourceLoader(
+ network::mojom::URLLoaderRequest url_loader_request,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& request,
+ network::mojom::URLLoaderClientPtr client,
+ const net::MutableNetworkTrafficAnnotationTag& annotation,
+ base::WeakPtr<AppCacheHost> appcache_host,
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory)
: remote_binding_(this, std::move(url_loader_request)),
remote_client_(std::move(client)),
request_(request),
@@ -54,7 +54,7 @@ class SubresourceLoader : public network::mojom::URLLoader,
request_id_(request_id),
options_(options),
traffic_annotation_(annotation),
- network_loader_factory_(std::move(net_factory_getter)),
+ network_loader_factory_(std::move(network_loader_factory)),
local_client_binding_(this),
host_(appcache_host),
weak_factory_(this) {
@@ -116,7 +116,7 @@ class SubresourceLoader : public network::mojom::URLLoader,
DCHECK(!appcache_loader_);
network::mojom::URLLoaderClientPtr client_ptr;
local_client_binding_.Bind(mojo::MakeRequest(&client_ptr));
- network_loader_factory_->GetNetworkFactory()->CreateLoaderAndStart(
+ network_loader_factory_->CreateLoaderAndStart(
mojo::MakeRequest(&network_loader_), routing_id_, request_id_, options_,
request_, std::move(client_ptr), traffic_annotation_);
if (has_set_priority_)
@@ -127,13 +127,15 @@ class SubresourceLoader : public network::mojom::URLLoader,
// network::mojom::URLLoader implementation
// Called by the remote client in the renderer.
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override {
DCHECK(!modified_request_headers.has_value())
<< "Redirect with modified headers was not supported yet. "
"crbug.com/845683";
if (!handler_) {
- network_loader_->FollowRedirect(base::nullopt);
+ network_loader_->FollowRedirect(base::nullopt, base::nullopt);
return;
}
DCHECK(network_loader_);
@@ -152,7 +154,7 @@ class SubresourceLoader : public network::mojom::URLLoader,
if (handler)
CreateAndStartAppCacheLoader(std::move(handler));
else
- network_loader_->FollowRedirect(base::nullopt);
+ network_loader_->FollowRedirect(base::nullopt, base::nullopt);
}
void SetPriority(net::RequestPriority priority,
@@ -179,12 +181,10 @@ class SubresourceLoader : public network::mojom::URLLoader,
// network::mojom::URLLoaderClient implementation
// Called by either the appcache or network loader, whichever is in use.
void OnReceiveResponse(
- const network::ResourceResponseHead& response_head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override {
+ const network::ResourceResponseHead& response_head) override {
// Don't MaybeFallback for appcache produced responses.
if (appcache_loader_ || !handler_) {
- remote_client_->OnReceiveResponse(response_head,
- std::move(downloaded_file));
+ remote_client_->OnReceiveResponse(response_head);
return;
}
@@ -192,19 +192,16 @@ class SubresourceLoader : public network::mojom::URLLoader,
handler_->MaybeFallbackForSubresourceResponse(
response_head,
base::BindOnce(&SubresourceLoader::ContinueOnReceiveResponse,
- weak_factory_.GetWeakPtr(), response_head,
- std::move(downloaded_file)));
+ weak_factory_.GetWeakPtr(), response_head));
}
void ContinueOnReceiveResponse(
const network::ResourceResponseHead& response_head,
- network::mojom::DownloadedTempFilePtr downloaded_file,
SingleRequestURLLoaderFactory::RequestHandler handler) {
if (handler) {
CreateAndStartAppCacheLoader(std::move(handler));
} else {
- remote_client_->OnReceiveResponse(response_head,
- std::move(downloaded_file));
+ remote_client_->OnReceiveResponse(response_head);
}
}
@@ -237,10 +234,6 @@ class SubresourceLoader : public network::mojom::URLLoader,
remote_client_->OnReceiveRedirect(redirect_info_, response_head);
}
- void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override {
- remote_client_->OnDataDownloaded(data_len, encoded_data_len);
- }
-
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override {
@@ -291,7 +284,7 @@ class SubresourceLoader : public network::mojom::URLLoader,
int32_t request_id_;
uint32_t options_;
net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
- scoped_refptr<URLLoaderFactoryGetter> network_loader_factory_;
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
net::RedirectInfo redirect_info_;
int redirect_limit_ = net::URLRequest::kMaxRedirects;
bool did_receive_network_response_ = false;
@@ -319,9 +312,9 @@ class SubresourceLoader : public network::mojom::URLLoader,
// Implements the URLLoaderFactory mojom for AppCache requests.
AppCacheSubresourceURLFactory::AppCacheSubresourceURLFactory(
- URLLoaderFactoryGetter* default_url_loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
base::WeakPtr<AppCacheHost> host)
- : default_url_loader_factory_getter_(default_url_loader_factory_getter),
+ : network_loader_factory_(std::move(network_loader_factory)),
appcache_host_(host),
weak_factory_(this) {
bindings_.set_connection_error_handler(
@@ -333,7 +326,7 @@ AppCacheSubresourceURLFactory::~AppCacheSubresourceURLFactory() {}
// static
void AppCacheSubresourceURLFactory::CreateURLLoaderFactory(
- URLLoaderFactoryGetter* default_url_loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
base::WeakPtr<AppCacheHost> host,
network::mojom::URLLoaderFactoryPtr* loader_factory) {
DCHECK(host.get());
@@ -341,7 +334,7 @@ void AppCacheSubresourceURLFactory::CreateURLLoaderFactory(
// to it and will get deleted when all clients drop their connections.
// Please see OnConnectionError() for details.
auto* impl = new AppCacheSubresourceURLFactory(
- default_url_loader_factory_getter, host);
+ std::move(network_loader_factory), host);
impl->Clone(mojo::MakeRequest(loader_factory));
// Save the factory in the host to ensure that we don't create it again when
@@ -360,7 +353,7 @@ void AppCacheSubresourceURLFactory::CreateLoaderAndStart(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
new SubresourceLoader(std::move(url_loader_request), routing_id, request_id,
options, request, std::move(client), traffic_annotation,
- appcache_host_, default_url_loader_factory_getter_);
+ appcache_host_, network_loader_factory_);
}
void AppCacheSubresourceURLFactory::Clone(
diff --git a/chromium/content/browser/appcache/appcache_subresource_url_factory.h b/chromium/content/browser/appcache/appcache_subresource_url_factory.h
index 9ed9fc82161..c2ecf3420cd 100644
--- a/chromium/content/browser/appcache/appcache_subresource_url_factory.h
+++ b/chromium/content/browser/appcache/appcache_subresource_url_factory.h
@@ -13,13 +13,16 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "url/gurl.h"
+namespace network {
+class SharedURLLoaderFactory;
+}
+
namespace content {
class AppCacheHost;
class AppCacheJob;
class AppCacheRequestHandler;
class AppCacheServiceImpl;
-class URLLoaderFactoryGetter;
// Implements the URLLoaderFactory mojom for AppCache subresource requests.
class CONTENT_EXPORT AppCacheSubresourceURLFactory
@@ -28,13 +31,12 @@ class CONTENT_EXPORT AppCacheSubresourceURLFactory
~AppCacheSubresourceURLFactory() override;
// Factory function to create an instance of the factory.
- // 1. The |factory_getter| parameter is used to query the network service
- // to pass network requests to.
- // 2. The |host| parameter contains the appcache host instance. This is used
- // to create the AppCacheRequestHandler instances for handling subresource
- // requests.
+ // The |host| parameter contains the appcache host instance. This is used
+ // to create the AppCacheRequestHandler instances for handling subresource
+ // requests.
+ // |network_loader_factory| is a factory to the Network Service.
static void CreateURLLoaderFactory(
- URLLoaderFactoryGetter* factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
base::WeakPtr<AppCacheHost> host,
network::mojom::URLLoaderFactoryPtr* loader_factory);
@@ -56,12 +58,13 @@ class CONTENT_EXPORT AppCacheSubresourceURLFactory
// TODO(michaeln): Declare SubresourceLoader here and add unittests.
- AppCacheSubresourceURLFactory(URLLoaderFactoryGetter* factory_getter,
- base::WeakPtr<AppCacheHost> host);
+ AppCacheSubresourceURLFactory(
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
+ base::WeakPtr<AppCacheHost> host);
void OnConnectionError();
mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
- scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_;
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
base::WeakPtr<AppCacheHost> appcache_host_;
base::WeakPtrFactory<AppCacheSubresourceURLFactory> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(AppCacheSubresourceURLFactory);
diff --git a/chromium/content/browser/appcache/appcache_update_job_unittest.cc b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
index c02b0f17956..d801ffce9a4 100644
--- a/chromium/content/browser/appcache/appcache_update_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
@@ -624,7 +624,7 @@ class MockURLLoaderFactory : public network::mojom::URLLoaderFactory {
response.headers = info.headers;
response.headers->GetMimeType(&response.mime_type);
- client->OnReceiveResponse(response, nullptr);
+ client->OnReceiveResponse(response);
mojo::DataPipe data_pipe;
@@ -831,10 +831,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
expected = 2; // 2 hosts using frontend1
EXPECT_EQ(expected, events[0].first.size());
MockFrontend::HostIds& host_ids = events[0].first;
- EXPECT_TRUE(std::find(host_ids.begin(), host_ids.end(), host1.host_id())
- != host_ids.end());
- EXPECT_TRUE(std::find(host_ids.begin(), host_ids.end(), host3.host_id())
- != host_ids.end());
+ EXPECT_TRUE(base::ContainsValue(host_ids, host1.host_id()));
+ EXPECT_TRUE(base::ContainsValue(host_ids, host3.host_id()));
EXPECT_EQ(AppCacheEventID::APPCACHE_CHECKING_EVENT, events[0].second);
events = mock_frontend2.raised_events_;
@@ -3644,8 +3642,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
for (size_t k = 0; k < expected_ids.size(); ++k) {
int id = expected_ids[k];
- EXPECT_TRUE(std::find(actual_ids.begin(), actual_ids.end(), id) !=
- actual_ids.end());
+ EXPECT_TRUE(base::ContainsValue(actual_ids, id));
}
}
diff --git a/chromium/content/browser/appcache/appcache_update_url_loader_request.cc b/chromium/content/browser/appcache/appcache_update_url_loader_request.cc
index 321e4fad8ba..3f5051c2d8c 100644
--- a/chromium/content/browser/appcache/appcache_update_url_loader_request.cc
+++ b/chromium/content/browser/appcache/appcache_update_url_loader_request.cc
@@ -94,8 +94,7 @@ int AppCacheUpdateJob::UpdateURLLoaderRequest::Cancel() {
}
void AppCacheUpdateJob::UpdateURLLoaderRequest::OnReceiveResponse(
- const network::ResourceResponseHead& response_head,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
+ const network::ResourceResponseHead& response_head) {
response_ = response_head;
// TODO(ananta/michaeln)
@@ -123,12 +122,6 @@ void AppCacheUpdateJob::UpdateURLLoaderRequest::OnReceiveRedirect(
fetcher_->OnReceivedRedirect(redirect_info);
}
-void AppCacheUpdateJob::UpdateURLLoaderRequest::OnDataDownloaded(
- int64_t data_len,
- int64_t encoded_data_len) {
- NOTIMPLEMENTED();
-}
-
void AppCacheUpdateJob::UpdateURLLoaderRequest::OnUploadProgress(
int64_t current_position,
int64_t total_size,
diff --git a/chromium/content/browser/appcache/appcache_update_url_loader_request.h b/chromium/content/browser/appcache/appcache_update_url_loader_request.h
index e7279f62572..d826fc30fa4 100644
--- a/chromium/content/browser/appcache/appcache_update_url_loader_request.h
+++ b/chromium/content/browser/appcache/appcache_update_url_loader_request.h
@@ -54,12 +54,10 @@ class AppCacheUpdateJob::UpdateURLLoaderRequest
// network::mojom::URLLoaderClient implementation.
// These methods are called by the network loader.
void OnReceiveResponse(
- const network::ResourceResponseHead& response_head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override;
+ const network::ResourceResponseHead& response_head) override;
void OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head) override;
- void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
diff --git a/chromium/content/browser/appcache/appcache_url_loader_job.cc b/chromium/content/browser/appcache/appcache_url_loader_job.cc
index b3969898ae2..1455c9f3f23 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_job.cc
+++ b/chromium/content/browser/appcache/appcache_url_loader_job.cc
@@ -106,6 +106,8 @@ base::WeakPtr<AppCacheURLLoaderJob> AppCacheURLLoaderJob::GetDerivedWeakPtr() {
}
void AppCacheURLLoaderJob::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
NOTREACHED() << "appcache never produces redirects";
}
@@ -287,8 +289,7 @@ void AppCacheURLLoaderJob::SendResponseInfo() {
response_head.ssl_info = http_info->ssl_info;
response_head.load_timing = load_timing_info_;
- client_->OnReceiveResponse(response_head,
- network::mojom::DownloadedTempFilePtr());
+ client_->OnReceiveResponse(response_head);
client_->OnStartLoadingResponseBody(std::move(data_pipe_.consumer_handle));
}
diff --git a/chromium/content/browser/appcache/appcache_url_loader_job.h b/chromium/content/browser/appcache/appcache_url_loader_job.h
index d116c91d890..1cc9ae22816 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_job.h
+++ b/chromium/content/browser/appcache/appcache_url_loader_job.h
@@ -55,7 +55,9 @@ class CONTENT_EXPORT AppCacheURLLoaderJob : public AppCacheJob,
base::WeakPtr<AppCacheURLLoaderJob> GetDerivedWeakPtr();
// network::mojom::URLLoader implementation:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
diff --git a/chromium/content/browser/appcache/appcache_url_loader_request.cc b/chromium/content/browser/appcache/appcache_url_loader_request.cc
index 68b55a93369..03e37c05688 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_request.cc
+++ b/chromium/content/browser/appcache/appcache_url_loader_request.cc
@@ -77,9 +77,10 @@ base::WeakPtr<AppCacheURLLoaderRequest> AppCacheURLLoaderRequest::GetWeakPtr() {
void AppCacheURLLoaderRequest::UpdateWithRedirectInfo(
const net::RedirectInfo& redirect_info) {
bool not_used_clear_body;
- net::RedirectUtil::UpdateHttpRequest(request_.url, request_.method,
- redirect_info, &request_.headers,
- &not_used_clear_body);
+ net::RedirectUtil::UpdateHttpRequest(
+ request_.url, request_.method, redirect_info,
+ base::nullopt /* modified_request_headers */, &request_.headers,
+ &not_used_clear_body);
request_.url = redirect_info.new_url;
request_.method = redirect_info.new_method;
request_.referrer = GURL(redirect_info.new_referrer);
diff --git a/chromium/content/browser/appcache/chrome_appcache_service.cc b/chromium/content/browser/appcache/chrome_appcache_service.cc
index 89ccb9a8250..5c95cb9ee21 100644
--- a/chromium/content/browser/appcache/chrome_appcache_service.cc
+++ b/chromium/content/browser/appcache/chrome_appcache_service.cc
@@ -45,8 +45,26 @@ void ChromeAppCacheService::InitializeOnIOThread(
void ChromeAppCacheService::Bind(
std::unique_ptr<mojom::AppCacheBackend> backend,
- mojom::AppCacheBackendRequest request) {
- bindings_.AddBinding(std::move(backend), std::move(request));
+ mojom::AppCacheBackendRequest request,
+ int process_id) {
+ DCHECK(process_bindings_.find(process_id) == process_bindings_.end());
+ process_bindings_[process_id] =
+ bindings_.AddBinding(std::move(backend), std::move(request));
+}
+
+void ChromeAppCacheService::Unbind(int process_id) {
+ auto it = process_bindings_.find(process_id);
+ if (it != process_bindings_.end()) {
+ bindings_.RemoveBinding(it->second);
+ DCHECK(process_bindings_.find(process_id) == process_bindings_.end());
+ }
+}
+
+void ChromeAppCacheService::UnregisterBackend(
+ AppCacheBackendImpl* backend_impl) {
+ int process_id = backend_impl->process_id();
+ process_bindings_.erase(process_bindings_.find(process_id));
+ AppCacheServiceImpl::UnregisterBackend(backend_impl);
}
void ChromeAppCacheService::Shutdown() {
diff --git a/chromium/content/browser/appcache/chrome_appcache_service.h b/chromium/content/browser/appcache/chrome_appcache_service.h
index 7845936ea43..316f2c4c83d 100644
--- a/chromium/content/browser/appcache/chrome_appcache_service.h
+++ b/chromium/content/browser/appcache/chrome_appcache_service.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner_helpers.h"
+#include "content/browser/appcache/appcache_backend_impl.h"
#include "content/browser/appcache/appcache_policy.h"
#include "content/browser/appcache/appcache_service_impl.h"
#include "content/common/appcache.mojom.h"
@@ -56,7 +57,14 @@ class CONTENT_EXPORT ChromeAppCacheService
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy);
void Bind(std::unique_ptr<mojom::AppCacheBackend> backend,
- mojom::AppCacheBackendRequest request);
+ mojom::AppCacheBackendRequest request,
+ int process_id);
+ // Unbinds the pipe corresponding to the given process_id. Unbinding
+ // unregisters and destroys the existing backend for that process_id.
+ // The function must be called before a new backend is created for the given
+ // process_id to ensure that there is at most one backend per process_id.
+ // The function does nothing if no pipe was bound.
+ void Unbind(int process_id);
void Shutdown();
@@ -66,6 +74,9 @@ class CONTENT_EXPORT ChromeAppCacheService
bool CanCreateAppCache(const GURL& manifest_url,
const GURL& first_party) override;
+ // AppCacheServiceImpl override
+ void UnregisterBackend(AppCacheBackendImpl* backend_impl) override;
+
protected:
~ChromeAppCacheService() override;
@@ -81,6 +92,9 @@ class CONTENT_EXPORT ChromeAppCacheService
base::FilePath cache_path_;
mojo::StrongBindingSet<mojom::AppCacheBackend> bindings_;
+ // A map from a process_id to a binding_id.
+ std::map<int, mojo::BindingId> process_bindings_;
+
DISALLOW_COPY_AND_ASSIGN(ChromeAppCacheService);
};
diff --git a/chromium/content/browser/background_fetch/background_fetch.proto b/chromium/content/browser/background_fetch/background_fetch.proto
index ec387edd7b8..c8708770309 100644
--- a/chromium/content/browser/background_fetch/background_fetch.proto
+++ b/chromium/content/browser/background_fetch/background_fetch.proto
@@ -28,31 +28,36 @@ message BackgroundFetchRegistration {
// Developer provided options.
// https://wicg.github.io/background-fetch/#background-fetch-manager
//
-// Next Tag: 4
+// Next Tag: 3
message BackgroundFetchOptions {
optional string title = 1;
- // https://w3c.github.io/manifest/#icons-member
- // Note that sizes can have multiple values (e.g. "32x32 64x64").
+ // https://w3c.github.io/manifest/#dom-imageresource
//
- // Next Tag: 4
- message IconDefinition {
+ // Next Tag: 5
+ message ImageResource {
optional string src = 1;
- optional string sizes = 2;
- optional string type = 3;
+
+ // Next Tag: 3
+ message Size {
+ optional int32 width = 1;
+ optional int32 height = 2;
+ }
+
+ repeated Size sizes = 2;
+ optional bytes type = 3;
+
+ // https://w3c.github.io/manifest/#purpose-member
+ enum Purpose {
+ ANY = 1;
+ BADGE = 2;
+ }
+
+ // blink::Manifest::ImageResource::Purpose enum.
+ repeated Purpose purpose = 4;
}
- // Example value:
- // icons: {
- // src: "icon/lowres.webp"
- // sizes: "48x48"
- // type: "image/webp"
- // }
- // icons: {
- // src: "icon/hd_hi.ico"
- // sizes: "72x72 96x96 128x128 256x256"
- // }
- repeated IconDefinition icons = 2;
+ repeated ImageResource icons = 2;
optional uint64 download_total = 3;
}
@@ -71,6 +76,10 @@ message BackgroundFetchMetadata {
// Number of fetches initiated by the developer.
optional int32 num_fetches = 5;
+
+ // Raw bytes needed to deserialize into a PNG icon. Only used if the icon
+ // has a max resolution of 256x256. This means this is at most ~256KB.
+ optional bytes icon = 6;
}
// A background fetch request that is still in a pending state.
@@ -103,4 +112,4 @@ message BackgroundFetchCompletedRequest {
optional string serialized_request = 3;
optional string download_guid = 4;
optional bool succeeded = 5;
-} \ No newline at end of file
+}
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.cc b/chromium/content/browser/background_fetch/background_fetch_context.cc
index 0ddea261409..38bdb10727d 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_context.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind_helpers.h"
+#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/background_fetch_job_controller.h"
#include "content/browser/background_fetch/background_fetch_metrics.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
@@ -22,21 +23,61 @@ namespace content {
BackgroundFetchContext::BackgroundFetchContext(
BrowserContext* browser_context,
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
+ const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
+ const scoped_refptr<content::CacheStorageContextImpl>&
+ cache_storage_context)
: browser_context_(browser_context),
- data_manager_(browser_context, service_worker_context),
+ service_worker_context_(service_worker_context),
event_dispatcher_(service_worker_context),
registration_notifier_(
std::make_unique<BackgroundFetchRegistrationNotifier>()),
delegate_proxy_(browser_context_->GetBackgroundFetchDelegate()),
- scheduler_(std::make_unique<BackgroundFetchScheduler>(&data_manager_)),
weak_factory_(this) {
// Although this lives only on the IO thread, it is constructed on UI thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(service_worker_context_);
+
+ data_manager_ = std::make_unique<BackgroundFetchDataManager>(
+ browser_context_, service_worker_context, cache_storage_context);
+ scheduler_ = std::make_unique<BackgroundFetchScheduler>(data_manager_.get());
+ delegate_proxy_.SetClickEventDispatcher(base::BindRepeating(
+ &BackgroundFetchContext::DispatchClickEvent, weak_factory_.GetWeakPtr()));
}
BackgroundFetchContext::~BackgroundFetchContext() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ service_worker_context_->RemoveObserver(this);
+ data_manager_->RemoveObserver(this);
+}
+
+void BackgroundFetchContext::InitializeOnIOThread() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ service_worker_context_->AddObserver(this);
+
+ data_manager_->AddObserver(this);
+ data_manager_->InitializeOnIOThread();
+ data_manager_->GetInitializationData(
+ base::BindOnce(&BackgroundFetchContext::DidGetInitializationData,
+ weak_factory_.GetWeakPtr()));
+}
+
+void BackgroundFetchContext::DidGetInitializationData(
+ blink::mojom::BackgroundFetchError error,
+ std::vector<background_fetch::BackgroundFetchInitializationData>
+ initialization_data) {
+ if (error != blink::mojom::BackgroundFetchError::NONE) {
+ // TODO(crbug.com/780025): Log failures to UMA.
+ return;
+ }
+
+ for (auto& data : initialization_data) {
+ CreateController(data.registration_id, data.options, data.icon,
+ data.ui_title, data.num_completed_requests,
+ data.num_requests, data.active_fetch_guids,
+ std::make_unique<BackgroundFetchRegistration>(
+ std::move(data.registration)));
+ }
}
void BackgroundFetchContext::GetRegistration(
@@ -46,7 +87,7 @@ void BackgroundFetchContext::GetRegistration(
blink::mojom::BackgroundFetchService::GetRegistrationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- data_manager_.GetRegistration(
+ data_manager_->GetRegistration(
service_worker_registration_id, origin, developer_id,
base::BindOnce(&BackgroundFetchContext::DidGetRegistration,
weak_factory_.GetWeakPtr(), std::move(callback)));
@@ -56,8 +97,8 @@ void BackgroundFetchContext::GetDeveloperIdsForServiceWorker(
int64_t service_worker_registration_id,
const url::Origin& origin,
blink::mojom::BackgroundFetchService::GetDeveloperIdsCallback callback) {
- data_manager_.GetDeveloperIdsForServiceWorker(service_worker_registration_id,
- origin, std::move(callback));
+ data_manager_->GetDeveloperIdsForServiceWorker(service_worker_registration_id,
+ origin, std::move(callback));
}
void BackgroundFetchContext::DidGetRegistration(
@@ -67,7 +108,8 @@ void BackgroundFetchContext::DidGetRegistration(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (error != blink::mojom::BackgroundFetchError::NONE) {
- std::move(callback).Run(error, base::nullopt);
+ std::move(callback).Run(error,
+ base::nullopt /* BackgroundFetchRegistration */);
return;
}
@@ -88,11 +130,18 @@ void BackgroundFetchContext::StartFetch(
blink::mojom::BackgroundFetchService::FetchCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- data_manager_.CreateRegistration(
+ // |registration_id| should be unique even if developer id has been
+ // duplicated, because the caller of this function generates a new unique_id
+ // every time, which is what BackgroundFetchRegistrationId's comparison
+ // operator uses.
+ DCHECK_EQ(0u, fetch_callbacks_.count(registration_id));
+ fetch_callbacks_[registration_id] = std::move(callback);
+
+ data_manager_->CreateRegistration(
registration_id, requests, options, icon,
base::BindOnce(&BackgroundFetchContext::DidCreateRegistration,
weak_factory_.GetWeakPtr(), registration_id, options, icon,
- requests.size(), std::move(callback)));
+ requests.size()));
}
void BackgroundFetchContext::GetIconDisplaySize(
@@ -107,33 +156,32 @@ void BackgroundFetchContext::DidCreateRegistration(
const BackgroundFetchOptions& options,
const SkBitmap& icon,
size_t num_requests,
- blink::mojom::BackgroundFetchService::FetchCallback callback,
blink::mojom::BackgroundFetchError error,
std::unique_ptr<BackgroundFetchRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
background_fetch::RecordRegistrationCreatedError(error);
if (error != blink::mojom::BackgroundFetchError::NONE) {
- std::move(callback).Run(error, base::nullopt);
+ DCHECK(fetch_callbacks_.count(registration_id));
+ std::move(fetch_callbacks_[registration_id])
+ .Run(error, base::nullopt /* BackgroundFetchRegistration */);
+ fetch_callbacks_.erase(registration_id);
return;
}
- DCHECK(registration);
+ if (hang_registration_creation_for_testing_) {
+ // Hang here, to allow time for testing races. For instance, this helps us
+ // test the behavior when a service worker gets unregistered before the
+ // controller can be created.
+ return;
+ }
- BackgroundFetchRegistration* registration_ptr = registration.get();
- // The closure takes ownership of |registration|, and it's guaranteed to
- // outlive CreateController, which uses the underlying pointer.
- base::OnceClosure done_closure = base::BindOnce(
- [](blink::mojom::BackgroundFetchService::FetchCallback callback,
- blink::mojom::BackgroundFetchError error,
- std::unique_ptr<BackgroundFetchRegistration> registration) {
- std::move(callback).Run(error, *registration);
- },
- std::move(callback), error, std::move(registration));
+ DCHECK(registration);
// Create the BackgroundFetchJobController to do the actual fetching.
- CreateController(registration_id, options, icon, num_requests,
- *registration_ptr, std::move(done_closure));
+ CreateController(registration_id, options, icon, options.title,
+ 0u /* num_completed_requests */, num_requests,
+ {} /* outstanding_guids */, std::move(registration));
}
void BackgroundFetchContext::AddRegistrationObserver(
@@ -155,43 +203,88 @@ void BackgroundFetchContext::UpdateUI(
return;
}
- data_manager_.UpdateRegistrationUI(
- registration_id, title,
- base::BindOnce(&BackgroundFetchContext::DidUpdateStoredUI,
- weak_factory_.GetWeakPtr(), registration_id.unique_id(),
- title, std::move(callback)));
+ data_manager_->UpdateRegistrationUI(registration_id, title,
+ std::move(callback));
}
-void BackgroundFetchContext::DidUpdateStoredUI(
- const std::string& unique_id,
- const std::string& title,
- blink::mojom::BackgroundFetchService::UpdateUICallback callback,
- blink::mojom::BackgroundFetchError error) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+void BackgroundFetchContext::OnServiceWorkerDatabaseCorrupted(
+ int64_t service_worker_registration_id) {
+ AbandonFetches(service_worker_registration_id);
+}
- // TODO(delphick): The controller might not exist if the developer updates the
- // UI from the event using event.waitUntil. Consider showing a message in the
- // console.
- if (error == blink::mojom::BackgroundFetchError::NONE &&
- job_controllers_.count(unique_id)) {
- job_controllers_[unique_id]->UpdateUI(title);
+void BackgroundFetchContext::AbandonFetches(
+ int64_t service_worker_registration_id) {
+ // Abandon all active fetches associated with this service worker.
+ // BackgroundFetchJobController::Abort() will eventually lead to deletion of
+ // the controller from job_controllers, hence we can't use a range based
+ // for-loop here.
+ for (auto iter = job_controllers_.begin(); iter != job_controllers_.end();
+ /* no_increment */) {
+ auto saved_iter = iter;
+ iter++;
+ if (service_worker_registration_id ==
+ blink::mojom::kInvalidServiceWorkerRegistrationId ||
+ saved_iter->second->registration_id()
+ .service_worker_registration_id() ==
+ service_worker_registration_id) {
+ DCHECK(saved_iter->second);
+ saved_iter->second->Abort(
+ BackgroundFetchReasonToAbort::SERVICE_WORKER_UNAVAILABLE);
+ }
}
- std::move(callback).Run(error);
+ for (auto iter = fetch_callbacks_.begin(); iter != fetch_callbacks_.end();
+ /* no increment */) {
+ if (service_worker_registration_id ==
+ blink::mojom::kInvalidServiceWorkerRegistrationId ||
+ iter->first.service_worker_registration_id() ==
+ service_worker_registration_id) {
+ DCHECK(iter->second);
+ std::move(iter->second)
+ .Run(blink::mojom::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE,
+ base::nullopt /* BackgroundFetchRegistration */);
+ iter = fetch_callbacks_.erase(iter);
+ } else
+ iter++;
+ }
+}
+
+void BackgroundFetchContext::OnUpdatedUI(
+ const BackgroundFetchRegistrationId& registration_id,
+ const std::string& title) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto iter = job_controllers_.find(registration_id.unique_id());
+ if (iter != job_controllers_.end())
+ iter->second->UpdateUI(title);
+}
+
+void BackgroundFetchContext::OnRegistrationDeleted(
+ int64_t service_worker_registration_id,
+ const GURL& pattern) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ AbandonFetches(service_worker_registration_id);
+}
+
+void BackgroundFetchContext::OnStorageWiped() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ AbandonFetches(blink::mojom::kInvalidServiceWorkerRegistrationId);
}
void BackgroundFetchContext::CreateController(
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ const std::string& ui_title,
+ size_t num_completed_requests,
size_t num_requests,
- const BackgroundFetchRegistration& registration,
- base::OnceClosure done_closure) {
+ const std::vector<std::string>& outstanding_guids,
+ std::unique_ptr<BackgroundFetchRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto controller = std::make_unique<BackgroundFetchJobController>(
- &delegate_proxy_, registration_id, options, icon, registration,
- scheduler_.get(),
+ &delegate_proxy_, registration_id, options, icon,
+ registration->downloaded, scheduler_.get(),
// Safe because JobControllers are destroyed before RegistrationNotifier.
base::BindRepeating(&BackgroundFetchRegistrationNotifier::Notify,
base::Unretained(registration_notifier_.get())),
@@ -199,27 +292,17 @@ void BackgroundFetchContext::CreateController(
&BackgroundFetchContext::DidFinishJob, weak_factory_.GetWeakPtr(),
base::Bind(&background_fetch::RecordSchedulerFinishedError)));
- data_manager_.GetNumCompletedRequests(
- registration_id,
- base::BindOnce(&BackgroundFetchContext::InitializeController,
- weak_factory_.GetWeakPtr(), registration_id.unique_id(),
- std::move(controller), std::move(done_closure),
- num_requests));
-}
-
-void BackgroundFetchContext::InitializeController(
- const std::string& unique_id,
- std::unique_ptr<BackgroundFetchJobController> controller,
- base::OnceClosure done_closure,
- size_t total_downloads,
- size_t completed_downloads) {
- controller->InitializeRequestStatus(completed_downloads, total_downloads,
- {} /* outstanding download GUIDs */);
-
+ controller->InitializeRequestStatus(num_completed_requests, num_requests,
+ outstanding_guids, ui_title);
scheduler_->AddJobController(controller.get());
+ job_controllers_.emplace(registration_id.unique_id(), std::move(controller));
- job_controllers_.insert({unique_id, std::move(controller)});
- std::move(done_closure).Run();
+ auto fetch_callback_iter = fetch_callbacks_.find(registration_id);
+ if (fetch_callback_iter != fetch_callbacks_.end()) {
+ std::move(fetch_callback_iter->second)
+ .Run(blink::mojom::BackgroundFetchError::NONE, *registration);
+ fetch_callbacks_.erase(fetch_callback_iter);
+ }
}
void BackgroundFetchContext::Abort(
@@ -239,7 +322,7 @@ void BackgroundFetchContext::DidFinishJob(
// If |aborted| is true, this will also propagate the event to any active
// JobController for the registration, to terminate in-progress requests.
- data_manager_.MarkRegistrationForDeletion(
+ data_manager_->MarkRegistrationForDeletion(
registration_id,
base::BindOnce(&BackgroundFetchContext::DidMarkForDeletion,
weak_factory_.GetWeakPtr(), registration_id,
@@ -251,6 +334,7 @@ void BackgroundFetchContext::DidMarkForDeletion(
BackgroundFetchReasonToAbort reason_to_abort,
base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback,
blink::mojom::BackgroundFetchError error) {
+ DCHECK(callback);
std::move(callback).Run(error);
// It's normal to get INVALID_ID errors here - it means the registration was
@@ -268,15 +352,17 @@ void BackgroundFetchContext::DidMarkForDeletion(
switch (reason_to_abort) {
case BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER:
case BackgroundFetchReasonToAbort::CANCELLED_FROM_UI:
- CleanupRegistration(registration_id, {});
+ CleanupRegistration(registration_id, {},
+ mojom::BackgroundFetchState::FAILED);
// TODO(rayankans): Send fetches to the event dispatcher.
event_dispatcher_.DispatchBackgroundFetchAbortEvent(
registration_id, {} /* settled_fetches */, base::DoNothing());
return;
case BackgroundFetchReasonToAbort::TOTAL_DOWNLOAD_SIZE_EXCEEDED:
+ case BackgroundFetchReasonToAbort::SERVICE_WORKER_UNAVAILABLE:
case BackgroundFetchReasonToAbort::NONE:
// This will send a BackgroundFetchFetched or BackgroundFetchFail event.
- data_manager_.GetSettledFetchesForRegistration(
+ data_manager_->GetSettledFetchesForRegistration(
registration_id,
base::BindOnce(&BackgroundFetchContext::DidGetSettledFetches,
weak_factory_.GetWeakPtr(), registration_id));
@@ -293,7 +379,9 @@ void BackgroundFetchContext::DidGetSettledFetches(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (error != blink::mojom::BackgroundFetchError::NONE) {
- CleanupRegistration(registration_id, {} /* fetches */);
+ CleanupRegistration(registration_id, {} /* fetches */,
+ mojom::BackgroundFetchState::FAILED,
+ true /* preserve_info_to_dispatch_click_event */);
return;
}
@@ -309,7 +397,9 @@ void BackgroundFetchContext::DidGetSettledFetches(
// The blob uuid is sent as part of |settled_fetches|. Bind
// |blob_data_handles| to the callback to keep them alive
// until the waitUntil event is resolved.
- std::move(blob_data_handles)));
+ std::move(blob_data_handles),
+ mojom::BackgroundFetchState::SUCCEEDED,
+ true /* preserve_info_to_dispatch_click_event */));
} else {
event_dispatcher_.DispatchBackgroundFetchFailEvent(
registration_id, std::move(settled_fetches),
@@ -319,19 +409,28 @@ void BackgroundFetchContext::DidGetSettledFetches(
// The blob uuid is sent as part of |settled_fetches|. Bind
// |blob_data_handles| to the callback to keep them alive
// until the waitUntil event is resolved.
- std::move(blob_data_handles)));
+ std::move(blob_data_handles), mojom::BackgroundFetchState::FAILED,
+ true /* preserve_info_to_dispatch_click_event */));
}
}
void BackgroundFetchContext::CleanupRegistration(
const BackgroundFetchRegistrationId& registration_id,
- const std::vector<std::unique_ptr<storage::BlobDataHandle>>& blob_handles) {
+ const std::vector<std::unique_ptr<storage::BlobDataHandle>>& blob_handles,
+ mojom::BackgroundFetchState background_fetch_state,
+ bool preserve_info_to_dispatch_click_event) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// If we had an active JobController, it is no longer necessary, as the
// notification's UI can no longer be updated after the fetch is aborted, or
// after the waitUntil promise of the backgroundfetched/backgroundfetchfail
- // event has been resolved.
+ // event has been resolved. Store the information we want to persist after
+ // the controller is gone, in completed_fetches_.
+ scheduler_->RemoveJobController(registration_id);
+ if (preserve_info_to_dispatch_click_event) {
+ completed_fetches_[registration_id.unique_id()] = {registration_id,
+ background_fetch_state};
+ }
job_controllers_.erase(registration_id.unique_id());
// At this point, JavaScript can no longer obtain BackgroundFetchRegistration
@@ -348,13 +447,54 @@ void BackgroundFetchContext::CleanupRegistration(
weak_factory_.GetWeakPtr(), registration_id));
}
+void BackgroundFetchContext::DispatchClickEvent(const std::string& unique_id) {
+ auto iter = completed_fetches_.find(unique_id);
+ if (iter != completed_fetches_.end()) {
+ // The fetch has succeeded or failed. (not aborted/cancelled).
+ event_dispatcher_.DispatchBackgroundFetchClickEvent(
+ iter->second.first /* registration_id */,
+ iter->second.second /* background_fetch_state */, base::DoNothing());
+ completed_fetches_.erase(iter);
+ return;
+ }
+
+ // The fetch is active, or has been aborted/cancelled.
+ auto controllers_iter = job_controllers_.find(unique_id);
+ if (controllers_iter == job_controllers_.end())
+ return;
+ event_dispatcher_.DispatchBackgroundFetchClickEvent(
+ controllers_iter->second->registration_id(),
+ mojom::BackgroundFetchState::PENDING, base::DoNothing());
+}
+
void BackgroundFetchContext::LastObserverGarbageCollected(
const BackgroundFetchRegistrationId& registration_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- data_manager_.DeleteRegistration(
+ data_manager_->DeleteRegistration(
registration_id,
base::BindOnce(&background_fetch::RecordRegistrationDeletedError));
}
+void BackgroundFetchContext::Shutdown() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&BackgroundFetchContext::ShutdownOnIO, this));
+}
+
+void BackgroundFetchContext::ShutdownOnIO() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ data_manager_->ShutdownOnIO();
+}
+
+void BackgroundFetchContext::SetDataManagerForTesting(
+ std::unique_ptr<BackgroundFetchDataManager> data_manager) {
+ DCHECK(data_manager);
+ data_manager_ = std::move(data_manager);
+ scheduler_ = std::make_unique<BackgroundFetchScheduler>(data_manager_.get());
+}
+
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.h b/chromium/content/browser/background_fetch/background_fetch_context.h
index fe0892dd021..a6b05e1267a 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.h
+++ b/chromium/content/browser/background_fetch/background_fetch_context.h
@@ -13,9 +13,11 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "content/browser/background_fetch/background_fetch_data_manager.h"
+#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
#include "content/browser/background_fetch/background_fetch_delegate_proxy.h"
#include "content/browser/background_fetch/background_fetch_event_dispatcher.h"
+#include "content/browser/background_fetch/storage/get_initialization_data_task.h"
+#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
@@ -27,11 +29,13 @@ class BlobDataHandle;
namespace content {
class BackgroundFetchJobController;
+class BackgroundFetchDataManager;
struct BackgroundFetchOptions;
class BackgroundFetchRegistrationId;
class BackgroundFetchRegistrationNotifier;
class BackgroundFetchScheduler;
class BrowserContext;
+class CacheStorageContextImpl;
class ServiceWorkerContextWrapper;
struct ServiceWorkerFetchRequest;
@@ -40,14 +44,23 @@ struct ServiceWorkerFetchRequest;
// Background Fetch requests function similarly to normal fetches except that
// they are persistent across Chromium or service worker shutdown.
class CONTENT_EXPORT BackgroundFetchContext
- : public base::RefCountedThreadSafe<BackgroundFetchContext,
+ : public BackgroundFetchDataManagerObserver,
+ public ServiceWorkerContextCoreObserver,
+ public base::RefCountedThreadSafe<BackgroundFetchContext,
BrowserThread::DeleteOnIOThread> {
public:
// The BackgroundFetchContext will watch the ServiceWorkerContextWrapper so
// that it can respond to service worker events such as unregister.
BackgroundFetchContext(
BrowserContext* browser_context,
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context);
+ const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
+ const scoped_refptr<content::CacheStorageContextImpl>&
+ cache_storage_context);
+
+ void InitializeOnIOThread();
+
+ // Called by the StoragePartitionImpl destructor.
+ void Shutdown();
// Gets the active Background Fetch registration identified by |developer_id|
// for the given |service_worker_id| and |origin|. The |callback| will be
@@ -100,30 +113,40 @@ class CONTENT_EXPORT BackgroundFetchContext
const std::string& title,
blink::mojom::BackgroundFetchService::UpdateUICallback callback);
+ // BackgroundFetchDataManagerObserver implementation.
+ void OnUpdatedUI(const BackgroundFetchRegistrationId& registration_id,
+ const std::string& title) override;
+ void OnServiceWorkerDatabaseCorrupted(
+ int64_t service_worker_registration_id) override;
+
+ // ServiceWorkerContextCoreObserver implementation.
+ void OnRegistrationDeleted(int64_t registration_id,
+ const GURL& pattern) override;
+ void OnStorageWiped() override;
+
private:
+ friend class BackgroundFetchServiceTest;
+ friend class BackgroundFetchJobControllerTest;
friend class base::DeleteHelper<BackgroundFetchContext>;
- friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
friend class base::RefCountedThreadSafe<BackgroundFetchContext,
BrowserThread::DeleteOnIOThread>;
+ friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
- ~BackgroundFetchContext();
+ ~BackgroundFetchContext() override;
+
+ void ShutdownOnIO();
// Creates a new Job Controller for the given |registration_id| and |options|,
// which will start fetching the files that are part of the registration.
- void CreateController(const BackgroundFetchRegistrationId& registration_id,
- const BackgroundFetchOptions& options,
- const SkBitmap& icon,
- size_t num_requests,
- const BackgroundFetchRegistration& registration,
- base::OnceClosure done_closure);
-
- // Initializes the new Job Controller.
- void InitializeController(
- const std::string& unique_id,
- std::unique_ptr<BackgroundFetchJobController> controller,
- base::OnceClosure done_closure,
- size_t total_downloads,
- size_t completed_downloads);
+ void CreateController(
+ const BackgroundFetchRegistrationId& registration_id,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
+ const std::string& ui_title,
+ size_t num_completed_requests,
+ size_t num_requests,
+ const std::vector<std::string>& outstanding_guids,
+ std::unique_ptr<BackgroundFetchRegistration> registration);
// Called when an existing registration has been retrieved from the data
// manager. If the registration does not exist then |registration| is nullptr.
@@ -138,17 +161,9 @@ class CONTENT_EXPORT BackgroundFetchContext
const BackgroundFetchOptions& options,
const SkBitmap& icon,
size_t num_requests,
- blink::mojom::BackgroundFetchService::FetchCallback callback,
blink::mojom::BackgroundFetchError error,
std::unique_ptr<BackgroundFetchRegistration> registration);
- // Called when the new title has been updated in the data manager.
- void DidUpdateStoredUI(
- const std::string& unique_id,
- const std::string& title,
- blink::mojom::BackgroundFetchService::UpdateUICallback callback,
- blink::mojom::BackgroundFetchError error);
-
// Called by a JobController when it finishes processing. Also used to
// implement |Abort|.
void DidFinishJob(
@@ -172,13 +187,29 @@ class CONTENT_EXPORT BackgroundFetchContext
std::vector<BackgroundFetchSettledFetch> settled_fetches,
std::vector<std::unique_ptr<storage::BlobDataHandle>> blob_data_handles);
+ // Called when the notification UI for the background fetch job associated
+ // with |unique_id| is activated.
+ void DispatchClickEvent(const std::string& unique_id);
+
+ // Called when the data manager finishes getting the initialization data.
+ void DidGetInitializationData(
+ blink::mojom::BackgroundFetchError error,
+ std::vector<background_fetch::BackgroundFetchInitializationData>
+ initialization_data);
+
// Called when all processing for the |registration_id| has been finished and
// the job is ready to be deleted. |blob_handles| are unused, but some callers
// use it to keep blobs alive for the right duration.
+ // |partial cleanup|, when set, preserves the registration ID, and the state
+ // of Fetch when it completed, in |completed_fetches_|. This is not done when
+ // fetch is aborted or cancelled. We use this information to propagate
+ // BackgroundFetchClicked event to the developer, when the user taps the UI.
void CleanupRegistration(
const BackgroundFetchRegistrationId& registration_id,
const std::vector<std::unique_ptr<storage::BlobDataHandle>>&
- blob_data_handles);
+ blob_data_handles,
+ mojom::BackgroundFetchState background_fetch_state,
+ bool preserve_info_to_dispatch_click_event = false);
// Called when the last JavaScript BackgroundFetchRegistration object has been
// garbage collected for a registration marked for deletion, and so it is now
@@ -186,10 +217,21 @@ class CONTENT_EXPORT BackgroundFetchContext
void LastObserverGarbageCollected(
const BackgroundFetchRegistrationId& registration_id);
+ // Switches out |data_manager_| with a DataManager configured for testing
+ // environments. Must be called directly after the constructor.
+ void SetDataManagerForTesting(
+ std::unique_ptr<BackgroundFetchDataManager> data_manager);
+
+ // Helper method to abandon ongoing fetches for a given service worker.
+ // Abandons all of them if |service_worker_registration_id| is set to
+ // blink::mojom::kInvalidServiceWorkerRegistrationId.
+ void AbandonFetches(int64_t service_worker_registration_id);
+
// |this| is owned, indirectly, by the BrowserContext.
BrowserContext* browser_context_;
- BackgroundFetchDataManager data_manager_;
+ std::unique_ptr<BackgroundFetchDataManager> data_manager_;
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
BackgroundFetchEventDispatcher event_dispatcher_;
std::unique_ptr<BackgroundFetchRegistrationNotifier> registration_notifier_;
BackgroundFetchDelegateProxy delegate_proxy_;
@@ -201,6 +243,28 @@ class CONTENT_EXPORT BackgroundFetchContext
std::map<std::string, std::unique_ptr<BackgroundFetchJobController>>
job_controllers_;
+ // Map from background fetch registration |unique_ids|s to {background fetch
+ // registration id, fetch state}. An entry in here means the fetch has
+ // completed. This information is needed after the fetch has completed.
+ // TODO(crbug.com/857122): Clean this up when the UI is no longer showing.
+ std::map<
+ std::string,
+ std::pair<BackgroundFetchRegistrationId, mojom::BackgroundFetchState>>
+ completed_fetches_;
+
+ // Map from BackgroundFetchRegistrationIds to FetchCallbacks for active
+ // fetches. Must be destroyed before |data_manager_| and
+ // |registration_notifier_|. Since FetchCallback is a OnceCallback, please
+ // erase the map entry once the calback has been invoked.
+ std::map<BackgroundFetchRegistrationId,
+ blink::mojom::BackgroundFetchService::FetchCallback>
+ fetch_callbacks_;
+
+ // This is used to hang the fetch logic for testing. For instance, this helps
+ // us test the behavior when a service worker gets unregistered before the
+ // controller has been created.
+ bool hang_registration_creation_for_testing_ = false;
+
base::WeakPtrFactory<BackgroundFetchContext> weak_factory_; // Must be last.
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchContext);
diff --git a/chromium/content/browser/background_fetch/background_fetch_data_manager.cc b/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
index a8cb4f6d5fc..c326cdc1da3 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -8,10 +8,9 @@
#include "base/command_line.h"
#include "base/containers/queue.h"
-#include "base/guid.h"
#include "base/time/time.h"
#include "content/browser/background_fetch/background_fetch_constants.h"
-#include "content/browser/background_fetch/background_fetch_cross_origin_filter.h"
+#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/background_fetch/storage/cleanup_task.h"
#include "content/browser/background_fetch/storage/create_metadata_task.h"
@@ -19,34 +18,22 @@
#include "content/browser/background_fetch/storage/delete_registration_task.h"
#include "content/browser/background_fetch/storage/get_developer_ids_task.h"
#include "content/browser/background_fetch/storage/get_metadata_task.h"
-#include "content/browser/background_fetch/storage/get_num_requests_task.h"
#include "content/browser/background_fetch/storage/get_settled_fetches_task.h"
#include "content/browser/background_fetch/storage/mark_registration_for_deletion_task.h"
#include "content/browser/background_fetch/storage/mark_request_complete_task.h"
#include "content/browser/background_fetch/storage/start_next_pending_request_task.h"
#include "content/browser/background_fetch/storage/update_registration_ui_task.h"
-#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "storage/browser/blob/blob_data_builder.h"
-#include "storage/browser/blob/blob_impl.h"
-#include "storage/browser/blob/blob_storage_context.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
namespace content {
namespace {
-// Returns whether the response contained in the Background Fetch |request| is
-// considered OK. See https://fetch.spec.whatwg.org/#ok-status aka a successful
-// 2xx status per https://tools.ietf.org/html/rfc7231#section-6.3.
-bool IsOK(const BackgroundFetchRequestInfo& request) {
- int status = request.GetResponseCode();
- return status >= 200 && status < 300;
-}
-
// Helper function to convert a BackgroundFetchRegistration proto into a
// BackgroundFetchRegistration struct, and call the appropriate callback.
void GetRegistrationFromMetadata(
@@ -73,106 +60,12 @@ void GetRegistrationFromMetadata(
} // namespace
-// The Registration Data class encapsulates the data stored for a particular
-// Background Fetch registration. This roughly matches the on-disk format that
-// will be adhered to in the future.
-class BackgroundFetchDataManager::RegistrationData {
- public:
- RegistrationData(const BackgroundFetchRegistrationId& registration_id,
- const std::vector<ServiceWorkerFetchRequest>& requests,
- const BackgroundFetchOptions& options,
- const SkBitmap& icon)
- : registration_id_(registration_id), options_(options), icon_(icon) {
- int request_index = 0;
-
- // Convert the given |requests| to BackgroundFetchRequestInfo objects.
- for (const ServiceWorkerFetchRequest& fetch_request : requests) {
- pending_requests_.push(base::MakeRefCounted<BackgroundFetchRequestInfo>(
- request_index++, fetch_request));
- }
- }
-
- ~RegistrationData() = default;
-
- // Returns whether there are remaining requests on the request queue.
- bool HasPendingRequests() const { return !pending_requests_.empty(); }
-
- // Consumes a request from the queue that is to be fetched.
- scoped_refptr<BackgroundFetchRequestInfo> PopNextPendingRequest() {
- DCHECK(!pending_requests_.empty());
-
- auto request = pending_requests_.front();
- pending_requests_.pop();
-
- request->InitializeDownloadGuid();
-
- // The |request| is considered to be active now.
- active_requests_.push_back(request);
-
- return request;
- }
-
- // Marks the |request| as having completed. Verifies that the |request| is
- // currently active and moves it to the |completed_requests_| vector.
- void MarkRequestAsComplete(BackgroundFetchRequestInfo* request) {
- const auto iter = std::find_if(
- active_requests_.begin(), active_requests_.end(),
- [&request](scoped_refptr<BackgroundFetchRequestInfo> active_request) {
- return active_request->request_index() == request->request_index();
- });
-
- // The |request| must have been consumed from this RegistrationData.
- DCHECK(iter != active_requests_.end());
-
- completed_requests_.push_back(*iter);
- active_requests_.erase(iter);
-
- complete_requests_downloaded_bytes_ += request->GetFileSize();
- }
-
- // Returns the vector with all completed requests part of this registration.
- const std::vector<scoped_refptr<BackgroundFetchRequestInfo>>&
- GetCompletedRequests() const {
- return completed_requests_;
- }
-
- void SetTitle(const std::string& title) { options_.title = title; }
-
- const BackgroundFetchRegistrationId& registration_id() const {
- return registration_id_;
- }
-
- const BackgroundFetchOptions& options() const { return options_; }
-
- uint64_t GetDownloaded() const { return complete_requests_downloaded_bytes_; }
-
- size_t GetNumCompletedRequests() const { return completed_requests_.size(); }
-
- private:
- BackgroundFetchRegistrationId registration_id_;
- BackgroundFetchOptions options_;
- SkBitmap icon_;
- // Number of bytes downloaded as part of completed downloads. (In-progress
- // downloads are tracked elsewhere).
- uint64_t complete_requests_downloaded_bytes_ = 0;
-
- base::queue<scoped_refptr<BackgroundFetchRequestInfo>> pending_requests_;
- std::vector<scoped_refptr<BackgroundFetchRequestInfo>> active_requests_;
-
- // TODO(peter): Right now it's safe for this to be a vector because we only
- // allow a single parallel request. That stops when we start allowing more.
- static_assert(kMaximumBackgroundFetchParallelRequests == 1,
- "RegistrationData::completed_requests_ assumes no parallelism");
-
- std::vector<scoped_refptr<BackgroundFetchRequestInfo>> completed_requests_;
-
- DISALLOW_COPY_AND_ASSIGN(RegistrationData);
-};
-
BackgroundFetchDataManager::BackgroundFetchDataManager(
BrowserContext* browser_context,
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ scoped_refptr<CacheStorageContextImpl> cache_storage_context)
: service_worker_context_(std::move(service_worker_context)),
+ cache_storage_context_(std::move(cache_storage_context)),
weak_ptr_factory_(this) {
// Constructed on the UI thread, then used on the IO thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -182,26 +75,48 @@ BackgroundFetchDataManager::BackgroundFetchDataManager(
blob_storage_context_ =
base::WrapRefCounted(ChromeBlobStorageContext::GetFor(browser_context));
DCHECK(blob_storage_context_);
+}
+
+void BackgroundFetchDataManager::InitializeOnIOThread() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // The CacheStorageManager can only be accessed from the IO thread.
+ cache_manager_ =
+ base::WrapRefCounted(cache_storage_context_->cache_manager());
+
+ // TODO(crbug.com/855199): Persist which registrations to cleanup on startup.
+ Cleanup();
+
+ DCHECK(cache_manager_);
+}
- BrowserThread::PostAfterStartupTask(
- FROM_HERE, BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- // Normally weak pointers must be obtained on the IO thread, but it's ok
- // here as the factory cannot be destroyed before the constructor ends.
- base::BindOnce(&BackgroundFetchDataManager::Cleanup,
- weak_ptr_factory_.GetWeakPtr()));
+void BackgroundFetchDataManager::AddObserver(
+ BackgroundFetchDataManagerObserver* observer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ observers_.AddObserver(observer);
+}
+
+void BackgroundFetchDataManager::RemoveObserver(
+ BackgroundFetchDataManagerObserver* observer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ observers_.RemoveObserver(observer);
}
void BackgroundFetchDataManager::Cleanup() {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- AddDatabaseTask(std::make_unique<background_fetch::CleanupTask>(this));
- }
+ AddDatabaseTask(std::make_unique<background_fetch::CleanupTask>(this));
}
BackgroundFetchDataManager::~BackgroundFetchDataManager() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
+void BackgroundFetchDataManager::GetInitializationData(
+ GetInitializationDataCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ AddDatabaseTask(std::make_unique<background_fetch::GetInitializationDataTask>(
+ this, std::move(callback)));
+}
+
void BackgroundFetchDataManager::CreateRegistration(
const BackgroundFetchRegistrationId& registration_id,
const std::vector<ServiceWorkerFetchRequest>& requests,
@@ -210,47 +125,11 @@ void BackgroundFetchDataManager::CreateRegistration(
GetRegistrationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- auto registration_callback =
- base::BindOnce(&GetRegistrationFromMetadata, std::move(callback));
- AddDatabaseTask(std::make_unique<background_fetch::CreateMetadataTask>(
- this, registration_id, requests, options,
- std::move(registration_callback)));
- return;
- }
-
- // New registrations should never re-use a |unique_id|.
- DCHECK_EQ(0u, registrations_.count(registration_id.unique_id()));
-
- auto developer_id_tuple =
- std::make_tuple(registration_id.service_worker_registration_id(),
- registration_id.origin(), registration_id.developer_id());
-
- if (active_registration_unique_ids_.count(developer_id_tuple)) {
- std::move(callback).Run(
- blink::mojom::BackgroundFetchError::DUPLICATED_DEVELOPER_ID, nullptr);
- return;
- }
-
- // Mark |unique_id| as the currently active registration for
- // |developer_id_tuple|.
- active_registration_unique_ids_.emplace(std::move(developer_id_tuple),
- registration_id.unique_id());
-
- // Create the |RegistrationData|, and store it for easy access.
- registrations_.emplace(registration_id.unique_id(),
- std::make_unique<RegistrationData>(
- registration_id, requests, options, icon));
-
- // Re-use GetRegistration to compile the BackgroundFetchRegistration object.
- // WARNING: GetRegistration doesn't use the |unique_id| when looking up the
- // registration data. That's fine here, since we are calling it synchronously
- // immediately after writing the |unique_id| to |active_unique_ids_|. But if
- // GetRegistation becomes async, it will no longer be safe to do this.
- GetRegistration(registration_id.service_worker_registration_id(),
- registration_id.origin(), registration_id.developer_id(),
- std::move(callback));
+ auto registration_callback =
+ base::BindOnce(&GetRegistrationFromMetadata, std::move(callback));
+ AddDatabaseTask(std::make_unique<background_fetch::CreateMetadataTask>(
+ this, registration_id, requests, options, icon,
+ std::move(registration_callback)));
}
void BackgroundFetchDataManager::GetMetadata(
@@ -259,10 +138,7 @@ void BackgroundFetchDataManager::GetMetadata(
const std::string& developer_id,
GetMetadataCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- return;
- }
+
AddDatabaseTask(std::make_unique<background_fetch::GetMetadataTask>(
this, service_worker_registration_id, origin, developer_id,
std::move(callback)));
@@ -275,42 +151,10 @@ void BackgroundFetchDataManager::GetRegistration(
GetRegistrationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- auto registration_callback =
- base::BindOnce(&GetRegistrationFromMetadata, std::move(callback));
- GetMetadata(service_worker_registration_id, origin, developer_id,
- std::move(registration_callback));
- return;
- }
-
- auto developer_id_tuple =
- std::make_tuple(service_worker_registration_id, origin, developer_id);
-
- auto iter = active_registration_unique_ids_.find(developer_id_tuple);
- if (iter == active_registration_unique_ids_.end()) {
- std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID,
- nullptr /* registration */);
- return;
- }
-
- const std::string& unique_id = iter->second;
-
- DCHECK_EQ(1u, registrations_.count(unique_id));
- RegistrationData* data = registrations_[unique_id].get();
-
- // Compile the BackgroundFetchRegistration object for the developer.
- auto registration = std::make_unique<BackgroundFetchRegistration>();
- registration->developer_id = developer_id;
- registration->unique_id = unique_id;
- // TODO(crbug.com/774054): Uploads are not yet supported.
- registration->upload_total = 0;
- registration->uploaded = 0;
- registration->download_total = data->options().download_total;
- registration->downloaded = data->GetDownloaded();
-
- std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE,
- std::move(registration));
+ auto registration_callback =
+ base::BindOnce(&GetRegistrationFromMetadata, std::move(callback));
+ GetMetadata(service_worker_registration_id, origin, developer_id,
+ std::move(registration_callback));
}
void BackgroundFetchDataManager::UpdateRegistrationUI(
@@ -319,24 +163,8 @@ void BackgroundFetchDataManager::UpdateRegistrationUI(
blink::mojom::BackgroundFetchService::UpdateUICallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- AddDatabaseTask(
- std::make_unique<background_fetch::UpdateRegistrationUITask>(
- this, registration_id, title, std::move(callback)));
- return;
- }
-
- auto registrations_iter = registrations_.find(registration_id.unique_id());
- if (registrations_iter == registrations_.end()) { // Not found.
- std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID);
- return;
- }
-
- // Update stored registration.
- registrations_iter->second->SetTitle(title);
-
- std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE);
+ AddDatabaseTask(std::make_unique<background_fetch::UpdateRegistrationUITask>(
+ this, registration_id, title, std::move(callback)));
}
void BackgroundFetchDataManager::PopNextRequest(
@@ -344,38 +172,15 @@ void BackgroundFetchDataManager::PopNextRequest(
NextRequestCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- auto start_next_request = base::BindOnce(
- &BackgroundFetchDataManager::AddStartNextPendingRequestTask,
- weak_ptr_factory_.GetWeakPtr(),
- registration_id.service_worker_registration_id(), std::move(callback));
-
- // Get the associated metadata, and add a StartNextPendingRequestTask.
- GetMetadata(registration_id.service_worker_registration_id(),
- registration_id.origin(), registration_id.developer_id(),
- std::move(start_next_request));
-
- return;
- }
-
- if (!IsActive(registration_id)) {
- // Stop giving out requests as registration was aborted (or otherwise
- // finished).
- std::move(callback).Run(nullptr /* request */);
- return;
- }
-
- auto registration_iter = registrations_.find(registration_id.unique_id());
- DCHECK(registration_iter != registrations_.end());
-
- RegistrationData* registration_data = registration_iter->second.get();
-
- scoped_refptr<BackgroundFetchRequestInfo> next_request;
- if (registration_data->HasPendingRequests())
- next_request = registration_data->PopNextPendingRequest();
+ auto start_next_request = base::BindOnce(
+ &BackgroundFetchDataManager::AddStartNextPendingRequestTask,
+ weak_ptr_factory_.GetWeakPtr(),
+ registration_id.service_worker_registration_id(), std::move(callback));
- std::move(callback).Run(std::move(next_request));
+ // Get the associated metadata, and add a StartNextPendingRequestTask.
+ GetMetadata(registration_id.service_worker_registration_id(),
+ registration_id.origin(), registration_id.developer_id(),
+ std::move(start_next_request));
}
void BackgroundFetchDataManager::AddStartNextPendingRequestTask(
@@ -402,20 +207,8 @@ void BackgroundFetchDataManager::MarkRequestAsComplete(
BackgroundFetchScheduler::MarkedCompleteCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- AddDatabaseTask(std::make_unique<background_fetch::MarkRequestCompleteTask>(
- this, registration_id, request, std::move(callback)));
- return;
- }
-
- auto iter = registrations_.find(registration_id.unique_id());
- DCHECK(iter != registrations_.end());
-
- RegistrationData* registration_data = iter->second.get();
- registration_data->MarkRequestAsComplete(request);
-
- std::move(callback).Run();
+ AddDatabaseTask(std::make_unique<background_fetch::MarkRequestCompleteTask>(
+ this, registration_id, request, std::move(callback)));
}
void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
@@ -423,103 +216,8 @@ void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
SettledFetchesCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- AddDatabaseTask(std::make_unique<background_fetch::GetSettledFetchesTask>(
- this, registration_id, std::move(callback)));
- return;
- }
-
- auto iter = registrations_.find(registration_id.unique_id());
- DCHECK(iter != registrations_.end());
-
- RegistrationData* registration_data = iter->second.get();
- DCHECK(!registration_data->HasPendingRequests());
-
- const std::vector<scoped_refptr<BackgroundFetchRequestInfo>>& requests =
- registration_data->GetCompletedRequests();
-
- bool background_fetch_succeeded = true;
-
- std::vector<BackgroundFetchSettledFetch> settled_fetches;
- settled_fetches.reserve(requests.size());
-
- std::vector<std::unique_ptr<storage::BlobDataHandle>> blob_data_handles;
-
- for (const auto& request : requests) {
- BackgroundFetchSettledFetch settled_fetch;
- settled_fetch.request = request->fetch_request();
-
- // The |filter| decides which values can be passed on to the Service Worker.
- BackgroundFetchCrossOriginFilter filter(registration_id.origin(), *request);
-
- background_fetch_succeeded =
- FillServiceWorkerResponse(*request, registration_id.origin(),
- &settled_fetch.response) &&
- background_fetch_succeeded;
-
- settled_fetches.push_back(settled_fetch);
- }
-
- std::move(callback).Run(
- blink::mojom::BackgroundFetchError::NONE, background_fetch_succeeded,
- std::move(settled_fetches), std::move(blob_data_handles));
-}
-
-bool BackgroundFetchDataManager::FillServiceWorkerResponse(
- const BackgroundFetchRequestInfo& request,
- const url::Origin& origin,
- ServiceWorkerResponse* response) {
- DCHECK(response);
-
- response->url_list = request.GetURLChain();
- response->response_type = network::mojom::FetchResponseType::kDefault;
- // TODO(crbug.com/838837): settled_fetch.response.error
- response->response_time = request.GetResponseTime();
- // TODO(crbug.com/838837): settled_fetch.response.cors_exposed_header_names
-
- BackgroundFetchCrossOriginFilter filter(origin, request);
- if (!filter.CanPopulateBody()) {
- // TODO(crbug.com/711354): Consider Background Fetches as failed when the
- // response cannot be relayed to the developer.
- return false;
- }
-
- // Include the status code, status text and the response's body as a blob
- // when this is allowed by the CORS protocol.
- response->status_code = request.GetResponseCode();
- response->status_text = request.GetResponseText();
- response->headers.insert(request.GetResponseHeaders().begin(),
- request.GetResponseHeaders().end());
-
- if (request.GetFileSize() > 0) {
- DCHECK(!request.GetFilePath().empty());
- DCHECK(blob_storage_context_);
-
- auto blob_builder =
- std::make_unique<storage::BlobDataBuilder>(base::GenerateGUID());
- blob_builder->AppendFile(request.GetFilePath(), 0 /* offset */,
- request.GetFileSize(),
- base::Time() /* expected_modification_time */);
-
- auto blob_data_handle = GetBlobStorageContext(blob_storage_context_.get())
- ->AddFinishedBlob(std::move(blob_builder));
-
- // TODO(peter): Appropriately handle !blob_data_handle
- if (blob_data_handle) {
- response->blob_uuid = blob_data_handle->uuid();
- response->blob_size = blob_data_handle->size();
- blink::mojom::BlobPtr blob_ptr;
- storage::BlobImpl::Create(
- std::make_unique<storage::BlobDataHandle>(*blob_data_handle),
- MakeRequest(&blob_ptr));
-
- response->blob =
- base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
- }
- }
-
- return IsOK(request);
+ AddDatabaseTask(std::make_unique<background_fetch::GetSettledFetchesTask>(
+ this, registration_id, std::move(callback)));
}
void BackgroundFetchDataManager::MarkRegistrationForDeletion(
@@ -527,33 +225,9 @@ void BackgroundFetchDataManager::MarkRegistrationForDeletion(
HandleBackgroundFetchErrorCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- AddDatabaseTask(
- std::make_unique<background_fetch::MarkRegistrationForDeletionTask>(
- this, registration_id, std::move(callback)));
- return;
- }
-
- auto developer_id_tuple =
- std::make_tuple(registration_id.service_worker_registration_id(),
- registration_id.origin(), registration_id.developer_id());
-
- auto active_unique_id_iter =
- active_registration_unique_ids_.find(developer_id_tuple);
-
- // The |unique_id| must also match, as a website can create multiple
- // registrations with the same |developer_id_tuple| (even though only one can
- // be active at once).
- if (active_unique_id_iter == active_registration_unique_ids_.end() ||
- active_unique_id_iter->second != registration_id.unique_id()) {
- std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID);
- return;
- }
-
- active_registration_unique_ids_.erase(active_unique_id_iter);
-
- std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE);
+ AddDatabaseTask(
+ std::make_unique<background_fetch::MarkRegistrationForDeletionTask>(
+ this, registration_id, std::move(callback)));
}
void BackgroundFetchDataManager::DeleteRegistration(
@@ -561,20 +235,10 @@ void BackgroundFetchDataManager::DeleteRegistration(
HandleBackgroundFetchErrorCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- AddDatabaseTask(std::make_unique<background_fetch::DeleteRegistrationTask>(
- this, registration_id.service_worker_registration_id(),
- registration_id.unique_id(), std::move(callback)));
- return;
- }
-
- DCHECK(!IsActive(registration_id))
- << "MarkRegistrationForDeletion must already have been called";
-
- std::move(callback).Run(registrations_.erase(registration_id.unique_id())
- ? blink::mojom::BackgroundFetchError::NONE
- : blink::mojom::BackgroundFetchError::INVALID_ID);
+ AddDatabaseTask(std::make_unique<background_fetch::DeleteRegistrationTask>(
+ this, registration_id.service_worker_registration_id(),
+ registration_id.origin(), registration_id.unique_id(),
+ std::move(callback)));
}
void BackgroundFetchDataManager::GetDeveloperIdsForServiceWorker(
@@ -583,66 +247,32 @@ void BackgroundFetchDataManager::GetDeveloperIdsForServiceWorker(
blink::mojom::BackgroundFetchService::GetDeveloperIdsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- AddDatabaseTask(std::make_unique<background_fetch::GetDeveloperIdsTask>(
- this, service_worker_registration_id, origin, std::move(callback)));
- return;
- }
-
- std::vector<std::string> developer_ids;
- for (const auto& entry : active_registration_unique_ids_) {
- if (service_worker_registration_id == std::get<0>(entry.first) &&
- origin == std::get<1>(entry.first)) {
- developer_ids.emplace_back(std::get<2>(entry.first));
- }
- }
-
- std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE,
- developer_ids);
+ AddDatabaseTask(std::make_unique<background_fetch::GetDeveloperIdsTask>(
+ this, service_worker_registration_id, origin, std::move(callback)));
}
-void BackgroundFetchDataManager::GetNumCompletedRequests(
- const BackgroundFetchRegistrationId& registration_id,
- NumRequestsCallback callback) {
+void BackgroundFetchDataManager::ShutdownOnIO() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableBackgroundFetchPersistence)) {
- AddDatabaseTask(std::make_unique<background_fetch::GetNumRequestsTask>(
- this, registration_id, background_fetch::RequestType::kCompleted,
- std::move(callback)));
- return;
- }
+ // Release reference to CacheStorageManager. DatabaseTasks that need it
+ // hold their own copy, so they can continue their work.
+ cache_manager_ = nullptr;
- std::move(callback).Run(registrations_.find(registration_id.unique_id())
- ->second->GetNumCompletedRequests());
-}
-
-bool BackgroundFetchDataManager::IsActive(
- const BackgroundFetchRegistrationId& registration_id) {
- auto developer_id_tuple =
- std::make_tuple(registration_id.service_worker_registration_id(),
- registration_id.origin(), registration_id.developer_id());
-
- auto active_unique_id_iter =
- active_registration_unique_ids_.find(developer_id_tuple);
-
- // The |unique_id| must also match, as a website can create multiple
- // registrations with the same |developer_id_tuple| (even though only one can
- // be active at once).
- return active_unique_id_iter != active_registration_unique_ids_.end() &&
- active_unique_id_iter->second == registration_id.unique_id();
+ shutting_down_ = true;
}
void BackgroundFetchDataManager::AddDatabaseTask(
std::unique_ptr<background_fetch::DatabaseTask> task) {
+ // If Shutdown was called don't add any new tasks.
+ if (shutting_down_)
+ return;
+
database_tasks_.push(std::move(task));
if (database_tasks_.size() == 1)
database_tasks_.front()->Start();
}
-void BackgroundFetchDataManager::OnDatabaseTaskFinished(
+void BackgroundFetchDataManager::OnTaskFinished(
background_fetch::DatabaseTask* task) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -654,4 +284,8 @@ void BackgroundFetchDataManager::OnDatabaseTaskFinished(
database_tasks_.front()->Start();
}
+BackgroundFetchDataManager* BackgroundFetchDataManager::data_manager() {
+ return this;
+}
+
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_data_manager.h b/chromium/content/browser/background_fetch/background_fetch_data_manager.h
index 6b70bbf5715..56119296c98 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager.h
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager.h
@@ -16,10 +16,14 @@
#include "base/containers/queue.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/observer_list.h"
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/background_fetch_scheduler.h"
#include "content/browser/background_fetch/storage/database_task.h"
+#include "content/browser/background_fetch/storage/get_initialization_data_task.h"
+#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
#include "url/origin.h"
@@ -30,9 +34,11 @@ class BlobDataHandle;
namespace content {
+class BackgroundFetchDataManagerObserver;
class BackgroundFetchRequestInfo;
struct BackgroundFetchSettledFetch;
class BrowserContext;
+class CacheStorageManager;
class ChromeBlobStorageContext;
class ServiceWorkerContextWrapper;
@@ -48,8 +54,12 @@ class ServiceWorkerContextWrapper;
//
// Storage schema is documented in storage/README.md
class CONTENT_EXPORT BackgroundFetchDataManager
- : public BackgroundFetchScheduler::RequestProvider {
+ : public BackgroundFetchScheduler::RequestProvider,
+ public background_fetch::DatabaseTaskHost {
public:
+ using GetInitializationDataCallback = base::OnceCallback<void(
+ blink::mojom::BackgroundFetchError,
+ std::vector<background_fetch::BackgroundFetchInitializationData>)>;
using SettledFetchesCallback = base::OnceCallback<void(
blink::mojom::BackgroundFetchError,
bool /* background_fetch_succeeded */,
@@ -67,10 +77,23 @@ class CONTENT_EXPORT BackgroundFetchDataManager
BackgroundFetchDataManager(
BrowserContext* browser_context,
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ scoped_refptr<CacheStorageContextImpl> cache_storage_context);
~BackgroundFetchDataManager() override;
+ // Grabs a reference to CacheStorageManager.
+ virtual void InitializeOnIOThread();
+
+ // Adds or removes the given |observer| to this data manager instance.
+ void AddObserver(BackgroundFetchDataManagerObserver* observer);
+ void RemoveObserver(BackgroundFetchDataManagerObserver* observer);
+
+ // Gets the required data to initialize BackgroundFetchContext with the
+ // appropriate JobControllers. This will be called when BackgroundFetchContext
+ // is being intialized on the IO thread.
+ void GetInitializationData(GetInitializationDataCallback callback);
+
// Creates and stores a new registration with the given properties. Will
// invoke the |callback| when the registration has been created, which may
// fail due to invalid input or storage errors.
@@ -134,11 +157,9 @@ class CONTENT_EXPORT BackgroundFetchDataManager
const url::Origin& origin,
blink::mojom::BackgroundFetchService::GetDeveloperIdsCallback callback);
- // Gets the number of fetch requests that have been completed for a given
- // registration.
- void GetNumCompletedRequests(
- const BackgroundFetchRegistrationId& registration_id,
- NumRequestsCallback callback);
+ const base::ObserverList<BackgroundFetchDataManagerObserver>& observers() {
+ return observers_;
+ }
// BackgroundFetchScheduler::RequestProvider implementation:
void PopNextRequest(const BackgroundFetchRegistrationId& registration_id,
@@ -149,18 +170,27 @@ class CONTENT_EXPORT BackgroundFetchDataManager
BackgroundFetchRequestInfo* request,
BackgroundFetchScheduler::MarkedCompleteCallback callback) override;
- // TODO(rayankans): Move this function to MarkRequestCompleteTask after
- // non-persistent background fetch support is removed.
- bool FillServiceWorkerResponse(const BackgroundFetchRequestInfo& request,
- const url::Origin& origin,
- ServiceWorkerResponse* response);
+ void ShutdownOnIO();
private:
FRIEND_TEST_ALL_PREFIXES(BackgroundFetchDataManagerTest, Cleanup);
friend class BackgroundFetchDataManagerTest;
+ friend class BackgroundFetchTestDataManager;
friend class background_fetch::DatabaseTask;
- class RegistrationData;
+ // Accessors for tests and DatabaseTasks.
+ ServiceWorkerContextWrapper* service_worker_context() const {
+ return service_worker_context_.get();
+ }
+ scoped_refptr<CacheStorageManager> cache_manager() const {
+ return cache_manager_;
+ }
+ std::set<std::string>& ref_counted_unique_ids() {
+ return ref_counted_unique_ids_;
+ }
+ ChromeBlobStorageContext* blob_storage_context() const {
+ return blob_storage_context_.get();
+ }
void AddStartNextPendingRequestTask(
int64_t service_worker_registration_id,
@@ -170,33 +200,32 @@ class CONTENT_EXPORT BackgroundFetchDataManager
void AddDatabaseTask(std::unique_ptr<background_fetch::DatabaseTask> task);
- void OnDatabaseTaskFinished(background_fetch::DatabaseTask* task);
-
- // Returns true if not aborted/completed/failed.
- bool IsActive(const BackgroundFetchRegistrationId& registration_id);
+ // DatabaseTaskHost implementation.
+ void OnTaskFinished(background_fetch::DatabaseTask* task) override;
+ BackgroundFetchDataManager* data_manager() override;
void Cleanup();
+ // Whether Shutdown was called on BackgroundFetchContext.
+ bool shutting_down_ = false;
+
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
- // The blob storage request with which response information will be stored.
- scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
+ scoped_refptr<CacheStorageContextImpl> cache_storage_context_;
- // Map from {service_worker_registration_id, origin, developer_id} tuples to
- // the |unique_id|s of active background fetch registrations (not
- // completed/failed/aborted, so there will never be more than one entry for a
- // given key).
- std::map<std::tuple<int64_t, url::Origin, std::string>, std::string>
- active_registration_unique_ids_;
+ // The BackgroundFetch stores its own reference to CacheStorageManager
+ // in case StoragePartitionImpl is destoyed, which releases the reference.
+ scoped_refptr<CacheStorageManager> cache_manager_;
- // Map from the |unique_id|s of known (but possibly inactive) background fetch
- // registrations to their associated data.
- std::map<std::string, std::unique_ptr<RegistrationData>> registrations_;
+ // The blob storage request with which response information will be stored.
+ scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
// Pending database operations, serialized to ensure consistency.
// Invariant: the frontmost task, if any, has already been started.
base::queue<std::unique_ptr<background_fetch::DatabaseTask>> database_tasks_;
+ base::ObserverList<BackgroundFetchDataManagerObserver> observers_;
+
// The |unique_id|s of registrations that have been deactivated since the
// browser was last started. They will be automatically deleted when the
// refcount of JavaScript objects that refers to them goes to zero, unless
diff --git a/chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h b/chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h
new file mode 100644
index 00000000000..12981a841ba
--- /dev/null
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h
@@ -0,0 +1,31 @@
+// Copyright 2018 The Chromium Authors. All 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_FETCH_BACKGROUND_FETCH_DATA_MANAGER_OBSERVER_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DATA_MANAGER_OBSERVER_H_
+
+namespace content {
+
+class BackgroundFetchRegistrationId;
+
+// Observer interface for objects that would like to be notified about changes
+// committed to storage through the Background Fetch data manager. All methods
+// will be invoked on the IO thread.
+class BackgroundFetchDataManagerObserver {
+ public:
+ // Called when the |title| for the Background Fetch |registration_id| has been
+ // updated in the data store.
+ virtual void OnUpdatedUI(const BackgroundFetchRegistrationId& registration_id,
+ const std::string& title) = 0;
+
+ // Called if corrupted data is found in the Service Worker database.
+ virtual void OnServiceWorkerDatabaseCorrupted(
+ int64_t service_worker_registration_id) = 0;
+
+ virtual ~BackgroundFetchDataManagerObserver() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DATA_MANAGER_OBSERVER_H_
diff --git a/chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
index 8a1cd9a985e..acd1d25f874 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
@@ -15,25 +15,29 @@
#include "base/command_line.h"
#include "base/guid.h"
#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/background_fetch/background_fetch_test_base.h"
+#include "content/browser/background_fetch/background_fetch_test_data_manager.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
-#include "content/browser/background_fetch/storage/get_num_requests_task.h"
+#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/background_fetch_response.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/common/content_switches.h"
+#include "content/public/browser/storage_partition.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
namespace content {
namespace {
+using background_fetch::BackgroundFetchInitializationData;
using ::testing::UnorderedElementsAre;
using ::testing::IsEmpty;
-enum class BackgroundFetchRegistrationStorage { kPersistent, kNonPersistent };
-
const char kUserDataPrefix[] = "bgfetch_";
const char kExampleDeveloperId[] = "my-example-id";
@@ -44,6 +48,18 @@ const char kAlternativeUniqueId[] = "bb48a9fb-c21f-4c2d-a9ae-58bd48a9fb53";
const char kInitialTitle[] = "Initial Title";
const char kUpdatedTitle[] = "Updated Title";
+constexpr size_t kResponseFileSize = 42u;
+
+void DidGetInitializationData(
+ base::Closure quit_closure,
+ std::vector<BackgroundFetchInitializationData>* out_result,
+ blink::mojom::BackgroundFetchError error,
+ std::vector<BackgroundFetchInitializationData> result) {
+ DCHECK_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ *out_result = std::move(result);
+ std::move(quit_closure).Run();
+}
+
void DidCreateRegistration(
base::Closure quit_closure,
blink::mojom::BackgroundFetchError* out_error,
@@ -60,31 +76,48 @@ void DidGetError(base::Closure quit_closure,
std::move(quit_closure).Run();
}
-void DidGetRegistrationUserDataByKeyPrefix(base::Closure quit_closure,
- std::vector<std::string>* out_data,
- const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+void DidGetRegistrationUserDataByKeyPrefix(
+ base::OnceClosure quit_closure,
+ std::vector<std::string>* out_data,
+ const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status) {
DCHECK(out_data);
- DCHECK_EQ(SERVICE_WORKER_OK, status);
+ DCHECK_EQ(blink::ServiceWorkerStatusCode::kOk, status);
*out_data = data;
std::move(quit_closure).Run();
}
void AnnotateRequestInfoWithFakeDownloadManagerData(
- BackgroundFetchRequestInfo* request_info) {
- // Fill |request_info| with a failed result.
+ BackgroundFetchRequestInfo* request_info,
+ bool success = false) {
+ DCHECK(request_info);
+
+ std::string headers =
+ success ? "HTTP/1.1 200 OK\n" : "HTTP/1.1 404 Not found\n";
+ request_info->PopulateWithResponse(std::make_unique<BackgroundFetchResponse>(
+ std::vector<GURL>(1u, request_info->fetch_request().url),
+ base::MakeRefCounted<net::HttpResponseHeaders>(headers)));
+
+ if (!success) {
+ // Fill |request_info| with a failed result.
+ request_info->SetResult(std::make_unique<BackgroundFetchResult>(
+ base::Time::Now(), BackgroundFetchResult::FailureReason::UNKNOWN));
+ return;
+ }
+
+ // This is treated as an empty response, but the size is set to
+ // |kResponseFileSize| for tests that use filesize.
request_info->SetResult(std::make_unique<BackgroundFetchResult>(
- base::Time::Now(), BackgroundFetchResult::FailureReason::UNKNOWN));
- request_info->PopulateWithResponse(
- std::make_unique<BackgroundFetchResponse>(std::vector<GURL>(1), nullptr));
+ base::Time::Now(), base::FilePath(), base::nullopt /* blob_handle */,
+ kResponseFileSize));
}
void GetNumUserData(base::Closure quit_closure,
int* out_size,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK(out_size);
- DCHECK_EQ(SERVICE_WORKER_OK, status);
+ DCHECK_EQ(blink::ServiceWorkerStatusCode::kOk, status);
*out_size = data.size();
std::move(quit_closure).Run();
}
@@ -101,38 +134,57 @@ bool operator==(const ResponseStateStats& s1, const ResponseStateStats& s2) {
s1.completed_requests == s2.completed_requests;
}
+std::vector<ServiceWorkerFetchRequest> CreateValidRequests(
+ const url::Origin& origin,
+ size_t num_requests = 1u) {
+ std::vector<ServiceWorkerFetchRequest> requests(num_requests);
+ for (size_t i = 0; i < requests.size(); i++) {
+ // Creates a URL of the form: `http://example.com/x`
+ requests[i].url = GURL(origin.GetURL().spec() + base::NumberToString(i));
+ }
+ return requests;
+}
+
} // namespace
class BackgroundFetchDataManagerTest
: public BackgroundFetchTestBase,
- public ::testing::WithParamInterface<BackgroundFetchRegistrationStorage> {
+ public BackgroundFetchDataManagerObserver {
public:
BackgroundFetchDataManagerTest() {
- registration_storage_ = GetParam();
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kPersistent) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableBackgroundFetchPersistence);
- }
RestartDataManagerFromPersistentStorage();
}
- ~BackgroundFetchDataManagerTest() override = default;
+ ~BackgroundFetchDataManagerTest() override {
+ background_fetch_data_manager_->RemoveObserver(this);
+ }
// Re-creates the data manager. Useful for testing that data was persisted.
- // If the test is non-persistent mode (e.g. testing the old code path), then
- // this does nothing after the first call.
void RestartDataManagerFromPersistentStorage() {
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kNonPersistent &&
- background_fetch_data_manager_) {
- return;
- }
-
background_fetch_data_manager_ =
- std::make_unique<BackgroundFetchDataManager>(
- browser_context(),
- embedded_worker_test_helper()->context_wrapper());
+ std::make_unique<BackgroundFetchTestDataManager>(
+ browser_context(), storage_partition(),
+ embedded_worker_test_helper()->context_wrapper(),
+ true /* mock_fill_response */);
+
+ background_fetch_data_manager_->AddObserver(this);
+ background_fetch_data_manager_->InitializeOnIOThread();
+ }
+
+ // Synchronous version of BackgroundFetchDataManager::GetInitializationData().
+ std::vector<BackgroundFetchInitializationData> GetInitializationData() {
+ // Simulate browser restart. This re-initializes |data_manager_|, since
+ // this DatabaseTask should only be called on browser startup.
+ RestartDataManagerFromPersistentStorage();
+
+ std::vector<BackgroundFetchInitializationData> result;
+
+ base::RunLoop run_loop;
+ background_fetch_data_manager_->GetInitializationData(base::BindOnce(
+ &DidGetInitializationData, run_loop.QuitClosure(), &result));
+ run_loop.Run();
+
+ return result;
}
// Synchronous version of BackgroundFetchDataManager::CreateRegistration().
@@ -140,12 +192,13 @@ class BackgroundFetchDataManagerTest
const BackgroundFetchRegistrationId& registration_id,
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
blink::mojom::BackgroundFetchError* out_error) {
DCHECK(out_error);
base::RunLoop run_loop;
background_fetch_data_manager_->CreateRegistration(
- registration_id, requests, options, SkBitmap(),
+ registration_id, requests, options, icon,
base::BindOnce(&DidCreateRegistration, run_loop.QuitClosure(),
out_error));
run_loop.Run();
@@ -299,38 +352,6 @@ class BackgroundFetchDataManagerTest
}
// Synchronous version of
- // BackgroundFetchDataManager::GetNumCompletedRequests().
- void GetNumCompletedRequests(
- const BackgroundFetchRegistrationId& registration_id,
- size_t* out_size) {
- DCHECK(out_size);
-
- base::RunLoop run_loop;
- background_fetch_data_manager_->GetNumCompletedRequests(
- registration_id,
- base::BindOnce(&BackgroundFetchDataManagerTest::DidGetNumRequests,
- base::Unretained(this), run_loop.QuitClosure(),
- out_size));
- run_loop.Run();
- }
-
- // Synchronous version of GetNumRequestsTask::Start().
- void GetNumRequestsTask(const BackgroundFetchRegistrationId& registration_id,
- background_fetch::RequestType type,
- size_t* out_size) {
- DCHECK(out_size);
-
- base::RunLoop run_loop;
- background_fetch_data_manager_->AddDatabaseTask(
- std::make_unique<background_fetch::GetNumRequestsTask>(
- background_fetch_data_manager_.get(), registration_id, type,
- base::BindOnce(&BackgroundFetchDataManagerTest::DidGetNumRequests,
- base::Unretained(this), run_loop.QuitClosure(),
- out_size)));
- run_loop.Run();
- }
-
- // Synchronous version of
// ServiceWorkerContextWrapper::GetRegistrationUserDataByKeyPrefix.
std::vector<std::string> GetRegistrationUserDataByKeyPrefix(
int64_t service_worker_registration_id,
@@ -349,6 +370,38 @@ class BackgroundFetchDataManagerTest
return data;
}
+ // Synchronous version of CacheStorageManager::HasCache().
+ bool HasCache(const std::string& cache_name) {
+ bool result = false;
+
+ base::RunLoop run_loop;
+ background_fetch_data_manager_->cache_manager()->HasCache(
+ origin(), CacheStorageOwner::kBackgroundFetch, cache_name,
+ base::BindOnce(&BackgroundFetchDataManagerTest::DidFindCache,
+ base::Unretained(this), run_loop.QuitClosure(),
+ &result));
+ run_loop.Run();
+
+ return result;
+ }
+
+ // Synchronous version of CacheStorageManager::MatchCache().
+ bool MatchCache(const ServiceWorkerFetchRequest& request) {
+ bool result = false;
+ auto request_ptr = std::make_unique<ServiceWorkerFetchRequest>(request);
+
+ base::RunLoop run_loop;
+ background_fetch_data_manager_->cache_manager()->MatchCache(
+ origin(), CacheStorageOwner::kBackgroundFetch, kExampleUniqueId,
+ std::move(request_ptr), nullptr /* match_params */,
+ base::BindOnce(&BackgroundFetchDataManagerTest::DidMatchCache,
+ base::Unretained(this), run_loop.QuitClosure(),
+ &result));
+ run_loop.Run();
+
+ return result;
+ }
+
// Gets information about the number of background fetch requests by state.
ResponseStateStats GetRequestStats(int64_t service_worker_registration_id) {
ResponseStateStats stats;
@@ -388,6 +441,13 @@ class BackgroundFetchDataManagerTest
return stats;
}
+ // BackgroundFetchDataManagerObserver mocks:
+ MOCK_METHOD2(OnUpdatedUI,
+ void(const BackgroundFetchRegistrationId& registration,
+ const std::string& title));
+ MOCK_METHOD1(OnServiceWorkerDatabaseCorrupted,
+ void(int64_t service_worker_registration_id));
+
protected:
void DidGetRegistration(
base::Closure quit_closure,
@@ -465,28 +525,33 @@ class BackgroundFetchDataManagerTest
std::move(quit_closure).Run();
}
- void DidGetNumRequests(base::OnceClosure quit_closure,
- size_t* out_size,
- size_t size) {
- *out_size = size;
+ void DidFindCache(base::OnceClosure quit_closure,
+ bool* out_result,
+ bool has_cache,
+ blink::mojom::CacheStorageError error) {
+ DCHECK_EQ(error, blink::mojom::CacheStorageError::kSuccess);
+ *out_result = has_cache;
std::move(quit_closure).Run();
}
- BackgroundFetchRegistrationStorage registration_storage_;
- std::unique_ptr<BackgroundFetchDataManager> background_fetch_data_manager_;
-};
-
-INSTANTIATE_TEST_CASE_P(
- Persistent,
- BackgroundFetchDataManagerTest,
- ::testing::Values(BackgroundFetchRegistrationStorage::kPersistent));
+ void DidMatchCache(base::OnceClosure quit_closure,
+ bool* out_result,
+ blink::mojom::CacheStorageError error,
+ std::unique_ptr<ServiceWorkerResponse> response) {
+ if (error == blink::mojom::CacheStorageError::kSuccess) {
+ DCHECK(response);
+ *out_result = true;
+ } else {
+ *out_result = false;
+ }
+ std::move(quit_closure).Run();
+ }
-INSTANTIATE_TEST_CASE_P(
- NonPersistent,
- BackgroundFetchDataManagerTest,
- ::testing::Values(BackgroundFetchRegistrationStorage::kNonPersistent));
+ std::unique_ptr<BackgroundFetchTestDataManager>
+ background_fetch_data_manager_;
+};
-TEST_P(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
+TEST_F(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
// Tests that the BackgroundFetchDataManager correctly rejects creating a
// registration with a |developer_id| for which there is already an active
// registration.
@@ -509,7 +574,7 @@ TEST_P(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID);
// Creating the initial registration should succeed.
- CreateRegistration(registration_id1, requests, options, &error);
+ CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// Different |unique_id|, since this is a new Background Fetch registration,
@@ -520,7 +585,7 @@ TEST_P(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
// Attempting to create a second registration with the same |developer_id| and
// |service_worker_registration_id| should yield an error.
- CreateRegistration(registration_id2, requests, options, &error);
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::DUPLICATED_DEVELOPER_ID);
// Deactivating the second registration that failed to be created should fail.
@@ -534,11 +599,11 @@ TEST_P(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
// And now registering the second registration should work fine, since there
// is no longer an *active* registration with the same |developer_id|, even
// though the initial registration has not yet been deleted.
- CreateRegistration(registration_id2, requests, options, &error);
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
-TEST_P(BackgroundFetchDataManagerTest, GetDeveloperIds) {
+TEST_F(BackgroundFetchDataManagerTest, GetDeveloperIds) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
@@ -554,7 +619,7 @@ TEST_P(BackgroundFetchDataManagerTest, GetDeveloperIds) {
// Create a single registration.
BackgroundFetchRegistrationId registration_id1(
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
- CreateRegistration(registration_id1, requests, options, &error);
+ CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// Verify that the developer ID can be found.
@@ -572,7 +637,7 @@ TEST_P(BackgroundFetchDataManagerTest, GetDeveloperIds) {
// Create another registration.
BackgroundFetchRegistrationId registration_id2(
sw_id, origin(), kAlternativeDeveloperId, kAlternativeUniqueId);
- CreateRegistration(registration_id2, requests, options, &error);
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// Verify that both developer IDs can be found.
@@ -589,7 +654,7 @@ TEST_P(BackgroundFetchDataManagerTest, GetDeveloperIds) {
kAlternativeDeveloperId));
}
-TEST_P(BackgroundFetchDataManagerTest, GetRegistration) {
+TEST_F(BackgroundFetchDataManagerTest, GetRegistration) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
@@ -601,7 +666,7 @@ TEST_P(BackgroundFetchDataManagerTest, GetRegistration) {
blink::mojom::BackgroundFetchError error;
// Create a single registration.
- CreateRegistration(registration_id, requests, options, &error);
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// Verify that the registration can be retrieved.
@@ -628,12 +693,7 @@ TEST_P(BackgroundFetchDataManagerTest, GetRegistration) {
EXPECT_EQ(kExampleDeveloperId, registration->developer_id);
}
-TEST_P(BackgroundFetchDataManagerTest, GetMetadata) {
- // This test only applies to persistent storage.
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kNonPersistent)
- return;
-
+TEST_F(BackgroundFetchDataManagerTest, GetMetadata) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
@@ -645,7 +705,7 @@ TEST_P(BackgroundFetchDataManagerTest, GetMetadata) {
blink::mojom::BackgroundFetchError error;
// Create a single registration.
- CreateRegistration(registration_id, requests, options, &error);
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// Verify that the metadata can be retrieved.
@@ -672,12 +732,36 @@ TEST_P(BackgroundFetchDataManagerTest, GetMetadata) {
EXPECT_EQ(metadata->num_fetches(), static_cast<int>(requests.size()));
}
-TEST_P(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
- // This test only applies to persistent storage.
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kNonPersistent)
- return;
+TEST_F(BackgroundFetchDataManagerTest, LargeIconNotPersisted) {
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+
+ std::vector<ServiceWorkerFetchRequest> requests(2u);
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+
+ SkBitmap icon;
+ icon.allocN32Pixels(512, 512);
+ icon.eraseColor(SK_ColorGREEN);
+
+ // Create a single registration.
+ CreateRegistration(registration_id, requests, options, icon, &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ // Verify that the metadata can be retrieved.
+ auto metadata = GetMetadata(sw_id, origin(), kExampleDeveloperId, &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ ASSERT_TRUE(metadata);
+ EXPECT_EQ(metadata->origin(), origin().Serialize());
+ EXPECT_NE(metadata->creation_microseconds_since_unix_epoch(), 0);
+ EXPECT_EQ(metadata->num_fetches(), static_cast<int>(requests.size()));
+ EXPECT_TRUE(metadata->icon().empty());
+}
+
+TEST_F(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
@@ -695,7 +779,7 @@ TEST_P(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
EXPECT_TRUE(title.empty());
// Create a single registration.
- CreateRegistration(registration_id, requests, options, &error);
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// Verify that the title can be retrieved.
@@ -705,7 +789,12 @@ TEST_P(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
ASSERT_EQ(title.front(), kInitialTitle);
// Update the title.
- UpdateRegistrationUI(registration_id, kUpdatedTitle, &error);
+ {
+ EXPECT_CALL(*this, OnUpdatedUI(registration_id, kUpdatedTitle));
+
+ UpdateRegistrationUI(registration_id, kUpdatedTitle, &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
RestartDataManagerFromPersistentStorage();
@@ -716,7 +805,7 @@ TEST_P(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
ASSERT_EQ(title.front(), kUpdatedTitle);
}
-TEST_P(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
+TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
@@ -727,7 +816,7 @@ TEST_P(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
- CreateRegistration(registration_id1, requests, options, &error);
+ CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
RestartDataManagerFromPersistentStorage();
@@ -740,7 +829,7 @@ TEST_P(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
// Attempting to create a second registration with the same |developer_id| and
// |service_worker_registration_id| should yield an error, even after
// restarting.
- CreateRegistration(registration_id2, requests, options, &error);
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::DUPLICATED_DEVELOPER_ID);
// Verify that the registration can be retrieved before deletion.
@@ -772,7 +861,7 @@ TEST_P(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
// restarting, since there is no longer an *active* registration with the same
// |developer_id|, even though the initial registration has not yet been
// deleted.
- CreateRegistration(registration_id2, requests, options, &error);
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
RestartDataManagerFromPersistentStorage();
@@ -782,12 +871,7 @@ TEST_P(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
-TEST_P(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
- // This test only applies to persistent storage.
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kNonPersistent)
- return;
-
+TEST_F(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
@@ -809,7 +893,7 @@ TEST_P(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
- CreateRegistration(registration_id, requests, options, &error);
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_EQ(
GetRequestStats(sw_id),
@@ -862,12 +946,132 @@ TEST_P(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
2 /* completed_requests */}));
}
-TEST_P(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
- // This test only applies to persistent storage.
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kNonPersistent)
- return;
+TEST_F(BackgroundFetchDataManagerTest, DownloadTotalUpdated) {
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+ auto requests = CreateValidRequests(origin(), 3u /* num_requests */);
+
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ auto registration =
+ GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_EQ(registration->download_total, 0u);
+
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ PopNextRequest(registration_id, &request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
+ true /* succeeded */);
+ MarkRequestAsComplete(registration_id, request_info.get());
+
+ registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_EQ(registration->download_total, kResponseFileSize);
+
+ PopNextRequest(registration_id, &request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
+ true /* succeeded */);
+ MarkRequestAsComplete(registration_id, request_info.get());
+
+ registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_EQ(registration->download_total, 2 * kResponseFileSize);
+ PopNextRequest(registration_id, &request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
+ false /* succeeded */);
+ MarkRequestAsComplete(registration_id, request_info.get());
+
+ registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ // |download_total| is unchanged.
+ EXPECT_EQ(registration->download_total, 2 * kResponseFileSize);
+}
+
+TEST_F(BackgroundFetchDataManagerTest, WriteToCache) {
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+ auto requests = CreateValidRequests(origin(), 2u /* num_requests */);
+
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
+ true /* success */);
+ MarkRequestAsComplete(registration_id, request_info.get());
+
+ EXPECT_TRUE(HasCache(kExampleUniqueId));
+ EXPECT_FALSE(HasCache("foo"));
+
+ EXPECT_TRUE(MatchCache(requests[0]));
+ EXPECT_FALSE(MatchCache(requests[1]));
+
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
+ true /* success */);
+ MarkRequestAsComplete(registration_id, request_info.get());
+ EXPECT_TRUE(MatchCache(requests[0]));
+ EXPECT_TRUE(MatchCache(requests[1]));
+
+ RestartDataManagerFromPersistentStorage();
+ EXPECT_TRUE(MatchCache(requests[0]));
+ EXPECT_TRUE(MatchCache(requests[1]));
+}
+
+TEST_F(BackgroundFetchDataManagerTest, CacheDeleted) {
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+
+ ServiceWorkerFetchRequest request;
+ request.url = GURL(origin().GetURL().spec());
+
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+
+ CreateRegistration(registration_id, {request}, options, SkBitmap(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
+ true /* success */);
+ MarkRequestAsComplete(registration_id, request_info.get());
+
+ EXPECT_TRUE(HasCache(kExampleUniqueId));
+ EXPECT_TRUE(MatchCache(request));
+
+ MarkRegistrationForDeletion(registration_id, &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ DeleteRegistration(registration_id, &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ EXPECT_FALSE(HasCache(kExampleUniqueId));
+}
+
+TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
@@ -877,7 +1081,7 @@ TEST_P(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
BackgroundFetchRegistrationId registration_id(
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
- CreateRegistration(registration_id, requests, options, &error);
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_EQ(
GetRequestStats(sw_id),
@@ -917,126 +1121,73 @@ TEST_P(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
EXPECT_EQ(settled_fetches.size(), requests.size());
}
-TEST_P(BackgroundFetchDataManagerTest, GetNumCompletedRequests) {
+TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesFromCache) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
BackgroundFetchRegistrationId registration_id(
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+ auto requests = CreateValidRequests(origin(), 2u /* num_requests */);
- // The requests are default-initialized, but valid.
- std::vector<ServiceWorkerFetchRequest> requests(2u);
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- CreateRegistration(registration_id, requests, options, &error);
-
- size_t num_completed = 0u;
-
- GetNumCompletedRequests(registration_id, &num_completed);
- EXPECT_EQ(num_completed, 0u);
+ bool succeeded = false;
+ std::vector<BackgroundFetchSettledFetch> settled_fetches;
+ // Nothing is downloaded yet.
+ GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
+ &settled_fetches);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_TRUE(succeeded);
+ EXPECT_EQ(settled_fetches.size(), 0u);
scoped_refptr<BackgroundFetchRequestInfo> request_info;
- // Download and store first request.
PopNextRequest(registration_id, &request_info);
ASSERT_TRUE(request_info);
- AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
+ true /* success */);
MarkRequestAsComplete(registration_id, request_info.get());
- GetNumCompletedRequests(registration_id, &num_completed);
- EXPECT_EQ(num_completed, 1u);
-
- RestartDataManagerFromPersistentStorage();
-
- GetNumCompletedRequests(registration_id, &num_completed);
- EXPECT_EQ(num_completed, 1u);
+ GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
+ &settled_fetches);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_TRUE(succeeded);
+ EXPECT_EQ(settled_fetches.size(), 1u);
- // Download and store second request.
PopNextRequest(registration_id, &request_info);
ASSERT_TRUE(request_info);
- AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
+ true /* success */);
MarkRequestAsComplete(registration_id, request_info.get());
- GetNumCompletedRequests(registration_id, &num_completed);
- EXPECT_EQ(num_completed, 2u);
-}
-
-TEST_P(BackgroundFetchDataManagerTest, GetNumRequestsTask) {
- // This test only applies to persistent storage.
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kNonPersistent)
- return;
-
- int64_t sw_id = RegisterServiceWorker();
- ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
-
- BackgroundFetchRegistrationId registration_id(
- sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
- BackgroundFetchOptions options;
- blink::mojom::BackgroundFetchError error;
-
- CreateRegistration(registration_id, {ServiceWorkerFetchRequest()}, options,
- &error);
-
- size_t size = 0u;
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kAny,
- &size);
- EXPECT_EQ(size, 1u); // Total requests is 1.
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kPending,
- &size);
- EXPECT_EQ(size, 1u); // Total pending requests is 1.
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kActive,
- &size);
- EXPECT_EQ(size, 0u); // No active requests.
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kCompleted,
- &size);
- EXPECT_EQ(size, 0u); // No complete requests.
-
- scoped_refptr<BackgroundFetchRequestInfo> request_info;
- // Download and store first request.
- PopNextRequest(registration_id, &request_info);
- ASSERT_TRUE(request_info);
-
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kAny,
- &size);
- EXPECT_EQ(size, 1u); // Total requests is 1.
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kPending,
- &size);
- EXPECT_EQ(size, 0u); // Pending requests moved to active.
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kActive,
- &size);
- EXPECT_EQ(size, 1u); // Request is active.
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kCompleted,
- &size);
- EXPECT_EQ(size, 0u); // No complete requests.
-
- AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
- MarkRequestAsComplete(registration_id, request_info.get());
+ GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
+ &settled_fetches);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_TRUE(succeeded);
+ ASSERT_EQ(settled_fetches.size(), 2u);
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kActive,
- &size);
- EXPECT_EQ(size, 0u); // No active requests.
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kCompleted,
- &size);
- EXPECT_EQ(size, 1u); // Request is complete.
+ // Sanity check that the responses are written to / read from the cache.
+ EXPECT_TRUE(MatchCache(requests[0]));
+ EXPECT_TRUE(MatchCache(requests[1]));
+ EXPECT_EQ(settled_fetches[0].response.cache_storage_cache_name,
+ kExampleUniqueId);
+ EXPECT_EQ(settled_fetches[1].response.cache_storage_cache_name,
+ kExampleUniqueId);
RestartDataManagerFromPersistentStorage();
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kCompleted,
- &size);
- EXPECT_EQ(size, 1u);
- GetNumRequestsTask(registration_id, background_fetch::RequestType::kAny,
- &size);
- EXPECT_EQ(size, 1u); // Total requests is still 1.
+ GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
+ &settled_fetches);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_TRUE(succeeded);
+ EXPECT_EQ(settled_fetches.size(), 2u);
}
-TEST_P(BackgroundFetchDataManagerTest, Cleanup) {
+TEST_F(BackgroundFetchDataManagerTest, Cleanup) {
// Tests that the BackgroundFetchDataManager cleans up registrations
// marked for deletion.
-
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableBackgroundFetchPersistence);
-
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
@@ -1048,24 +1199,17 @@ TEST_P(BackgroundFetchDataManagerTest, Cleanup) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kPersistent) {
- EXPECT_EQ(
- 0u, GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
- }
-
+ EXPECT_EQ(0u,
+ GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
// Create a registration.
- CreateRegistration(registration_id, requests, options, &error);
+ CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kPersistent) {
- // We expect as many pending entries as there are requests.
- EXPECT_EQ(requests.size(),
- GetRegistrationUserDataByKeyPrefix(
- sw_id, background_fetch::kPendingRequestKeyPrefix)
- .size());
- }
+ // We expect as many pending entries as there are requests.
+ EXPECT_EQ(requests.size(),
+ GetRegistrationUserDataByKeyPrefix(
+ sw_id, background_fetch::kPendingRequestKeyPrefix)
+ .size());
// And deactivate it.
MarkRegistrationForDeletion(registration_id, &error);
@@ -1073,45 +1217,119 @@ TEST_P(BackgroundFetchDataManagerTest, Cleanup) {
RestartDataManagerFromPersistentStorage();
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kPersistent) {
- // Pending Requests should be deleted after marking a registration for
- // deletion.
- EXPECT_EQ(0u, GetRegistrationUserDataByKeyPrefix(
- sw_id, background_fetch::kPendingRequestKeyPrefix)
- .size());
- EXPECT_EQ(
- 2u, // Metadata proto + title.
- GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
- }
+ // Pending Requests should be deleted after marking a registration for
+ // deletion.
+ EXPECT_EQ(0u, GetRegistrationUserDataByKeyPrefix(
+ sw_id, background_fetch::kPendingRequestKeyPrefix)
+ .size());
+ EXPECT_EQ(2u, // Metadata proto + title.
+ GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
// Cleanup should delete the registration.
background_fetch_data_manager_->Cleanup();
- base::RunLoop().RunUntilIdle();
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kPersistent) {
- EXPECT_EQ(
- 0u, GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
- }
+ thread_bundle_.RunUntilIdle();
+ EXPECT_EQ(0u,
+ GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
RestartDataManagerFromPersistentStorage();
// The deletion should have been persisted.
- if (registration_storage_ ==
- BackgroundFetchRegistrationStorage::kPersistent) {
- EXPECT_EQ(
- 0u, GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
+ EXPECT_EQ(0u,
+ GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
+}
+
+TEST_F(BackgroundFetchDataManagerTest, GetInitializationData) {
+ {
+ // No registered ServiceWorkers.
+ std::vector<BackgroundFetchInitializationData> data =
+ GetInitializationData();
+ EXPECT_TRUE(data.empty());
+ }
+
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+ {
+ // Register ServiceWorker with no Background Fetch Registrations.
+ std::vector<BackgroundFetchInitializationData> data =
+ GetInitializationData();
+ EXPECT_TRUE(data.empty());
+ }
+
+ std::vector<ServiceWorkerFetchRequest> requests(2u);
+ BackgroundFetchOptions options;
+ options.title = kInitialTitle;
+ options.download_total = 42u;
+ blink::mojom::BackgroundFetchError error;
+ // Register a Background Fetch.
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+ SkBitmap icon;
+ icon.allocN32Pixels(42, 42);
+ icon.eraseColor(SK_ColorGREEN);
+ CreateRegistration(registration_id, requests, options, icon, &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ UpdateRegistrationUI(registration_id, kUpdatedTitle, &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ std::vector<BackgroundFetchInitializationData> data =
+ GetInitializationData();
+ ASSERT_EQ(data.size(), 1u);
+ const BackgroundFetchInitializationData& init = data[0];
+
+ EXPECT_EQ(init.registration_id, registration_id);
+ EXPECT_EQ(init.registration.unique_id, kExampleUniqueId);
+ EXPECT_EQ(init.registration.developer_id, kExampleDeveloperId);
+ EXPECT_EQ(init.options.title, kInitialTitle);
+ EXPECT_EQ(init.options.download_total, 42u);
+ EXPECT_EQ(init.ui_title, kUpdatedTitle);
+ EXPECT_EQ(init.num_requests, requests.size());
+ EXPECT_EQ(init.num_completed_requests, 0u);
+ EXPECT_TRUE(init.active_fetch_guids.empty());
+
+ // Check icon.
+ ASSERT_FALSE(init.icon.drawsNothing());
+ EXPECT_EQ(icon.width(), init.icon.width());
+ EXPECT_EQ(icon.height(), init.icon.height());
+ for (int i = 0; i < icon.width(); i++) {
+ for (int j = 0; j < icon.height(); j++)
+ EXPECT_EQ(init.icon.getColor(i, j), SK_ColorGREEN);
+ }
+ }
+
+ // Mark one request as complete and start another.
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get());
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+ {
+ std::vector<BackgroundFetchInitializationData> data =
+ GetInitializationData();
+ ASSERT_EQ(data.size(), 1u);
+
+ EXPECT_EQ(data[0].num_requests, requests.size());
+ EXPECT_EQ(data[0].num_completed_requests, 1u);
+ EXPECT_EQ(data[0].active_fetch_guids.size(), 1u);
+ }
+
+ // Create another registration.
+ BackgroundFetchRegistrationId registration_id2(
+ sw_id, origin(), kAlternativeDeveloperId, kAlternativeUniqueId);
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ {
+ std::vector<BackgroundFetchInitializationData> data =
+ GetInitializationData();
+ ASSERT_EQ(data.size(), 2u);
}
}
-TEST_P(BackgroundFetchDataManagerTest, CreateInParallel) {
+TEST_F(BackgroundFetchDataManagerTest, CreateInParallel) {
// Tests that multiple parallel calls to the BackgroundFetchDataManager are
// linearized and handled one at a time, rather than producing inconsistent
// results due to interleaving.
-
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableBackgroundFetchPersistence);
-
int64_t service_worker_registration_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
service_worker_registration_id);
diff --git a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
index 99679a6d0f1..90f63f92b31 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
@@ -143,6 +143,13 @@ class BackgroundFetchDelegateProxy::Core
delegate_->Abort(job_unique_id);
}
+ void UpdateUI(const std::string& job_unique_id, const std::string& title) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (delegate_)
+ delegate_->UpdateUI(job_unique_id, title);
+ }
+
// BackgroundFetchDelegate::Client implementation:
void OnJobCancelled(const std::string& job_unique_id,
BackgroundFetchReasonToAbort reason_to_abort) override;
@@ -157,6 +164,7 @@ class BackgroundFetchDelegateProxy::Core
const std::string& job_unique_id,
const std::string& guid,
std::unique_ptr<content::BackgroundFetchResponse> response) override;
+ void OnUIActivated(const std::string& unique_id) override;
void OnDelegateShutdown() override;
private:
@@ -216,6 +224,16 @@ void BackgroundFetchDelegateProxy::Core::OnDownloadStarted(
job_unique_id, guid, std::move(response)));
}
+void BackgroundFetchDelegateProxy::Core::OnUIActivated(
+ const std::string& job_unique_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&BackgroundFetchDelegateProxy::DidActivateUI, io_parent_,
+ job_unique_id));
+}
+
void BackgroundFetchDelegateProxy::Core::OnDelegateShutdown() {
delegate_ = nullptr;
}
@@ -248,6 +266,11 @@ BackgroundFetchDelegateProxy::~BackgroundFetchDelegateProxy() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
+void BackgroundFetchDelegateProxy::SetClickEventDispatcher(
+ const DispatchClickEventCallback callback) {
+ click_event_dispatcher_callback_ = std::move(callback);
+}
+
void BackgroundFetchDelegateProxy::GetIconDisplaySize(
BackgroundFetchDelegate::GetIconDisplaySizeCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -294,7 +317,9 @@ void BackgroundFetchDelegateProxy::UpdateUI(const std::string& job_unique_id,
const std::string& title) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // TODO(delphick): Update the user interface with |title|.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&Core::UpdateUI, ui_core_ptr_, job_unique_id, title));
}
void BackgroundFetchDelegateProxy::Abort(const std::string& job_unique_id) {
@@ -350,6 +375,12 @@ void BackgroundFetchDelegateProxy::DidStartRequest(
job_details.controller->DidStartRequest(request_info);
}
+void BackgroundFetchDelegateProxy::DidActivateUI(
+ const std::string& job_unique_id) {
+ DCHECK(click_event_dispatcher_callback_);
+ click_event_dispatcher_callback_.Run(job_unique_id);
+}
+
void BackgroundFetchDelegateProxy::OnDownloadUpdated(
const std::string& job_unique_id,
const std::string& guid,
diff --git a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
index 744278a5d18..1084985b3be 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
@@ -28,6 +28,8 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
public:
// Subclasses must only be destroyed on the IO thread, since these methods
// will be called on the IO thread.
+ using DispatchClickEventCallback =
+ base::RepeatingCallback<void(const std::string& /* unique_id */)>;
class Controller {
public:
// Called when the given |request| has started fetching.
@@ -54,6 +56,11 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
~BackgroundFetchDelegateProxy();
+ // Set BackgroundFetchClick event dispatcher callback, which is a method on
+ // the background fetch context.
+ void SetClickEventDispatcher(
+ const DispatchClickEventCallback click_event_callback);
+
// Gets size of the icon to display with the Background Fetch UI.
void GetIconDisplaySize(
BackgroundFetchDelegate::GetIconDisplaySizeCallback callback);
@@ -113,6 +120,9 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
const std::string& guid,
std::unique_ptr<BackgroundFetchResponse> response);
+ // Should only be called from the BackgroundFetchDelegate (on the IO thread).
+ void DidActivateUI(const std::string& job_unique_id);
+
std::unique_ptr<Core, BrowserThread::DeleteOnUIThread> ui_core_;
base::WeakPtr<Core> ui_core_ptr_;
@@ -135,6 +145,7 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
// GUIDs and the controller that started the download.
std::map<std::string, JobDetails> job_details_map_;
+ DispatchClickEventCallback click_event_dispatcher_callback_;
base::WeakPtrFactory<BackgroundFetchDelegateProxy> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchDelegateProxy);
diff --git a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
index 788e87a46a8..3b3a88a0e2a 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
@@ -62,10 +62,17 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
aborted_jobs_.insert(job_unique_id);
}
+ void UpdateUI(const std::string& job_unique_id,
+ const std::string& title) override {
+ ++title_update_count_;
+ }
+
void set_complete_downloads(bool complete_downloads) {
complete_downloads_ = complete_downloads;
}
+ int title_update_count_ = 0;
+
private:
void CompleteDownload(const std::string& job_unique_id,
const std::string& guid) {
@@ -77,7 +84,8 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
client()->OnDownloadComplete(job_unique_id, guid,
std::make_unique<BackgroundFetchResult>(
- base::Time::Now(), base::FilePath(), 10u));
+ base::Time::Now(), base::FilePath(),
+ base::nullopt /* blob_handle */, 10u));
}
std::set<std::string> aborted_jobs_;
@@ -239,4 +247,29 @@ TEST_F(BackgroundFetchDelegateProxyTest, GetIconDisplaySize) {
EXPECT_EQ(out_display_size.height(), kIconDisplaySize);
}
+TEST_F(BackgroundFetchDelegateProxyTest, UpdateUI) {
+ FakeController controller;
+ ServiceWorkerFetchRequest fetch_request;
+
+ auto request = CreateRequestInfo(0 /* request_index */, fetch_request);
+ auto fetch_description = std::make_unique<BackgroundFetchDescription>(
+ kExampleUniqueId, "Job 1 Started.", url::Origin(), SkBitmap(),
+ 0 /* completed_parts */, 1 /* total_parts */,
+ 0 /* completed_parts_size */, 0 /* total_parts_size */,
+ std::vector<std::string>());
+
+ delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
+ std::move(fetch_description));
+
+ delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(controller.request_started_);
+ EXPECT_TRUE(controller.request_completed_);
+
+ delegate_proxy_.UpdateUI(kExampleUniqueId, "Job 1 Complete!");
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(delegate_.title_update_count_, 1);
+}
+
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc
index 4f7182d5511..81b2e3ae092 100644
--- a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc
@@ -7,7 +7,7 @@
#include "base/callback.h"
#include "base/time/time.h"
#include "content/common/background_fetch/background_fetch_types.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
namespace content {
@@ -23,8 +23,7 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchAbortEventCallback callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback) {
last_developer_id_ = developer_id;
last_unique_id_ = unique_id;
last_fetches_ = fetches;
@@ -44,8 +43,7 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent(
const std::string& developer_id,
mojom::BackgroundFetchState state,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchClickEventCallback callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback) {
last_developer_id_ = developer_id;
last_state_ = state;
@@ -65,8 +63,7 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchFailEventCallback callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback) {
last_developer_id_ = developer_id;
last_unique_id_ = unique_id;
last_fetches_ = fetches;
@@ -87,8 +84,7 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchedEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::DispatchBackgroundFetchedEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback) {
last_developer_id_ = developer_id;
last_unique_id_ = unique_id;
last_fetches_ = fetches;
diff --git a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
index 248b9113586..312debdfb4e 100644
--- a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
+++ b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
@@ -70,25 +70,25 @@ class BackgroundFetchEmbeddedWorkerTestHelper
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchAbortEventCallback callback) override;
+ mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback)
+ override;
void OnBackgroundFetchClickEvent(
const std::string& developer_id,
mojom::BackgroundFetchState state,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchClickEventCallback callback) override;
+ mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback)
+ override;
void OnBackgroundFetchFailEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchFailEventCallback callback) override;
+ mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback)
+ override;
void OnBackgroundFetchedEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchedEventCallback callback) override;
+ mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback)
+ override;
private:
bool fail_abort_event_ = false;
diff --git a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
index 452c9524c84..e80dd43eb28 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
@@ -51,14 +51,13 @@ void RecordDispatchResult(
// Records the failure reason of a failed dispatch for |metric_name|.
void RecordFailureResult(ServiceWorkerMetrics::EventType event,
const char* metric_name,
- ServiceWorkerStatusCode service_worker_status) {
+ blink::ServiceWorkerStatusCode service_worker_status) {
std::string histogram_name = base::StringPrintf(
"BackgroundFetch.EventDispatchFailure.%s.%s", metric_name,
HistogramSuffixForEventType(event).c_str());
// Used because the |histogram_name| is not a constant.
- base::UmaHistogramEnumeration(histogram_name, service_worker_status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
+ base::UmaHistogramEnumeration(histogram_name, service_worker_status);
}
} // namespace
@@ -95,7 +94,7 @@ void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchAbortEvent(
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
- service_worker_version->event_dispatcher()->DispatchBackgroundFetchAbortEvent(
+ service_worker_version->endpoint()->DispatchBackgroundFetchAbortEvent(
developer_id, unique_id, fetches,
service_worker_version->CreateSimpleEventCallback(request_id));
}
@@ -119,7 +118,7 @@ void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchClickEvent(
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
- service_worker_version->event_dispatcher()->DispatchBackgroundFetchClickEvent(
+ service_worker_version->endpoint()->DispatchBackgroundFetchClickEvent(
developer_id, state,
service_worker_version->CreateSimpleEventCallback(request_id));
}
@@ -145,7 +144,7 @@ void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchFailEvent(
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
- service_worker_version->event_dispatcher()->DispatchBackgroundFetchFailEvent(
+ service_worker_version->endpoint()->DispatchBackgroundFetchFailEvent(
developer_id, unique_id, fetches,
service_worker_version->CreateSimpleEventCallback(request_id));
}
@@ -171,7 +170,7 @@ void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchedEvent(
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
- service_worker_version->event_dispatcher()->DispatchBackgroundFetchedEvent(
+ service_worker_version->endpoint()->DispatchBackgroundFetchedEvent(
developer_id, unique_id, fetches,
service_worker_version->CreateSimpleEventCallback(request_id));
}
@@ -193,9 +192,9 @@ void BackgroundFetchEventDispatcher::StartActiveWorkerForDispatch(
ServiceWorkerMetrics::EventType event,
base::OnceClosure finished_closure,
ServiceWorkerLoadedCallback loaded_callback,
- ServiceWorkerStatusCode service_worker_status,
+ blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> registration) {
- if (service_worker_status != SERVICE_WORKER_OK) {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
DidDispatchEvent(event, std::move(finished_closure), DispatchPhase::FINDING,
service_worker_status);
return;
@@ -216,8 +215,8 @@ void BackgroundFetchEventDispatcher::DispatchEvent(
base::OnceClosure finished_closure,
ServiceWorkerLoadedCallback loaded_callback,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
- ServiceWorkerStatusCode start_worker_status) {
- if (start_worker_status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode start_worker_status) {
+ if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
DidDispatchEvent(event, std::move(finished_closure),
DispatchPhase::STARTING, start_worker_status);
return;
@@ -235,7 +234,7 @@ void BackgroundFetchEventDispatcher::DidDispatchEvent(
ServiceWorkerMetrics::EventType event,
base::OnceClosure finished_closure,
DispatchPhase dispatch_phase,
- ServiceWorkerStatusCode service_worker_status) {
+ blink::ServiceWorkerStatusCode service_worker_status) {
// Record the histograms tracking event dispatching success.
switch (dispatch_phase) {
case DispatchPhase::FINDING:
@@ -247,7 +246,7 @@ void BackgroundFetchEventDispatcher::DidDispatchEvent(
RecordFailureResult(event, "StartWorker", service_worker_status);
break;
case DispatchPhase::DISPATCHING:
- if (service_worker_status != SERVICE_WORKER_OK) {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
RecordDispatchResult(event, DISPATCH_RESULT_CANNOT_DISPATCH_EVENT);
RecordFailureResult(event, "Dispatch", service_worker_status);
} else {
diff --git a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h
index 7194e67e967..f5358207186 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h
@@ -13,7 +13,7 @@
#include "base/memory/ref_counted.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "content/common/service_worker/service_worker.mojom.h"
namespace content {
@@ -94,7 +94,7 @@ class CONTENT_EXPORT BackgroundFetchEventDispatcher {
ServiceWorkerMetrics::EventType event,
base::OnceClosure finished_closure,
ServiceWorkerLoadedCallback loaded_callback,
- ServiceWorkerStatusCode service_worker_status,
+ blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> registration);
// Dispatches the actual event after the Service Worker has been started.
@@ -103,13 +103,14 @@ class CONTENT_EXPORT BackgroundFetchEventDispatcher {
base::OnceClosure finished_closure,
ServiceWorkerLoadedCallback loaded_callback,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
- ServiceWorkerStatusCode start_worker_status);
+ blink::ServiceWorkerStatusCode start_worker_status);
// Called when an event of type |event| has finished dispatching.
- static void DidDispatchEvent(ServiceWorkerMetrics::EventType event,
- base::OnceClosure finished_closure,
- DispatchPhase dispatch_phase,
- ServiceWorkerStatusCode service_worker_status);
+ static void DidDispatchEvent(
+ ServiceWorkerMetrics::EventType event,
+ base::OnceClosure finished_closure,
+ DispatchPhase dispatch_phase,
+ blink::ServiceWorkerStatusCode service_worker_status);
// Methods that actually invoke the event on an activated Service Worker.
static void DoDispatchBackgroundFetchAbortEvent(
diff --git a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
index aac9e2f1f68..dd6655ef7b2 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
@@ -10,7 +10,7 @@
#include "base/guid.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/background_fetch_test_base.h"
@@ -54,7 +54,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchInvalidRegistration) {
BackgroundFetchEventDispatcher::DISPATCH_RESULT_CANNOT_FIND_WORKER, 1);
histogram_tester_.ExpectBucketCount(
"BackgroundFetch.EventDispatchFailure.FindWorker.AbortEvent",
- SERVICE_WORKER_ERROR_NOT_FOUND, 1);
+ blink::ServiceWorkerStatusCode::kErrorNotFound, 1);
}
TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
@@ -119,7 +119,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
BackgroundFetchEventDispatcher::DISPATCH_RESULT_CANNOT_DISPATCH_EVENT, 1);
histogram_tester_.ExpectUniqueSample(
"BackgroundFetch.EventDispatchFailure.Dispatch.AbortEvent",
- SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, 1);
+ blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected, 1);
}
TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
@@ -183,7 +183,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
BackgroundFetchEventDispatcher::DISPATCH_RESULT_CANNOT_DISPATCH_EVENT, 1);
histogram_tester_.ExpectUniqueSample(
"BackgroundFetch.EventDispatchFailure.Dispatch.ClickEvent",
- SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, 1);
+ blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected, 1);
}
TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
@@ -250,7 +250,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
BackgroundFetchEventDispatcher::DISPATCH_RESULT_CANNOT_DISPATCH_EVENT, 1);
histogram_tester_.ExpectUniqueSample(
"BackgroundFetch.EventDispatchFailure.Dispatch.FailEvent",
- SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, 1);
+ blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected, 1);
}
TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchedEvent) {
@@ -325,7 +325,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchedEvent) {
BackgroundFetchEventDispatcher::DISPATCH_RESULT_CANNOT_DISPATCH_EVENT, 1);
histogram_tester_.ExpectUniqueSample(
"BackgroundFetch.EventDispatchFailure.Dispatch.FetchedEvent",
- SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, 1);
+ blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected, 1);
}
} // namespace
diff --git a/chromium/content/browser/background_fetch/background_fetch_job_controller.cc b/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
index aac1856ce92..2b9a7e6681a 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
@@ -16,7 +16,7 @@ BackgroundFetchJobController::BackgroundFetchJobController(
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
- const BackgroundFetchRegistration& registration,
+ uint64_t bytes_downloaded,
BackgroundFetchRequestManager* request_manager,
ProgressCallback progress_callback,
BackgroundFetchScheduler::FinishedCallback finished_callback)
@@ -24,7 +24,7 @@ BackgroundFetchJobController::BackgroundFetchJobController(
std::move(finished_callback)),
options_(options),
icon_(icon),
- complete_requests_downloaded_bytes_cache_(registration.downloaded),
+ complete_requests_downloaded_bytes_cache_(bytes_downloaded),
request_manager_(request_manager),
delegate_proxy_(delegate_proxy),
progress_callback_(std::move(progress_callback)),
@@ -35,7 +35,8 @@ BackgroundFetchJobController::BackgroundFetchJobController(
void BackgroundFetchJobController::InitializeRequestStatus(
int completed_downloads,
int total_downloads,
- const std::vector<std::string>& outstanding_guids) {
+ const std::vector<std::string>& outstanding_guids,
+ const std::string& ui_title) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Don't allow double initialization.
@@ -49,7 +50,7 @@ void BackgroundFetchJobController::InitializeRequestStatus(
int total_downloads_size = options_.download_total;
auto fetch_description = std::make_unique<BackgroundFetchDescription>(
- registration_id().unique_id(), options_.title, registration_id().origin(),
+ registration_id().unique_id(), ui_title, registration_id().origin(),
icon_, completed_downloads, total_downloads,
complete_requests_downloaded_bytes_cache_, total_downloads_size,
outstanding_guids);
diff --git a/chromium/content/browser/background_fetch/background_fetch_job_controller.h b/chromium/content/browser/background_fetch/background_fetch_job_controller.h
index bc7eb93c844..780791dda8b 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller.h
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller.h
@@ -51,18 +51,20 @@ class CONTENT_EXPORT BackgroundFetchJobController final
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
- const BackgroundFetchRegistration& registration,
+ uint64_t bytes_downloaded,
BackgroundFetchRequestManager* request_manager,
ProgressCallback progress_callback,
BackgroundFetchScheduler::FinishedCallback finished_callback);
~BackgroundFetchJobController() override;
// Initializes the job controller with the status of the active and completed
- // downloads. Only called when this has been loaded from the database.
+ // downloads, as well as the title to use.
+ // Only called when this has been loaded from the database.
void InitializeRequestStatus(
int completed_downloads,
int total_downloads,
- const std::vector<std::string>& outstanding_guids);
+ const std::vector<std::string>& outstanding_guids,
+ const std::string& ui_title);
// Gets the number of bytes downloaded for jobs that are currently running.
uint64_t GetInProgressDownloadedBytes();
diff --git a/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
index f504d14b912..423fc1eb36d 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
@@ -17,10 +17,12 @@
#include "base/run_loop.h"
#include "components/download/public/common/download_item.h"
#include "content/browser/background_fetch/background_fetch_constants.h"
+#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/background_fetch_test_base.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/background_fetch_delegate.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/fake_download_item.h"
@@ -88,6 +90,8 @@ class FakeBackgroundFetchRequestManager : public BackgroundFetchRequestManager {
std::map<std::string, RegistrationState> registration_status_map_;
};
+} // namespace
+
class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
public:
BackgroundFetchJobControllerTest() = default;
@@ -150,25 +154,49 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
DCHECK(delegate_);
delegate_proxy_ = std::make_unique<BackgroundFetchDelegateProxy>(delegate_);
- BackgroundFetchRegistration registration;
- registration.developer_id = registration_id.developer_id();
- registration.unique_id = registration_id.unique_id();
-
auto controller = std::make_unique<BackgroundFetchJobController>(
delegate_proxy_.get(), registration_id, BackgroundFetchOptions(),
- SkBitmap(), registration, &request_manager_,
+ SkBitmap(), 0 /* bytes_downloaded */, &request_manager_,
base::BindRepeating(
&BackgroundFetchJobControllerTest::DidUpdateProgress,
base::Unretained(this)),
base::BindOnce(&BackgroundFetchJobControllerTest::OnJobFinished));
- controller->InitializeRequestStatus(0, total_downloads,
- std::vector<std::string>());
+ controller->InitializeRequestStatus(
+ 0, total_downloads, {} /* outstanding_guids */, "" /* ui_title */);
return controller;
}
+ void AddControllerToContextMap(
+ const std::string& unique_id,
+ std::unique_ptr<BackgroundFetchJobController> controller) {
+ context_->job_controllers_[unique_id] = std::move(controller);
+ }
+
+ // BackgroundFetchTestBase overrides:
+ void SetUp() override {
+ BackgroundFetchTestBase::SetUp();
+
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+
+ context_ = new BackgroundFetchContext(
+ browser_context(),
+ base::WrapRefCounted(embedded_worker_test_helper()->context_wrapper()),
+ base::WrapRefCounted(partition->GetCacheStorageContext()));
+ }
+
+ void TearDown() override {
+ BackgroundFetchTestBase::TearDown();
+ context_ = nullptr;
+
+ // Give pending shutdown operations a chance to finish.
+ base::RunLoop().RunUntilIdle();
+ }
+
protected:
FakeBackgroundFetchRequestManager request_manager_;
+ scoped_refptr<BackgroundFetchContext> context_;
uint64_t last_downloaded_ = 0;
@@ -269,9 +297,6 @@ TEST_F(BackgroundFetchJobControllerTest, Abort) {
controller->StartRequest(requests[0]);
controller->Abort(BackgroundFetchReasonToAbort::CANCELLED_FROM_UI);
- // Tell the delegate to abort the job as well so it doesn't send completed
- // messages to the JobController.
- delegate_->Abort(registration_id.unique_id());
base::RunLoop().RunUntilIdle();
@@ -312,5 +337,50 @@ TEST_F(BackgroundFetchJobControllerTest, Progress) {
EXPECT_EQ(last_downloaded_, strlen(kExampleResponseData));
}
-} // namespace
+TEST_F(BackgroundFetchJobControllerTest, ServiceWorkerRegistrationDeleted) {
+ BackgroundFetchRegistrationId registration_id;
+
+ auto requests = CreateRegistrationForRequests(
+ &registration_id, {{GURL("https://example.com/funny_cat.png"), "GET"}},
+ true /* auto_complete_requests */);
+
+ EXPECT_EQ(JobCompletionStatus::kRunning,
+ request_manager_.GetCompletionStatus(registration_id));
+
+ std::unique_ptr<BackgroundFetchJobController> controller =
+ CreateJobController(registration_id, requests.size());
+
+ AddControllerToContextMap(registration_id.unique_id(), std::move(controller));
+ context_->OnRegistrationDeleted(kExampleServiceWorkerRegistrationId,
+ GURL("https://example.com/funny_cat.png"));
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(JobCompletionStatus::kAborted,
+ request_manager_.GetCompletionStatus(registration_id));
+}
+
+TEST_F(BackgroundFetchJobControllerTest, ServiceWorkerDatabaseDeleted) {
+ BackgroundFetchRegistrationId registration_id;
+
+ auto requests = CreateRegistrationForRequests(
+ &registration_id, {{GURL("https://example.com/funny_cat.png"), "GET"}},
+ true /* auto_complete_requests */);
+
+ EXPECT_EQ(JobCompletionStatus::kRunning,
+ request_manager_.GetCompletionStatus(registration_id));
+
+ std::unique_ptr<BackgroundFetchJobController> controller =
+ CreateJobController(registration_id, requests.size());
+
+ AddControllerToContextMap(registration_id.unique_id(), std::move(controller));
+
+ context_->OnStorageWiped();
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(JobCompletionStatus::kAborted,
+ request_manager_.GetCompletionStatus(registration_id));
+}
+
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_request_info.cc b/chromium/content/browser/background_fetch/background_fetch_request_info.cc
index 25a471ccadd..e13df709f2f 100644
--- a/chromium/content/browser/background_fetch/background_fetch_request_info.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_request_info.cc
@@ -91,6 +91,13 @@ const std::vector<GURL>& BackgroundFetchRequestInfo::GetURLChain() const {
return url_chain_;
}
+const base::Optional<storage::BlobDataHandle>&
+BackgroundFetchRequestInfo::GetBlobDataHandle() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(result_);
+ return result_->blob_handle;
+}
+
const base::FilePath& BackgroundFetchRequestInfo::GetFilePath() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(result_);
@@ -109,4 +116,10 @@ const base::Time& BackgroundFetchRequestInfo::GetResponseTime() const {
return result_->response_time;
}
+bool BackgroundFetchRequestInfo::IsResultSuccess() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(result_);
+ return result_->failure_reason == BackgroundFetchResult::FailureReason::NONE;
+}
+
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_request_info.h b/chromium/content/browser/background_fetch/background_fetch_request_info.h
index a8d12425349..1a796748e4e 100644
--- a/chromium/content/browser/background_fetch/background_fetch_request_info.h
+++ b/chromium/content/browser/background_fetch/background_fetch_request_info.h
@@ -13,6 +13,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
+#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "components/download/public/common/download_item.h"
@@ -21,6 +22,10 @@
#include "content/common/service_worker/service_worker_types.h"
#include "url/gurl.h"
+namespace storage {
+class BlobDataHandle;
+}
+
namespace content {
struct BackgroundFetchResponse;
@@ -75,6 +80,10 @@ class CONTENT_EXPORT BackgroundFetchRequestInfo
// Returns the URL chain for the response, including redirects.
const std::vector<GURL>& GetURLChain() const;
+ // Returns the blob data handle for the response. Only available when dealing
+ // with in-memory downloads.
+ const base::Optional<storage::BlobDataHandle>& GetBlobDataHandle() const;
+
// Returns the absolute path to the file in which the response is stored.
const base::FilePath& GetFilePath() const;
@@ -84,6 +93,9 @@ class CONTENT_EXPORT BackgroundFetchRequestInfo
// Returns the time at which the response was completed.
const base::Time& GetResponseTime() const;
+ // Whether the BackgroundFetchResult was successful.
+ bool IsResultSuccess() const;
+
private:
friend class base::RefCountedDeleteOnSequence<BackgroundFetchRequestInfo>;
friend class base::DeleteHelper<BackgroundFetchRequestInfo>;
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler.cc b/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
index 62309d66bba..ba39a99d590 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
@@ -33,12 +33,23 @@ BackgroundFetchScheduler::BackgroundFetchScheduler(
BackgroundFetchScheduler::~BackgroundFetchScheduler() = default;
+void BackgroundFetchScheduler::RemoveJobController(
+ const BackgroundFetchRegistrationId& registration_id) {
+ for (auto iter = controller_queue_.begin(); iter != controller_queue_.end();
+ /* no increment */) {
+ if ((**iter).registration_id() == registration_id)
+ iter = controller_queue_.erase(iter);
+ else
+ iter++;
+ }
+}
+
void BackgroundFetchScheduler::AddJobController(
BackgroundFetchScheduler::Controller* controller) {
controller_queue_.push_back(controller);
- while (!controller_queue_.empty() &&
- download_controller_map_.size() < max_concurrent_downloads_) {
+ if (!controller_queue_.empty() &&
+ download_controller_map_.size() < max_concurrent_downloads_) {
ScheduleDownload();
}
}
@@ -46,12 +57,14 @@ void BackgroundFetchScheduler::AddJobController(
void BackgroundFetchScheduler::ScheduleDownload() {
DCHECK(download_controller_map_.size() < max_concurrent_downloads_);
- if (controller_queue_.empty())
+ if (lock_scheduler_ || controller_queue_.empty())
return;
auto* controller = controller_queue_.front();
controller_queue_.pop_front();
+ // Making an async call, `ScheduleDownload` shouldn't be called anymore.
+ lock_scheduler_ = true;
request_provider_->PopNextRequest(
controller->registration_id(),
base::BindOnce(&BackgroundFetchScheduler::DidPopNextRequest,
@@ -61,8 +74,20 @@ void BackgroundFetchScheduler::ScheduleDownload() {
void BackgroundFetchScheduler::DidPopNextRequest(
BackgroundFetchScheduler::Controller* controller,
scoped_refptr<BackgroundFetchRequestInfo> request_info) {
+ DCHECK(controller);
+ lock_scheduler_ = false; // Can schedule downloads again.
+
+ // Storage error, fetch might have been aborted.
+ if (!request_info) {
+ ScheduleDownload();
+ return;
+ }
+
download_controller_map_[request_info->download_guid()] = controller;
controller->StartRequest(request_info);
+
+ if (download_controller_map_.size() < max_concurrent_downloads_)
+ ScheduleDownload();
}
void BackgroundFetchScheduler::MarkRequestAsComplete(
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler.h b/chromium/content/browser/background_fetch/background_fetch_scheduler.h
index 8527582c520..243bb95e705 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler.h
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler.h
@@ -88,6 +88,13 @@ class CONTENT_EXPORT BackgroundFetchScheduler
// schedule jobs for |controller|.
void AddJobController(Controller* controller);
+ // Removes a job controller from the scheduler. Abort ongoing fetches on the
+ // controller before calling this.
+ // TODO(crbug.com/850075): Move management of active fetches to
+ // BackgroundFetchScheduler.
+ void RemoveJobController(
+ const BackgroundFetchRegistrationId& registration_id);
+
void set_max_concurrent_downloads(size_t new_max) {
max_concurrent_downloads_ = new_max;
}
@@ -115,6 +122,7 @@ class CONTENT_EXPORT BackgroundFetchScheduler
base::circular_deque<Controller*> controller_queue_;
std::map<std::string, Controller*> download_controller_map_;
+ bool lock_scheduler_ = false;
size_t max_concurrent_downloads_ = 1;
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchScheduler);
diff --git a/chromium/content/browser/background_fetch/background_fetch_service_impl.h b/chromium/content/browser/background_fetch/background_fetch_service_impl.h
index 984a94c034a..c61095e1a3c 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_impl.h
+++ b/chromium/content/browser/background_fetch/background_fetch_service_impl.h
@@ -12,6 +12,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
#include "url/origin.h"
diff --git a/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
index 839e8eee9a7..6e2a9c67992 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -9,19 +9,25 @@
#include "base/auto_reset.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/test/histogram_tester.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
+#include "build/build_config.h"
#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h"
+#include "content/browser/background_fetch/background_fetch_job_controller.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/background_fetch_service_impl.h"
#include "content/browser/background_fetch/background_fetch_test_base.h"
+#include "content/browser/background_fetch/background_fetch_test_data_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "mojo/edk/embedder/embedder.h"
+#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/message.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
+#include "ui/gfx/geometry/size.h"
namespace content {
namespace {
@@ -30,13 +36,13 @@ const char kExampleUniqueId[] = "7e57ab1e-c0de-a150-ca75-1e75f005ba11";
const char kExampleDeveloperId[] = "my-background-fetch";
const char kAlternativeDeveloperId[] = "my-alternative-fetch";
-IconDefinition CreateIcon(std::string src,
- std::string sizes,
- std::string type) {
- IconDefinition icon;
- icon.src = std::move(src);
+blink::Manifest::ImageResource CreateIcon(const std::string& src,
+ std::vector<gfx::Size> sizes,
+ const std::string& type) {
+ blink::Manifest::ImageResource icon;
+ icon.src = GURL(src);
icon.sizes = std::move(sizes);
- icon.type = std::move(type);
+ icon.type = base::ASCIIToUTF16(type);
return icon;
}
@@ -45,13 +51,13 @@ class BadMessageObserver {
public:
BadMessageObserver()
: dummy_message_(0, 0, 0, 0, nullptr), context_(&dummy_message_) {
- mojo::edk::SetDefaultProcessErrorCallback(base::BindRepeating(
+ mojo::core::SetDefaultProcessErrorCallback(base::BindRepeating(
&BadMessageObserver::ReportBadMessage, base::Unretained(this)));
}
~BadMessageObserver() {
- mojo::edk::SetDefaultProcessErrorCallback(
- mojo::edk::ProcessErrorCallback());
+ mojo::core::SetDefaultProcessErrorCallback(
+ mojo::core::ProcessErrorCallback());
}
const std::string& last_error() const { return last_error_; }
@@ -66,6 +72,8 @@ class BadMessageObserver {
DISALLOW_COPY_AND_ASSIGN(BadMessageObserver);
};
+} // namespace
+
class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
public:
BackgroundFetchServiceTest() = default;
@@ -121,6 +129,50 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
out_registration->unique_id);
}
+ // Starts the Fetch without completing it. Only creates a registration.
+ void StartFetch(int64_t service_worker_registration_id,
+ const std::string& developer_id,
+ const std::vector<ServiceWorkerFetchRequest>& requests,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon) {
+ BackgroundFetchRegistrationId registration_id(
+ service_worker_registration_id, origin(), developer_id,
+ kExampleUniqueId);
+
+ base::RunLoop run_loop;
+ context_->data_manager_->CreateRegistration(
+ registration_id, requests, options, icon,
+ base::BindOnce(&BackgroundFetchServiceTest::DidStartFetch,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+
+ // Calls BackgroundFetchServiceImpl::Fetch() and unregisters the service
+ // worker before Fetch has completed but after the controller has been
+ // initialized.
+ void FetchAndUnregisterServiceWorker(
+ int64_t service_worker_registration_id,
+ const std::string& developer_id,
+ const std::vector<ServiceWorkerFetchRequest>& requests,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
+ blink::mojom::BackgroundFetchError* out_error,
+ BackgroundFetchRegistration* out_registration) {
+ DCHECK(out_error);
+ DCHECK(out_registration);
+
+ base::AutoReset<bool> hang_registration_creation_for_testing(
+ &context_->hang_registration_creation_for_testing_, true);
+ base::RunLoop run_loop;
+ service_->Fetch(
+ service_worker_registration_id, developer_id, requests, options, icon,
+ base::BindOnce(&BackgroundFetchServiceTest::DidGetRegistration,
+ base::Unretained(this), run_loop.QuitClosure(),
+ out_error, out_registration));
+ UnregisterServiceWorker();
+ run_loop.Run();
+ }
+
// Synchronous wrapper for BackgroundFetchServiceImpl::UpdateUI().
void UpdateUI(int64_t service_worker_registration_id,
const std::string& developer_id,
@@ -156,6 +208,8 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
// We only delete the registration if we successfully abort.
if (*out_error == blink::mojom::BackgroundFetchError::NONE) {
+ // TODO(crbug.com/850894): The Abort callback is being resolved early.
+ base::RunLoop().RunUntilIdle();
// The error passed to the histogram counter is not related to this
// |*out_error|, but the result of
// BackgroundFetchDataManager::DeleteRegistration. For the purposes these
@@ -201,14 +255,27 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
run_loop.Run();
}
+ std::set<std::string> GetJobIDs() {
+ std::set<std::string> job_ids;
+ for (const auto& it : context_->job_controllers_)
+ job_ids.insert(it.first);
+ return job_ids;
+ }
+
// BackgroundFetchTestBase overrides:
void SetUp() override {
BackgroundFetchTestBase::SetUp();
context_ = new BackgroundFetchContext(
browser_context(),
- base::WrapRefCounted(embedded_worker_test_helper()->context_wrapper()));
-
+ base::WrapRefCounted(embedded_worker_test_helper()->context_wrapper()),
+ nullptr /* cache_storage_context */);
+ context_->SetDataManagerForTesting(
+ std::make_unique<BackgroundFetchTestDataManager>(
+ browser_context(), storage_partition(),
+ embedded_worker_test_helper()->context_wrapper()));
+
+ context_->InitializeOnIOThread();
service_ = std::make_unique<BackgroundFetchServiceImpl>(context_, origin());
}
@@ -238,6 +305,14 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
std::move(quit_closure).Run();
}
+ void DidStartFetch(
+ base::Closure quit_closure,
+ blink::mojom::BackgroundFetchError error,
+ std::unique_ptr<BackgroundFetchRegistration> registration) {
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ std::move(quit_closure).Run();
+ }
+
void DidGetError(base::Closure quit_closure,
blink::mojom::BackgroundFetchError* out_error,
blink::mojom::BackgroundFetchError error) {
@@ -313,8 +388,10 @@ TEST_F(BackgroundFetchServiceTest, FetchRegistrationProperties) {
requests.emplace_back(); // empty, but valid
BackgroundFetchOptions options;
- options.icons.push_back(CreateIcon("funny_cat.png", "256x256", "image/png"));
- options.icons.push_back(CreateIcon("silly_cat.gif", "512x512", "image/gif"));
+ options.icons.push_back(
+ CreateIcon("funny_cat.png", {{256, 256}}, "image/png"));
+ options.icons.push_back(
+ CreateIcon("silly_cat.gif", {{512, 512}}, "image/gif"));
options.title = "My Background Fetch!";
options.download_total = 9001;
@@ -947,7 +1024,10 @@ TEST_F(BackgroundFetchServiceTest, GetDeveloperIds) {
GetDeveloperIds(service_worker_registration_id, &error, &developer_ids);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- ASSERT_EQ(developer_ids.size(), 0u);
+ // TODO(crbug.com/850076): The Storage Worker Database access is not
+ // checking the origin. In a non-test environment this won't happen since a
+ // ServiceWorker registration ID is tied to the origin.
+ ASSERT_EQ(developer_ids.size(), 2u);
}
// Verify that using the wrong service worker id does not return developer ids
@@ -967,5 +1047,78 @@ TEST_F(BackgroundFetchServiceTest, GetDeveloperIds) {
}
}
-} // namespace
+TEST_F(BackgroundFetchServiceTest, UnregisterServiceWorker) {
+ // This test registers a service worker, and calls fetch, but unregisters the
+ // service worker before fetch has finished. We then verify that the
+ // appropriate error is returned from Fetch().
+
+ int64_t service_worker_registration_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
+ service_worker_registration_id);
+
+ std::vector<ServiceWorkerFetchRequest> requests;
+ requests.emplace_back(); // empty, but valid
+
+ BackgroundFetchOptions options;
+ options.icons.push_back(
+ CreateIcon("funny_cat.png", {{256, 256}}, "image/png"));
+ options.icons.push_back(
+ CreateIcon("silly_cat.gif", {{512, 512}}, "image/gif"));
+ options.title = "My Background Fetch!";
+ options.download_total = 9001;
+
+ blink::mojom::BackgroundFetchError error;
+ BackgroundFetchRegistration registration;
+
+ FetchAndUnregisterServiceWorker(service_worker_registration_id,
+ kExampleDeveloperId, requests, options,
+ SkBitmap(), &error, &registration);
+ ASSERT_EQ(error,
+ blink::mojom::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE);
+ EXPECT_TRUE(registration.developer_id.empty());
+}
+
+TEST_F(BackgroundFetchServiceTest, JobsInitializedOnBrowserRestart) {
+ // Initially there are no jobs in the JobController map.
+ EXPECT_TRUE(GetJobIDs().empty());
+
+ int64_t service_worker_registration_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
+ service_worker_registration_id);
+
+ std::vector<ServiceWorkerFetchRequest> requests;
+ requests.push_back(CreateRequestWithProvidedResponse(
+ "GET", GURL("https://example.com/mildly_funny_cat.txt"),
+ TestResponseBuilder(200)
+ .SetResponseData("A mildly funny cat.")
+ .AddResponseHeader("Content-Type", "text/plain")
+ .Build()));
+ BackgroundFetchOptions options;
+
+ // Only register the Fetch.
+ StartFetch(service_worker_registration_id, kExampleDeveloperId, requests,
+ options, SkBitmap());
+
+ // Simulate browser restart by re-creating |context_| and |service_|.
+ SetUp();
+
+ // Queue up a GetRegistration DatabaseTask to run right after the
+ // initialization, but before the fetch is resumed.
+ BackgroundFetchRegistration registration;
+ blink::mojom::BackgroundFetchError error;
+ GetRegistration(service_worker_registration_id, kExampleDeveloperId, &error,
+ &registration);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_EQ(registration.developer_id, kExampleDeveloperId);
+
+ // Allow the fetch to completely finish.
+ thread_bundle_.RunUntilIdle();
+
+ // At this point the fetch ran to completion.
+ EXPECT_TRUE(GetJobIDs().empty());
+ GetRegistration(service_worker_registration_id, kExampleDeveloperId, &error,
+ &registration);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID);
+}
+
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_test_base.cc b/chromium/content/browser/background_fetch/background_fetch_test_base.cc
index 7c08e174d5b..fc5366e5abd 100644
--- a/chromium/content/browser/background_fetch/background_fetch_test_base.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_test_base.cc
@@ -21,9 +21,9 @@
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_registration.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_thread.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
namespace content {
@@ -35,11 +35,11 @@ const char kTestScriptUrl[] = "https://example.com/sw.js";
void DidRegisterServiceWorker(int64_t* out_service_worker_registration_id,
base::Closure quit_closure,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t service_worker_registration_id) {
DCHECK(out_service_worker_registration_id);
- EXPECT_EQ(SERVICE_WORKER_OK, status) << status_message;
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status) << status_message;
*out_service_worker_registration_id = service_worker_registration_id;
@@ -49,16 +49,24 @@ void DidRegisterServiceWorker(int64_t* out_service_worker_registration_id,
void DidFindServiceWorkerRegistration(
scoped_refptr<ServiceWorkerRegistration>* out_service_worker_registration,
base::Closure quit_closure,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
DCHECK(out_service_worker_registration);
- EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
*out_service_worker_registration = service_worker_registration;
std::move(quit_closure).Run();
}
+// Callback for UnregisterServiceWorker.
+void DidUnregisterServiceWorker(base::Closure quit_closure,
+ blink::ServiceWorkerStatusCode status) {
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
+ std::move(quit_closure).Run();
+}
+
} // namespace
BackgroundFetchTestBase::BackgroundFetchTestBase()
@@ -66,7 +74,9 @@ BackgroundFetchTestBase::BackgroundFetchTestBase()
// at time of writing EmbeddedWorkerTestHelper didn't seem to support that.
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
delegate_(browser_context_.GetBackgroundFetchDelegate()),
- origin_(url::Origin::Create(GURL(kTestOrigin))) {}
+ origin_(url::Origin::Create(GURL(kTestOrigin))),
+ storage_partition_(
+ BrowserContext::GetDefaultStoragePartition(browser_context())) {}
BackgroundFetchTestBase::~BackgroundFetchTestBase() {
DCHECK(set_up_called_);
@@ -84,7 +94,6 @@ void BackgroundFetchTestBase::TearDown() {
int64_t BackgroundFetchTestBase::RegisterServiceWorker() {
GURL script_url(kTestScriptUrl);
-
int64_t service_worker_registration_id =
blink::mojom::kInvalidServiceWorkerRegistrationId;
@@ -133,6 +142,14 @@ int64_t BackgroundFetchTestBase::RegisterServiceWorker() {
return service_worker_registration_id;
}
+void BackgroundFetchTestBase::UnregisterServiceWorker() {
+ base::RunLoop run_loop;
+ embedded_worker_test_helper_.context()->UnregisterServiceWorker(
+ origin_.GetURL(),
+ base::BindOnce(&DidUnregisterServiceWorker, run_loop.QuitClosure()));
+ run_loop.Run();
+}
+
ServiceWorkerFetchRequest
BackgroundFetchTestBase::CreateRequestWithProvidedResponse(
const std::string& method,
diff --git a/chromium/content/browser/background_fetch/background_fetch_test_base.h b/chromium/content/browser/background_fetch/background_fetch_test_base.h
index 7d2341b1bee..a2bcc7365bd 100644
--- a/chromium/content/browser/background_fetch/background_fetch_test_base.h
+++ b/chromium/content/browser/background_fetch/background_fetch_test_base.h
@@ -23,6 +23,7 @@
namespace content {
class ServiceWorkerRegistration;
+class StoragePartition;
// Base class containing common functionality needed in unit tests written for
// the Background Fetch feature.
@@ -44,6 +45,10 @@ class BackgroundFetchTestBase : public ::testing::Test {
// ServiceWorkerRegistration will be kept alive for the test's lifetime.
int64_t RegisterServiceWorker();
+ // Unregisters the test Service Worker and verifies that the unregistration
+ // succeeded.
+ void UnregisterServiceWorker();
+
// Creates a ServiceWorkerFetchRequest instance for the given details and
// provides a faked |response|.
ServiceWorkerFetchRequest CreateRequestWithProvidedResponse(
@@ -60,6 +65,9 @@ class BackgroundFetchTestBase : public ::testing::Test {
// Returns the browser context that should be used for the tests.
BrowserContext* browser_context() { return &browser_context_; }
+ // Returns the once-initialized default storage partition to be used in tests.
+ StoragePartition* storage_partition() { return storage_partition_; }
+
// Returns the origin that should be used for Background Fetch tests.
const url::Origin& origin() const { return origin_; }
@@ -75,6 +83,8 @@ class BackgroundFetchTestBase : public ::testing::Test {
url::Origin origin_;
+ StoragePartition* storage_partition_;
+
// Vector of ServiceWorkerRegistration instances that have to be kept alive
// for the lifetime of this test.
std::vector<scoped_refptr<ServiceWorkerRegistration>>
diff --git a/chromium/content/browser/background_fetch/background_fetch_test_data_manager.cc b/chromium/content/browser/background_fetch/background_fetch_test_data_manager.cc
new file mode 100644
index 00000000000..b081be6b97c
--- /dev/null
+++ b/chromium/content/browser/background_fetch/background_fetch_test_data_manager.cc
@@ -0,0 +1,76 @@
+// Copyright 2018 The Chromium Authors. All rights 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_fetch/background_fetch_test_data_manager.h"
+
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/cache_storage/cache_storage_manager.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/test/mock_quota_manager.h"
+#include "storage/browser/test/mock_quota_manager_proxy.h"
+#include "storage/browser/test/mock_special_storage_policy.h"
+
+namespace content {
+
+namespace {
+
+class MockBGFQuotaManagerProxy : public MockQuotaManagerProxy {
+ public:
+ MockBGFQuotaManagerProxy(MockQuotaManager* quota_manager)
+ : MockQuotaManagerProxy(quota_manager,
+ base::ThreadTaskRunnerHandle::Get().get()) {}
+
+ // Ignore quota client, it is irrelevant for these tests.
+ void RegisterClient(QuotaClient* client) override {
+ delete client; // Directly delete, to avoid memory leak.
+ }
+
+ protected:
+ ~MockBGFQuotaManagerProxy() override = default;
+};
+
+} // namespace
+
+BackgroundFetchTestDataManager::BackgroundFetchTestDataManager(
+ BrowserContext* browser_context,
+ StoragePartition* storage_partition,
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ bool mock_fill_response)
+ : BackgroundFetchDataManager(browser_context,
+ service_worker_context,
+ nullptr /* cache_storage_context */),
+ browser_context_(browser_context),
+ storage_partition_(storage_partition),
+ mock_fill_response_(mock_fill_response) {}
+
+void BackgroundFetchTestDataManager::InitializeOnIOThread() {
+ ChromeBlobStorageContext* blob_storage_context(
+ ChromeBlobStorageContext::GetFor(browser_context_));
+ // Wait for ChromeBlobStorageContext to finish initializing.
+ base::RunLoop().RunUntilIdle();
+
+ mock_quota_manager_ = base::MakeRefCounted<MockQuotaManager>(
+ storage_partition_->GetPath().empty(), storage_partition_->GetPath(),
+ base::ThreadTaskRunnerHandle::Get().get(),
+ base::MakeRefCounted<MockSpecialStoragePolicy>());
+ mock_quota_manager_->SetQuota(GURL("https://example.com/"),
+ StorageType::kTemporary, 1024 * 1024 * 100);
+
+ cache_manager_ = CacheStorageManager::Create(
+ storage_partition_->GetPath(), base::ThreadTaskRunnerHandle::Get(),
+ base::MakeRefCounted<MockBGFQuotaManagerProxy>(
+ mock_quota_manager_.get()));
+ DCHECK(cache_manager_);
+
+ cache_manager_->SetBlobParametersForCache(
+ storage_partition_->GetURLRequestContext(),
+ blob_storage_context->context()->AsWeakPtr());
+}
+
+BackgroundFetchTestDataManager::~BackgroundFetchTestDataManager() = default;
+
+} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_test_data_manager.h b/chromium/content/browser/background_fetch/background_fetch_test_data_manager.h
new file mode 100644
index 00000000000..9596d3f84d8
--- /dev/null
+++ b/chromium/content/browser/background_fetch/background_fetch_test_data_manager.h
@@ -0,0 +1,51 @@
+// Copyright 2018 The Chromium Authors. All 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_FETCH_BACKGROUND_FETCH_TEST_DATA_MANAGER_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_TEST_DATA_MANAGER_H_
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "content/browser/background_fetch/background_fetch_data_manager.h"
+#include "content/browser/background_fetch/background_fetch_request_info.h"
+#include "url/origin.h"
+
+namespace content {
+
+class BrowserContext;
+class CacheStorageManager;
+class MockQuotaManager;
+class ServiceWorkerContextWrapper;
+class StoragePartition;
+
+// Test DataManager that sets up a CacheStorageManager suited for test
+// environments. Tests can also optionally override FillServiceWorkerResponse by
+// setting |mock_fill_response| to true.
+class BackgroundFetchTestDataManager : public BackgroundFetchDataManager {
+ public:
+ BackgroundFetchTestDataManager(
+ BrowserContext* browser_context,
+ StoragePartition* storage_partition,
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ bool mock_fill_response = false);
+
+ ~BackgroundFetchTestDataManager() override;
+
+ void InitializeOnIOThread() override;
+
+ private:
+ friend class BackgroundFetchDataManagerTest;
+
+ scoped_refptr<MockQuotaManager> mock_quota_manager_;
+ BrowserContext* browser_context_;
+ StoragePartition* storage_partition_;
+ bool mock_fill_response_;
+
+ DISALLOW_COPY_AND_ASSIGN(BackgroundFetchTestDataManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_TEST_DATA_MANAGER_H_
diff --git a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc
index 753d955a839..72a098529cc 100644
--- a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc
+++ b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc
@@ -130,7 +130,8 @@ void MockBackgroundFetchDelegate::DownloadUrl(
&BackgroundFetchDelegate::Client::OnDownloadComplete, client(),
job_unique_id, guid,
std::make_unique<BackgroundFetchResult>(
- base::Time::Now(), response_path, test_response->data.size())));
+ base::Time::Now(), response_path,
+ base::nullopt /* blob_handle */, test_response->data.size())));
} else {
PostAbortCheckingTask(
job_unique_id,
@@ -148,6 +149,9 @@ void MockBackgroundFetchDelegate::Abort(const std::string& job_unique_id) {
aborted_jobs_.insert(job_unique_id);
}
+void MockBackgroundFetchDelegate::UpdateUI(const std::string& job_unique_id,
+ const std::string& title) {}
+
void MockBackgroundFetchDelegate::RegisterResponse(
const GURL& url,
std::unique_ptr<TestResponse> response) {
diff --git a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h
index bc685f96a56..587f07116a5 100644
--- a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h
+++ b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h
@@ -74,6 +74,8 @@ class MockBackgroundFetchDelegate : public BackgroundFetchDelegate {
const net::NetworkTrafficAnnotationTag& traffic_annotation,
const net::HttpRequestHeaders& headers) override;
void Abort(const std::string& job_unique_id) override;
+ void UpdateUI(const std::string& job_unique_id,
+ const std::string& title) override;
void RegisterResponse(const GURL& url,
std::unique_ptr<TestResponse> response);
diff --git a/chromium/content/browser/background_fetch/storage/README.md b/chromium/content/browser/background_fetch/storage/README.md
index e21e9c327e9..a21b6bc1a03 100644
--- a/chromium/content/browser/background_fetch/storage/README.md
+++ b/chromium/content/browser/background_fetch/storage/README.md
@@ -45,6 +45,19 @@ key: "bgfetch_completed_request_<unique_id>_<request_index>"
value: "<serialized content::proto::BackgroundFetchCompletedRequest>"
```
+## Cache Storage UserData schema
+
+The downloaded responses of every fetch will be stored in their own private cache.
+
+### Cache identifiers
+* `origin`: `<origin>`
+* `owner`: `CacheStorageOwner::kBackgroundFetch`
+* `cache_name`: `<unique_id>`
+
+The cache will contain all the Request/Response key/value pairs of the fetch.
+Note that the Request value stored isn't comprehensive, and only the url value is
+used to as a key to find the matching Response.
+
### Expansions
* `<unique_id>` is a GUID (v4) that identifies a background fetch registration.
E.g. `17467386-60b4-4c5b-b66c-aabf793fd39b`
diff --git a/chromium/content/browser/background_fetch/storage/cleanup_task.cc b/chromium/content/browser/background_fetch/storage/cleanup_task.cc
index 047ec4b9015..8940c09d09d 100644
--- a/chromium/content/browser/background_fetch/storage/cleanup_task.cc
+++ b/chromium/content/browser/background_fetch/storage/cleanup_task.cc
@@ -8,9 +8,11 @@
#include "base/containers/flat_set.h"
#include "content/browser/background_fetch/background_fetch.pb.h"
+#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/background_fetch/storage/delete_registration_task.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "url/origin.h"
namespace content {
@@ -20,8 +22,8 @@ namespace {
void EmptyErrorHandler(blink::mojom::BackgroundFetchError) {}
} // namespace
-CleanupTask::CleanupTask(BackgroundFetchDataManager* data_manager)
- : DatabaseTask(data_manager), weak_factory_(this) {}
+CleanupTask::CleanupTask(DatabaseTaskHost* host)
+ : DatabaseTask(host), weak_factory_(this) {}
CleanupTask::~CleanupTask() = default;
@@ -33,10 +35,10 @@ void CleanupTask::Start() {
void CleanupTask::DidGetRegistrations(
const std::vector<std::pair<int64_t, std::string>>& registration_data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
if (ToDatabaseStatus(status) != DatabaseStatus::kOk ||
registration_data.empty()) {
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
@@ -49,13 +51,13 @@ void CleanupTask::DidGetRegistrations(
void CleanupTask::DidGetActiveUniqueIds(
const std::vector<std::pair<int64_t, std::string>>& registration_data,
const std::vector<std::pair<int64_t, std::string>>& active_unique_id_data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
case DatabaseStatus::kNotFound:
break;
case DatabaseStatus::kFailed:
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
@@ -78,17 +80,22 @@ void CleanupTask::DidGetActiveUniqueIds(
// This |unique_id| can be safely cleaned up. Re-use
// DeleteRegistrationTask for the actual deletion logic.
AddDatabaseTask(std::make_unique<DeleteRegistrationTask>(
- data_manager(), service_worker_registration_id, unique_id,
+ data_manager(), service_worker_registration_id,
+ url::Origin::Create(GURL(metadata_proto.origin())), unique_id,
base::BindOnce(&EmptyErrorHandler)));
}
}
}
}
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
return;
}
+void CleanupTask::FinishWithError(blink::mojom::BackgroundFetchError error) {
+ Finished(); // Destroys |this|.
+}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/cleanup_task.h b/chromium/content/browser/background_fetch/storage/cleanup_task.h
index 92db4ae4266..e116f789a39 100644
--- a/chromium/content/browser/background_fetch/storage/cleanup_task.h
+++ b/chromium/content/browser/background_fetch/storage/cleanup_task.h
@@ -10,7 +10,7 @@
#include <vector>
#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
@@ -20,7 +20,7 @@ namespace background_fetch {
// TODO(crbug.com/780025): Log failed deletions to UMA.
class CleanupTask : public background_fetch::DatabaseTask {
public:
- explicit CleanupTask(BackgroundFetchDataManager* data_manager);
+ explicit CleanupTask(DatabaseTaskHost* host);
~CleanupTask() override;
@@ -29,13 +29,14 @@ class CleanupTask : public background_fetch::DatabaseTask {
private:
void DidGetRegistrations(
const std::vector<std::pair<int64_t, std::string>>& registration_data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
- private:
void DidGetActiveUniqueIds(
const std::vector<std::pair<int64_t, std::string>>& registration_data,
const std::vector<std::pair<int64_t, std::string>>& active_unique_id_data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
+
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
base::WeakPtrFactory<CleanupTask> weak_factory_; // Keep as last.
diff --git a/chromium/content/browser/background_fetch/storage/create_metadata_task.cc b/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
index c070e9f817b..07fdeb13d8a 100644
--- a/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
+++ b/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
@@ -6,25 +6,49 @@
#include <utility>
+#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "ui/gfx/image/image.h"
namespace content {
namespace background_fetch {
+namespace {
+
+std::string ConvertAndSerializeIcon(const SkBitmap& icon) {
+ // Serialize the icon and copy the bytes over.
+ std::string serialized_icon;
+ auto icon_bytes = gfx::Image::CreateFrom1xBitmap(icon).As1xPNGBytes();
+ serialized_icon.assign(icon_bytes->front_as<char>(),
+ icon_bytes->front_as<char>() + icon_bytes->size());
+ return serialized_icon;
+}
+
+} // namespace
+
+// The max icon resolution, this is used as a threshold to decide
+// whether the icon should be persisted.
+constexpr int kMaxIconResolution = 256 * 256;
+
CreateMetadataTask::CreateMetadataTask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
CreateMetadataCallback callback)
- : DatabaseTask(data_manager),
+ : DatabaseTask(host),
registration_id_(registration_id),
requests_(requests),
options_(options),
+ icon_(icon),
callback_(std::move(callback)),
weak_factory_(this) {}
@@ -39,46 +63,62 @@ void CreateMetadataTask::Start() {
}
void CreateMetadataTask::DidGetUniqueId(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kNotFound:
- StoreMetadata();
+ InitializeMetadataProto();
return;
case DatabaseStatus::kOk:
// Can't create a registration since there is already an active
// registration with the same |developer_id|. It must be deactivated
// (completed/failed/aborted) first.
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::DUPLICATED_DEVELOPER_ID,
- nullptr /* metadata */);
- Finished(); // Destroys |this|.
+ FinishWithError(
+ blink::mojom::BackgroundFetchError::DUPLICATED_DEVELOPER_ID);
return;
case DatabaseStatus::kFailed:
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR,
- nullptr /* metadata */);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
}
void CreateMetadataTask::InitializeMetadataProto() {
metadata_proto_ = std::make_unique<proto::BackgroundFetchMetadata>();
+
// Set BackgroundFetchRegistration fields.
- // Upload/Download stats default to correct initial values.
auto* registration_proto = metadata_proto_->mutable_registration();
registration_proto->set_unique_id(registration_id_.unique_id());
registration_proto->set_developer_id(registration_id_.developer_id());
+ registration_proto->set_download_total(options_.download_total);
// Set Options fields.
auto* options_proto = metadata_proto_->mutable_options();
options_proto->set_title(options_.title);
options_proto->set_download_total(options_.download_total);
for (const auto& icon : options_.icons) {
- auto* icon_definition_proto = options_proto->add_icons();
- icon_definition_proto->set_src(icon.src);
- icon_definition_proto->set_sizes(icon.sizes);
- icon_definition_proto->set_type(icon.type);
+ auto* image_resource_proto = options_proto->add_icons();
+
+ image_resource_proto->set_src(icon.src.spec());
+
+ for (const auto& size : icon.sizes) {
+ auto* size_proto = image_resource_proto->add_sizes();
+ size_proto->set_width(size.width());
+ size_proto->set_height(size.height());
+ }
+
+ image_resource_proto->set_type(base::UTF16ToASCII(icon.type));
+
+ for (const auto& purpose : icon.purpose) {
+ switch (purpose) {
+ case blink::Manifest::ImageResource::Purpose::ANY:
+ image_resource_proto->add_purpose(
+ proto::BackgroundFetchOptions_ImageResource_Purpose_ANY);
+ break;
+ case blink::Manifest::ImageResource::Purpose::BADGE:
+ image_resource_proto->add_purpose(
+ proto::BackgroundFetchOptions_ImageResource_Purpose_BADGE);
+ break;
+ }
+ }
}
// Set other metadata fields.
@@ -86,20 +126,40 @@ void CreateMetadataTask::InitializeMetadataProto() {
metadata_proto_->set_creation_microseconds_since_unix_epoch(
(base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds());
metadata_proto_->set_num_fetches(requests_.size());
+
+ // Check if |icon_| should be persisted.
+ if (icon_.height() * icon_.width() > kMaxIconResolution) {
+ StoreMetadata();
+ return;
+ }
+
+ // Do the initialization on a seperate thread to avoid blocking on
+ // expensive operations (image conversions), then post back to IO thread
+ // and continue normally.
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE,
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+ base::TaskPriority::BACKGROUND},
+ base::BindOnce(&ConvertAndSerializeIcon, icon_),
+ base::BindOnce(&CreateMetadataTask::StoreIcon,
+ weak_factory_.GetWeakPtr()));
+}
+
+void CreateMetadataTask::StoreIcon(std::string serialized_icon) {
+ DCHECK(metadata_proto_);
+ metadata_proto_->set_icon(std::move(serialized_icon));
+ StoreMetadata();
}
void CreateMetadataTask::StoreMetadata() {
+ DCHECK(metadata_proto_);
std::vector<std::pair<std::string, std::string>> entries;
entries.reserve(requests_.size() * 2 + 1);
- InitializeMetadataProto();
std::string serialized_metadata_proto;
if (!metadata_proto_->SerializeToString(&serialized_metadata_proto)) {
- // TODO(crbug.com/780025): Log failures to UMA.
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR,
- nullptr /* metadata */);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
@@ -123,29 +183,32 @@ void CreateMetadataTask::StoreMetadata() {
service_worker_context()->StoreRegistrationUserData(
registration_id_.service_worker_registration_id(),
registration_id_.origin().GetURL(), entries,
- base::BindRepeating(&CreateMetadataTask::DidStoreMetadata,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&CreateMetadataTask::DidStoreMetadata,
+ weak_factory_.GetWeakPtr()));
}
-void CreateMetadataTask::DidStoreMetadata(ServiceWorkerStatusCode status) {
- DCHECK(metadata_proto_);
-
+void CreateMetadataTask::DidStoreMetadata(
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
break;
case DatabaseStatus::kFailed:
case DatabaseStatus::kNotFound:
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR,
- nullptr /* metadata */);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::NONE,
- std::move(metadata_proto_));
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+}
+
+void CreateMetadataTask::FinishWithError(
+ blink::mojom::BackgroundFetchError error) {
+ if (error != blink::mojom::BackgroundFetchError::NONE)
+ metadata_proto_.reset();
+ std::move(callback_).Run(error, std::move(metadata_proto_));
Finished(); // Destroys |this|.
}
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/create_metadata_task.h b/chromium/content/browser/background_fetch/storage/create_metadata_task.h
index 433c265c38a..48bc0d59541 100644
--- a/chromium/content/browser/background_fetch/storage/create_metadata_task.h
+++ b/chromium/content/browser/background_fetch/storage/create_metadata_task.h
@@ -11,8 +11,9 @@
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
+#include "third_party/skia/include/core/SkBitmap.h"
namespace content {
@@ -25,10 +26,11 @@ class CreateMetadataTask : public DatabaseTask {
base::OnceCallback<void(blink::mojom::BackgroundFetchError,
std::unique_ptr<proto::BackgroundFetchMetadata>)>;
- CreateMetadataTask(BackgroundFetchDataManager* data_manager,
+ CreateMetadataTask(DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
CreateMetadataCallback callback);
~CreateMetadataTask() override;
@@ -37,17 +39,23 @@ class CreateMetadataTask : public DatabaseTask {
private:
void DidGetUniqueId(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
+
+ void StoreIcon(std::string serialized_icon);
void StoreMetadata();
- void DidStoreMetadata(ServiceWorkerStatusCode status);
+ void DidStoreMetadata(
+ blink::ServiceWorkerStatusCode status);
void InitializeMetadataProto();
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+
BackgroundFetchRegistrationId registration_id_;
std::vector<ServiceWorkerFetchRequest> requests_;
BackgroundFetchOptions options_;
+ SkBitmap icon_;
CreateMetadataCallback callback_;
std::unique_ptr<proto::BackgroundFetchMetadata> metadata_proto_;
diff --git a/chromium/content/browser/background_fetch/storage/database_helpers.cc b/chromium/content/browser/background_fetch/storage/database_helpers.cc
index cb8348e731c..4e4fadf265c 100644
--- a/chromium/content/browser/background_fetch/storage/database_helpers.cc
+++ b/chromium/content/browser/background_fetch/storage/database_helpers.cc
@@ -52,36 +52,35 @@ std::string CompletedRequestKey(const std::string& unique_id,
return CompletedRequestKeyPrefix(unique_id) + std::to_string(request_index);
}
-DatabaseStatus ToDatabaseStatus(ServiceWorkerStatusCode status) {
+DatabaseStatus ToDatabaseStatus(blink::ServiceWorkerStatusCode status) {
switch (status) {
- case SERVICE_WORKER_OK:
+ case blink::ServiceWorkerStatusCode::kOk:
return DatabaseStatus::kOk;
- case SERVICE_WORKER_ERROR_FAILED:
- case SERVICE_WORKER_ERROR_ABORT:
+ case blink::ServiceWorkerStatusCode::kErrorFailed:
+ case blink::ServiceWorkerStatusCode::kErrorAbort:
// FAILED is for invalid arguments (e.g. empty key) or database errors.
// ABORT is for unexpected failures, e.g. because shutdown is in progress.
// BackgroundFetchDataManager handles both of these the same way.
return DatabaseStatus::kFailed;
- case SERVICE_WORKER_ERROR_NOT_FOUND:
+ case blink::ServiceWorkerStatusCode::kErrorNotFound:
// This can also happen for writes, if the ServiceWorkerRegistration has
// been deleted.
return DatabaseStatus::kNotFound;
- case SERVICE_WORKER_ERROR_START_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND:
- case SERVICE_WORKER_ERROR_EXISTS:
- case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_IPC_FAILED:
- case SERVICE_WORKER_ERROR_NETWORK:
- case SERVICE_WORKER_ERROR_SECURITY:
- case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED:
- case SERVICE_WORKER_ERROR_STATE:
- case SERVICE_WORKER_ERROR_TIMEOUT:
- case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED:
- case SERVICE_WORKER_ERROR_DISK_CACHE:
- case SERVICE_WORKER_ERROR_REDUNDANT:
- case SERVICE_WORKER_ERROR_DISALLOWED:
- case SERVICE_WORKER_ERROR_MAX_VALUE:
+ case blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorProcessNotFound:
+ case blink::ServiceWorkerStatusCode::kErrorExists:
+ case blink::ServiceWorkerStatusCode::kErrorInstallWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorActivateWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorIpcFailed:
+ case blink::ServiceWorkerStatusCode::kErrorNetwork:
+ case blink::ServiceWorkerStatusCode::kErrorSecurity:
+ case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
+ case blink::ServiceWorkerStatusCode::kErrorState:
+ case blink::ServiceWorkerStatusCode::kErrorTimeout:
+ case blink::ServiceWorkerStatusCode::kErrorScriptEvaluateFailed:
+ case blink::ServiceWorkerStatusCode::kErrorDiskCache:
+ case blink::ServiceWorkerStatusCode::kErrorRedundant:
+ case blink::ServiceWorkerStatusCode::kErrorDisallowed:
break;
}
NOTREACHED();
diff --git a/chromium/content/browser/background_fetch/storage/database_helpers.h b/chromium/content/browser/background_fetch/storage/database_helpers.h
index c81874378ce..a9741fe283c 100644
--- a/chromium/content/browser/background_fetch/storage/database_helpers.h
+++ b/chromium/content/browser/background_fetch/storage/database_helpers.h
@@ -7,8 +7,8 @@
#include <string>
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
@@ -50,7 +50,7 @@ std::string CompletedRequestKey(const std::string& unique_id,
enum class DatabaseStatus { kOk, kFailed, kNotFound };
-DatabaseStatus ToDatabaseStatus(ServiceWorkerStatusCode status);
+DatabaseStatus ToDatabaseStatus(blink::ServiceWorkerStatusCode status);
} // namespace background_fetch
diff --git a/chromium/content/browser/background_fetch/storage/database_task.cc b/chromium/content/browser/background_fetch/storage/database_task.cc
index d8139c4b842..62a5a758c1e 100644
--- a/chromium/content/browser/background_fetch/storage/database_task.cc
+++ b/chromium/content/browser/background_fetch/storage/database_task.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "content/browser/background_fetch/background_fetch_data_manager.h"
+#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/public/browser/browser_thread.h"
@@ -14,23 +15,72 @@ namespace content {
namespace background_fetch {
+DatabaseTaskHost::DatabaseTaskHost() : weak_factory_(this) {}
+
+DatabaseTaskHost::~DatabaseTaskHost() = default;
+
+base::WeakPtr<DatabaseTaskHost> DatabaseTaskHost::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+DatabaseTask::DatabaseTask(DatabaseTaskHost* host) : host_(host) {
+ DCHECK(host_);
+ // Hold a reference to the CacheStorageManager.
+ cache_manager_ = data_manager()->cache_manager();
+}
+
+DatabaseTask::~DatabaseTask() = default;
+
void DatabaseTask::Finished() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // Post the OnTaskFinished callback to the same thread, to allow the the
+ // DatabaseTask to finish execution before deallocating it.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&DatabaseTaskHost::OnTaskFinished,
+ host_->GetWeakPtr(), this));
+}
- data_manager_->OnDatabaseTaskFinished(this);
+void DatabaseTask::OnTaskFinished(DatabaseTask* finished_subtask) {
+ size_t erased = active_subtasks_.erase(finished_subtask);
+ DCHECK_EQ(erased, 1u);
}
void DatabaseTask::AddDatabaseTask(std::unique_ptr<DatabaseTask> task) {
- data_manager_->AddDatabaseTask(std::move(task));
+ DCHECK_EQ(task->host_, data_manager());
+ data_manager()->AddDatabaseTask(std::move(task));
+}
+
+void DatabaseTask::AddSubTask(std::unique_ptr<DatabaseTask> task) {
+ DCHECK_EQ(task->host_, this);
+ auto insert_result = active_subtasks_.emplace(task.get(), std::move(task));
+ insert_result.first->second->Start(); // Start the subtask.
+}
+
+void DatabaseTask::AbandonFetches(int64_t service_worker_registration_id) {
+ for (auto& observer : data_manager()->observers())
+ observer.OnServiceWorkerDatabaseCorrupted(service_worker_registration_id);
}
ServiceWorkerContextWrapper* DatabaseTask::service_worker_context() {
- DCHECK(data_manager_->service_worker_context_);
- return data_manager_->service_worker_context_.get();
+ DCHECK(data_manager()->service_worker_context());
+ return data_manager()->service_worker_context();
+}
+
+CacheStorageManager* DatabaseTask::cache_manager() {
+ DCHECK(cache_manager_);
+ return cache_manager_.get();
}
std::set<std::string>& DatabaseTask::ref_counted_unique_ids() {
- return data_manager_->ref_counted_unique_ids_;
+ return data_manager()->ref_counted_unique_ids();
+}
+
+ChromeBlobStorageContext* DatabaseTask::blob_storage_context() {
+ return data_manager()->blob_storage_context();
+}
+
+BackgroundFetchDataManager* DatabaseTask::data_manager() {
+ return host_->data_manager();
}
} // namespace background_fetch
diff --git a/chromium/content/browser/background_fetch/storage/database_task.h b/chromium/content/browser/background_fetch/storage/database_task.h
index 3d46a0fb358..3d5742cfa6e 100644
--- a/chromium/content/browser/background_fetch/storage/database_task.h
+++ b/chromium/content/browser/background_fetch/storage/database_task.h
@@ -11,12 +11,16 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
+#include "content/browser/cache_storage/cache_storage_manager.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
namespace content {
class BackgroundFetchDataManager;
+class CacheStorageManager;
+class ChromeBlobStorageContext;
class ServiceWorkerContextWrapper;
// Note that this also handles non-error cases where the NONE is NONE.
@@ -25,6 +29,26 @@ using HandleBackgroundFetchErrorCallback =
namespace background_fetch {
+class DatabaseTask;
+
+// A DatabaseTaskHost is the entity responsible for scheduling and running
+// DatabaseTasks, usually the BackgroundFetchDataManager. Note that a
+// DatabaseTask can be a DatabaseTaskHost, in order to run subtasks.
+class DatabaseTaskHost {
+ public:
+ virtual void OnTaskFinished(DatabaseTask* task) = 0;
+ virtual BackgroundFetchDataManager* data_manager() = 0;
+ virtual ~DatabaseTaskHost();
+
+ base::WeakPtr<DatabaseTaskHost> GetWeakPtr();
+
+ protected:
+ DatabaseTaskHost();
+
+ private:
+ base::WeakPtrFactory<DatabaseTaskHost> weak_factory_;
+};
+
// A DatabaseTask is an asynchronous "transaction" that needs to read/write the
// Service Worker Database.
//
@@ -32,32 +56,57 @@ namespace background_fetch {
// reads/writes Background Fetch keys, so each task effectively has an exclusive
// lock, except that core Service Worker code may delete all keys for a
// ServiceWorkerRegistration or the entire database at any time.
-class DatabaseTask {
+//
+// A DatabaseTask can also optionally run other DatabaseTasks as subtasks. This
+// allows us to re-use commonly used DatabaseTasks. Subtasks are started as soon
+// as they are added, and cannot outlive the parent DatabaseTask.
+class DatabaseTask : public DatabaseTaskHost {
public:
- virtual ~DatabaseTask() = default;
+ ~DatabaseTask() override;
virtual void Start() = 0;
protected:
- explicit DatabaseTask(BackgroundFetchDataManager* data_manager)
- : data_manager_(data_manager) {
- DCHECK(data_manager_);
- }
+ explicit DatabaseTask(DatabaseTaskHost* host);
// Each task MUST call this once finished, even if exceptions occur, to
// release their lock and allow the next task to execute.
+ // This should be called in FinishWithError() for consistency.
void Finished();
void AddDatabaseTask(std::unique_ptr<DatabaseTask> task);
+ void AddSubTask(std::unique_ptr<DatabaseTask> task);
+
+ // Abandon all fetches for a given service worker.
+ void AbandonFetches(int64_t service_worker_registration_id);
ServiceWorkerContextWrapper* service_worker_context();
+ CacheStorageManager* cache_manager();
+
std::set<std::string>& ref_counted_unique_ids();
- BackgroundFetchDataManager* data_manager() { return data_manager_; }
+ ChromeBlobStorageContext* blob_storage_context();
+
+ // DatabaseTaskHost implementation.
+ void OnTaskFinished(DatabaseTask* finished_subtask) override;
+ BackgroundFetchDataManager* data_manager() override;
private:
- BackgroundFetchDataManager* data_manager_; // Owns this.
+ // Each task must override this function and perform the following steps:
+ // 1) Report error (UMA) if applicable.
+ // 2) Run the provided callback.
+ // 3) Call Finished().
+ virtual void FinishWithError(blink::mojom::BackgroundFetchError error) = 0;
+
+ DatabaseTaskHost* host_;
+
+ // Owns a reference to the CacheStorageManager in case Shutdown was
+ // called and the DatabaseTask needs to finish.
+ scoped_refptr<CacheStorageManager> cache_manager_;
+
+ // Map the raw pointer to its unique_ptr, to make lookups easier.
+ std::map<DatabaseTask*, std::unique_ptr<DatabaseTask>> active_subtasks_;
DISALLOW_COPY_AND_ASSIGN(DatabaseTask);
};
diff --git a/chromium/content/browser/background_fetch/storage/delete_registration_task.cc b/chromium/content/browser/background_fetch/storage/delete_registration_task.cc
index e5c2d759758..5734680a96d 100644
--- a/chromium/content/browser/background_fetch/storage/delete_registration_task.cc
+++ b/chromium/content/browser/background_fetch/storage/delete_registration_task.cc
@@ -6,8 +6,11 @@
#include <utility>
+#include "base/barrier_closure.h"
#include "content/browser/background_fetch/background_fetch.pb.h"
+#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
namespace content {
@@ -21,7 +24,7 @@ namespace {
// been already marked for deletion.
void DCheckRegistrationNotActive(const std::string& unique_id,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
DCHECK_EQ(1u, data.size());
@@ -38,12 +41,14 @@ void DCheckRegistrationNotActive(const std::string& unique_id,
} // namespace
DeleteRegistrationTask::DeleteRegistrationTask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
int64_t service_worker_registration_id,
+ const url::Origin& origin,
const std::string& unique_id,
HandleBackgroundFetchErrorCallback callback)
- : DatabaseTask(data_manager),
+ : DatabaseTask(host),
service_worker_registration_id_(service_worker_registration_id),
+ origin_(origin),
unique_id_(unique_id),
callback_(std::move(callback)),
weak_factory_(this) {}
@@ -51,20 +56,34 @@ DeleteRegistrationTask::DeleteRegistrationTask(
DeleteRegistrationTask::~DeleteRegistrationTask() = default;
void DeleteRegistrationTask::Start() {
+ base::RepeatingClosure barrier_closure = base::BarrierClosure(
+ 2u, base::BindOnce(
+ [](base::WeakPtr<DeleteRegistrationTask> task) {
+ if (task)
+ task->FinishWithError(task->error_);
+ },
+ weak_factory_.GetWeakPtr()));
+
#if DCHECK_IS_ON()
// Get the registration |developer_id| to check it was deactivated.
service_worker_context()->GetRegistrationUserData(
service_worker_registration_id_, {RegistrationKey(unique_id_)},
base::BindOnce(&DeleteRegistrationTask::DidGetRegistration,
- weak_factory_.GetWeakPtr()));
+ weak_factory_.GetWeakPtr(), barrier_closure));
#else
- DidGetRegistration({}, SERVICE_WORKER_OK);
+ DidGetRegistration(barrier_closure, {}, blink::ServiceWorkerStatusCode::kOk);
#endif // DCHECK_IS_ON()
+
+ cache_manager()->DeleteCache(
+ origin_, CacheStorageOwner::kBackgroundFetch, unique_id_ /* cache_name */,
+ base::BindOnce(&DeleteRegistrationTask::DidDeleteCache,
+ weak_factory_.GetWeakPtr(), barrier_closure));
}
void DeleteRegistrationTask::DidGetRegistration(
+ base::OnceClosure done_closure,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
#if DCHECK_IS_ON()
if (ToDatabaseStatus(status) == DatabaseStatus::kOk) {
DCHECK_EQ(1u, data.size());
@@ -77,35 +96,55 @@ void DeleteRegistrationTask::DidGetRegistration(
metadata_proto.registration().developer_id())},
base::BindOnce(&DCheckRegistrationNotActive, unique_id_));
} else {
- NOTREACHED()
- << "Database is corrupt"; // TODO(crbug.com/780027): Nuke it.
+ // Service worker database has been corrupted. Abandon all fetches.
+ error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ AbandonFetches(service_worker_registration_id_);
+ std::move(done_closure).Run();
}
} else {
// TODO(crbug.com/780025): Log failure to UMA.
}
#endif // DCHECK_IS_ON()
+ std::vector<std::string> deletion_key_prefixes{
+ RegistrationKey(unique_id_), TitleKey(unique_id_),
+ PendingRequestKeyPrefix(unique_id_), ActiveRequestKeyPrefix(unique_id_),
+ CompletedRequestKeyPrefix(unique_id_)};
+
service_worker_context()->ClearRegistrationUserDataByKeyPrefixes(
- service_worker_registration_id_,
- {RegistrationKey(unique_id_), TitleKey(unique_id_)},
+ service_worker_registration_id_, std::move(deletion_key_prefixes),
base::BindOnce(&DeleteRegistrationTask::DidDeleteRegistration,
- weak_factory_.GetWeakPtr()));
+ weak_factory_.GetWeakPtr(), std::move(done_closure)));
}
void DeleteRegistrationTask::DidDeleteRegistration(
- ServiceWorkerStatusCode status) {
+ base::OnceClosure done_closure,
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
case DatabaseStatus::kNotFound:
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::NONE);
- Finished(); // Destroys |this|.
- return;
+ break;
case DatabaseStatus::kFailed:
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR);
- Finished(); // Destroys |this|.
- return;
+ error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ break;
}
+ std::move(done_closure).Run();
+}
+
+void DeleteRegistrationTask::DidDeleteCache(
+ base::OnceClosure done_closure,
+ blink::mojom::CacheStorageError error) {
+ if (error != blink::mojom::CacheStorageError::kSuccess &&
+ error != blink::mojom::CacheStorageError::kErrorNotFound) {
+ error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ }
+ std::move(done_closure).Run();
+}
+
+void DeleteRegistrationTask::FinishWithError(
+ blink::mojom::BackgroundFetchError error) {
+ std::move(callback_).Run(error);
+ Finished(); // Destroys |this|.
}
} // namespace background_fetch
diff --git a/chromium/content/browser/background_fetch/storage/delete_registration_task.h b/chromium/content/browser/background_fetch/storage/delete_registration_task.h
index 4ac2bb5da35..b25a7d19955 100644
--- a/chromium/content/browser/background_fetch/storage/delete_registration_task.h
+++ b/chromium/content/browser/background_fetch/storage/delete_registration_task.h
@@ -9,7 +9,9 @@
#include <vector>
#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
+#include "url/origin.h"
namespace content {
@@ -18,8 +20,9 @@ namespace background_fetch {
// Deletes Background Fetch registration entries from the database.
class DeleteRegistrationTask : public background_fetch::DatabaseTask {
public:
- DeleteRegistrationTask(BackgroundFetchDataManager* data_manager,
+ DeleteRegistrationTask(DatabaseTaskHost* host,
int64_t service_worker_registration_id,
+ const url::Origin& origin,
const std::string& unique_id,
HandleBackgroundFetchErrorCallback callback);
@@ -28,15 +31,27 @@ class DeleteRegistrationTask : public background_fetch::DatabaseTask {
void Start() override;
private:
- void DidGetRegistration(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ void DidGetRegistration(base::OnceClosure done_closure,
+ const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status);
- void DidDeleteRegistration(ServiceWorkerStatusCode status);
+ void DidDeleteRegistration(base::OnceClosure done_closure,
+ blink::ServiceWorkerStatusCode status);
+
+ void DidDeleteCache(base::OnceClosure done_closure,
+ blink::mojom::CacheStorageError error);
+
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
int64_t service_worker_registration_id_;
+ url::Origin origin_;
std::string unique_id_;
HandleBackgroundFetchErrorCallback callback_;
+ // The error to report once all async work is completed.
+ blink::mojom::BackgroundFetchError error_ =
+ blink::mojom::BackgroundFetchError::NONE;
+
base::WeakPtrFactory<DeleteRegistrationTask> weak_factory_; // Keep as last.
DISALLOW_COPY_AND_ASSIGN(DeleteRegistrationTask);
diff --git a/chromium/content/browser/background_fetch/storage/get_developer_ids_task.cc b/chromium/content/browser/background_fetch/storage/get_developer_ids_task.cc
index 03b9c849ee6..1f170218d83 100644
--- a/chromium/content/browser/background_fetch/storage/get_developer_ids_task.cc
+++ b/chromium/content/browser/background_fetch/storage/get_developer_ids_task.cc
@@ -14,11 +14,11 @@ namespace content {
namespace background_fetch {
GetDeveloperIdsTask::GetDeveloperIdsTask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
int64_t service_worker_registration_id,
const url::Origin& origin,
blink::mojom::BackgroundFetchService::GetDeveloperIdsCallback callback)
- : DatabaseTask(data_manager),
+ : DatabaseTask(host),
service_worker_registration_id_(service_worker_registration_id),
origin_(origin),
callback_(std::move(callback)),
@@ -35,26 +35,27 @@ void GetDeveloperIdsTask::Start() {
void GetDeveloperIdsTask::DidGetUniqueIds(
const base::flat_map<std::string, std::string>& data_map,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kNotFound:
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::NONE,
- {} /* No results */);
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
break;
case DatabaseStatus::kOk: {
- auto ids = std::vector<std::string>();
- ids.reserve(data_map.size());
+ developer_ids_.reserve(data_map.size());
for (const auto& pair : data_map)
- ids.push_back(pair.first);
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::NONE, ids);
+ developer_ids_.push_back(pair.first);
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
break;
}
case DatabaseStatus::kFailed:
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR,
- {} /* No results */);
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
break;
}
+}
+
+void GetDeveloperIdsTask::FinishWithError(
+ blink::mojom::BackgroundFetchError error) {
+ std::move(callback_).Run(error, std::move(developer_ids_));
Finished(); // Destroys |this|.
}
diff --git a/chromium/content/browser/background_fetch/storage/get_developer_ids_task.h b/chromium/content/browser/background_fetch/storage/get_developer_ids_task.h
index b205c712794..e9db0880fcc 100644
--- a/chromium/content/browser/background_fetch/storage/get_developer_ids_task.h
+++ b/chromium/content/browser/background_fetch/storage/get_developer_ids_task.h
@@ -11,7 +11,7 @@
#include "base/callback_forward.h"
#include "base/containers/flat_map.h"
#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
#include "url/origin.h"
@@ -24,7 +24,7 @@ namespace background_fetch {
class GetDeveloperIdsTask : public DatabaseTask {
public:
GetDeveloperIdsTask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
int64_t service_worker_registration_id,
const url::Origin& origin,
blink::mojom::BackgroundFetchService::GetDeveloperIdsCallback callback);
@@ -36,13 +36,17 @@ class GetDeveloperIdsTask : public DatabaseTask {
private:
void DidGetUniqueIds(const base::flat_map<std::string, std::string>& data_map,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
+
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
int64_t service_worker_registration_id_;
url::Origin origin_;
blink::mojom::BackgroundFetchService::GetDeveloperIdsCallback callback_;
+ std::vector<std::string> developer_ids_;
+
base::WeakPtrFactory<GetDeveloperIdsTask> weak_factory_; // Keep as last.
DISALLOW_COPY_AND_ASSIGN(GetDeveloperIdsTask);
diff --git a/chromium/content/browser/background_fetch/storage/get_initialization_data_task.cc b/chromium/content/browser/background_fetch/storage/get_initialization_data_task.cc
new file mode 100644
index 00000000000..10db38fcd96
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/get_initialization_data_task.cc
@@ -0,0 +1,536 @@
+// Copyright 2018 The Chromium Authors. All rights 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_fetch/storage/get_initialization_data_task.h"
+
+#include "base/barrier_closure.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
+#include "content/browser/background_fetch/background_fetch.pb.h"
+#include "content/browser/background_fetch/background_fetch_data_manager.h"
+#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/background_fetch/storage/mark_registration_for_deletion_task.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
+#include "ui/gfx/image/image.h"
+#include "url/origin.h"
+
+namespace content {
+
+namespace background_fetch {
+
+namespace {
+
+// Base class with all the common implementation for the SubTasks
+// needed in this file.
+class InitializationSubTask : public DatabaseTask {
+ public:
+ // Holds data used by all SubTasks.
+ struct SubTaskInit {
+ SubTaskInit() = delete;
+ ~SubTaskInit() = default;
+
+ // Service Worker Database metadata.
+ int64_t service_worker_registration_id;
+ std::string unique_id;
+
+ // The results to report.
+ BackgroundFetchInitializationData* initialization_data;
+ };
+
+ InitializationSubTask(DatabaseTaskHost* host,
+ const SubTaskInit& sub_task_init,
+ base::OnceClosure done_closure)
+ : DatabaseTask(host),
+ sub_task_init_(sub_task_init),
+ done_closure_(std::move(done_closure)) {
+ DCHECK(sub_task_init_.initialization_data);
+ }
+
+ ~InitializationSubTask() override = default;
+
+ protected:
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override {
+ if (error != blink::mojom::BackgroundFetchError::NONE)
+ sub_task_init_.initialization_data->error = error;
+ std::move(done_closure_).Run();
+ Finished(); // Destroys |this|.
+ }
+
+ SubTaskInit& sub_task_init() { return sub_task_init_; }
+
+ private:
+ SubTaskInit sub_task_init_;
+ base::OnceClosure done_closure_;
+
+ DISALLOW_COPY_AND_ASSIGN(InitializationSubTask);
+};
+
+// Fills the BackgroundFetchInitializationData with the most recent UI title.
+class GetTitleTask : public InitializationSubTask {
+ public:
+ GetTitleTask(DatabaseTaskHost* host,
+ const SubTaskInit& sub_task_init,
+ base::OnceClosure done_closure)
+ : InitializationSubTask(host, sub_task_init, std::move(done_closure)),
+ weak_factory_(this) {}
+
+ ~GetTitleTask() override = default;
+
+ void Start() override {
+ service_worker_context()->GetRegistrationUserData(
+ sub_task_init().service_worker_registration_id,
+ {TitleKey(sub_task_init().unique_id)},
+ base::BindOnce(&GetTitleTask::DidGetTitle, weak_factory_.GetWeakPtr()));
+ }
+
+ private:
+ void DidGetTitle(const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kFailed:
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ case DatabaseStatus::kNotFound:
+ case DatabaseStatus::kOk:
+ break;
+ }
+
+ if (!data.empty())
+ sub_task_init().initialization_data->ui_title = data.front();
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+ }
+
+ base::WeakPtrFactory<GetTitleTask> weak_factory_; // Keep as last.
+};
+
+// Gets the number of completed fetches, the number of active fetches,
+// and deletes inconsistencies in state transitions.
+// 1. Get all completed requests.
+// 2. Delete matching active requests.
+// 3. Get active requests.
+// 4. Delete matching pending requests.
+class GetRequestsTask : public InitializationSubTask {
+ public:
+ GetRequestsTask(DatabaseTaskHost* host,
+ const SubTaskInit& sub_task_init,
+ base::OnceClosure done_closure)
+ : InitializationSubTask(host, sub_task_init, std::move(done_closure)),
+ weak_factory_(this) {}
+
+ ~GetRequestsTask() override = default;
+
+ void Start() override {
+ service_worker_context()->GetRegistrationUserDataByKeyPrefix(
+ sub_task_init().service_worker_registration_id,
+ CompletedRequestKeyPrefix(sub_task_init().unique_id),
+ base::BindOnce(&GetRequestsTask::DidGetCompletedRequests,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ private:
+ void DidGetCompletedRequests(const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kFailed:
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ case DatabaseStatus::kNotFound:
+ case DatabaseStatus::kOk:
+ break;
+ }
+
+ sub_task_init().initialization_data->num_completed_requests = data.size();
+
+ std::vector<std::string> active_requests_to_delete;
+ active_requests_to_delete.reserve(data.size());
+ for (const std::string& serialized_completed_request : data) {
+ proto::BackgroundFetchCompletedRequest completed_request;
+ if (!completed_request.ParseFromString(serialized_completed_request) ||
+ sub_task_init().unique_id != completed_request.unique_id()) {
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ }
+
+ active_requests_to_delete.push_back(ActiveRequestKey(
+ completed_request.unique_id(), completed_request.request_index()));
+ }
+
+ if (active_requests_to_delete.empty()) {
+ DidClearActiveRequests(blink::ServiceWorkerStatusCode::kOk);
+ return;
+ }
+
+ service_worker_context()->ClearRegistrationUserData(
+ sub_task_init().service_worker_registration_id,
+ std::move(active_requests_to_delete),
+ base::BindOnce(&GetRequestsTask::DidClearActiveRequests,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ void DidClearActiveRequests(blink::ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kFailed:
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ case DatabaseStatus::kNotFound:
+ case DatabaseStatus::kOk:
+ break;
+ }
+
+ service_worker_context()->GetRegistrationUserDataByKeyPrefix(
+ sub_task_init().service_worker_registration_id,
+ ActiveRequestKeyPrefix(sub_task_init().unique_id),
+ base::BindOnce(&GetRequestsTask::DidGetRemainingActiveRequests,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ void DidGetRemainingActiveRequests(const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kFailed:
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ case DatabaseStatus::kNotFound:
+ case DatabaseStatus::kOk:
+ break;
+ }
+
+ std::vector<std::string> pending_requests_to_delete;
+ pending_requests_to_delete.reserve(data.size());
+ for (const std::string& serialized_active_request : data) {
+ proto::BackgroundFetchActiveRequest active_request;
+ if (!active_request.ParseFromString(serialized_active_request)) {
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ }
+ DCHECK_EQ(sub_task_init().unique_id, active_request.unique_id());
+ sub_task_init().initialization_data->active_fetch_guids.push_back(
+ active_request.download_guid());
+ pending_requests_to_delete.push_back(PendingRequestKey(
+ active_request.unique_id(), active_request.request_index()));
+ }
+
+ if (pending_requests_to_delete.empty()) {
+ DidClearPendingRequests(blink::ServiceWorkerStatusCode::kOk);
+ return;
+ }
+
+ service_worker_context()->ClearRegistrationUserData(
+ sub_task_init().service_worker_registration_id,
+ std::move(pending_requests_to_delete),
+ base::BindOnce(&GetRequestsTask::DidClearPendingRequests,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ void DidClearPendingRequests(blink::ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kFailed:
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ case DatabaseStatus::kNotFound:
+ case DatabaseStatus::kOk:
+ break;
+ }
+
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+ }
+
+ base::WeakPtrFactory<GetRequestsTask> weak_factory_; // Keep as last.
+
+ DISALLOW_COPY_AND_ASSIGN(GetRequestsTask);
+};
+
+// Deserializes the icon and creates an SkBitmap from it.
+class DeserializeIconTask : public InitializationSubTask {
+ public:
+ DeserializeIconTask(DatabaseTaskHost* host,
+ const SubTaskInit& sub_task_init,
+ base::OnceClosure done_closure,
+ std::string* serialized_icon)
+ : InitializationSubTask(host, sub_task_init, std::move(done_closure)),
+ serialized_icon_(serialized_icon),
+ weak_factory_(this) {}
+
+ ~DeserializeIconTask() override = default;
+
+ void Start() override {
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE,
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+ base::TaskPriority::BACKGROUND},
+ base::BindOnce(&DeserializeIcon, std::move(serialized_icon_)),
+ base::BindOnce(&DeserializeIconTask::StoreIcon,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ private:
+ static SkBitmap DeserializeIcon(
+ std::unique_ptr<std::string> serialized_icon) {
+ return gfx::Image::CreateFrom1xPNGBytes(
+ reinterpret_cast<const unsigned char*>(serialized_icon->c_str()),
+ serialized_icon->size())
+ .AsBitmap();
+ }
+
+ void StoreIcon(SkBitmap icon) {
+ sub_task_init().initialization_data->icon = std::move(icon);
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+ }
+
+ std::unique_ptr<std::string> serialized_icon_;
+
+ base::WeakPtrFactory<DeserializeIconTask> weak_factory_; // Keep as last.
+};
+
+// Fills the BackgroundFetchInitializationData with all the relevant information
+// stored in the BackgroundFetchMetadata proto.
+class FillFromMetadataTask : public InitializationSubTask {
+ public:
+ FillFromMetadataTask(DatabaseTaskHost* host,
+ const SubTaskInit& sub_task_init,
+ base::OnceClosure done_closure)
+ : InitializationSubTask(host, sub_task_init, std::move(done_closure)),
+ weak_factory_(this) {}
+
+ ~FillFromMetadataTask() override = default;
+
+ void Start() override {
+ service_worker_context()->GetRegistrationUserDataByKeyPrefix(
+ sub_task_init().service_worker_registration_id,
+ {RegistrationKey(sub_task_init().unique_id)},
+ base::BindOnce(&FillFromMetadataTask::DidGetMetadata,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ private:
+ void DidGetMetadata(const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kFailed:
+ case DatabaseStatus::kNotFound:
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ case DatabaseStatus::kOk:
+ break;
+ }
+
+ if (data.size() != 1u) {
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ }
+
+ proto::BackgroundFetchMetadata metadata;
+ if (!metadata.ParseFromString(data[0])) {
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ }
+
+ if (sub_task_init().unique_id != metadata.registration().unique_id()) {
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ }
+
+ // Fill BackgroundFetchRegistrationId.
+ sub_task_init().initialization_data->registration_id =
+ BackgroundFetchRegistrationId(
+ sub_task_init().service_worker_registration_id,
+ url::Origin::Create(GURL(metadata.origin())),
+ metadata.registration().developer_id(),
+ metadata.registration().unique_id());
+
+ // Fill BackgroundFetchRegistration.
+ auto& registration = sub_task_init().initialization_data->registration;
+ // TODO(crbug.com/853874): Unify conversion logic.
+ registration.developer_id = metadata.registration().developer_id();
+ registration.unique_id = metadata.registration().unique_id();
+ registration.upload_total = metadata.registration().upload_total();
+ registration.uploaded = metadata.registration().uploaded();
+ registration.download_total = metadata.registration().download_total();
+ registration.downloaded = metadata.registration().downloaded();
+
+ // Total number of requests.
+ sub_task_init().initialization_data->num_requests = metadata.num_fetches();
+
+ // Fill BackgroundFetchOptions.
+ auto& options = sub_task_init().initialization_data->options;
+ options.title = metadata.options().title();
+ options.download_total = metadata.options().download_total();
+ options.icons.reserve(metadata.options().icons_size());
+ for (const auto& icon : metadata.options().icons()) {
+ blink::Manifest::ImageResource ir;
+ ir.src = GURL(icon.src());
+ ir.type = base::ASCIIToUTF16(icon.type());
+
+ ir.sizes.reserve(icon.sizes_size());
+ for (const auto& size : icon.sizes())
+ ir.sizes.emplace_back(size.width(), size.height());
+
+ ir.purpose.reserve(icon.purpose_size());
+ for (auto purpose : icon.purpose()) {
+ switch (purpose) {
+ case proto::BackgroundFetchOptions_ImageResource_Purpose_ANY:
+ ir.purpose.push_back(blink::Manifest::ImageResource::Purpose::ANY);
+ break;
+ case proto::BackgroundFetchOptions_ImageResource_Purpose_BADGE:
+ ir.purpose.push_back(
+ blink::Manifest::ImageResource::Purpose::BADGE);
+ break;
+ }
+ }
+ }
+
+ if (!metadata.icon().empty()) {
+ // Start an icon deserialization SubTask on another thread, then finish.
+ AddSubTask(std::make_unique<DeserializeIconTask>(
+ this, sub_task_init(),
+ base::BindOnce(&FillFromMetadataTask::FinishWithError,
+ weak_factory_.GetWeakPtr(),
+ blink::mojom::BackgroundFetchError::NONE),
+ metadata.release_icon()));
+ } else {
+ // Immediately finish.
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+ }
+ }
+
+ base::WeakPtrFactory<FillFromMetadataTask> weak_factory_; // Keep as last.
+
+ DISALLOW_COPY_AND_ASSIGN(FillFromMetadataTask);
+};
+
+// Asynchronously calls the SubTasks required to collect all the information for
+// the BackgroundFetchInitializationData.
+class FillBackgroundFetchInitializationDataTask : public InitializationSubTask {
+ public:
+ FillBackgroundFetchInitializationDataTask(DatabaseTaskHost* host,
+ const SubTaskInit& sub_task_init,
+ base::OnceClosure done_closure)
+ : InitializationSubTask(host, sub_task_init, std::move(done_closure)),
+ weak_factory_(this) {}
+
+ ~FillBackgroundFetchInitializationDataTask() override = default;
+
+ void Start() override {
+ // We need 3 queries to get the initialization data. These are wrapped
+ // in a BarrierClosure to avoid querying them serially.
+ // 1. Metadata (+ icon deserialization)
+ // 2. Request statuses and state sanitization
+ // 3. UI Title
+ base::RepeatingClosure barrier_closure = base::BarrierClosure(
+ 3u,
+ base::BindOnce(
+ [](base::WeakPtr<FillBackgroundFetchInitializationDataTask> task) {
+ if (task)
+ task->FinishWithError(
+ task->sub_task_init().initialization_data->error);
+ },
+ weak_factory_.GetWeakPtr()));
+ AddSubTask(std::make_unique<FillFromMetadataTask>(this, sub_task_init(),
+ barrier_closure));
+ AddSubTask(std::make_unique<GetRequestsTask>(this, sub_task_init(),
+ barrier_closure));
+ AddSubTask(
+ std::make_unique<GetTitleTask>(this, sub_task_init(), barrier_closure));
+ }
+
+ private:
+ base::WeakPtrFactory<FillBackgroundFetchInitializationDataTask>
+ weak_factory_; // Keep as last.
+
+ DISALLOW_COPY_AND_ASSIGN(FillBackgroundFetchInitializationDataTask);
+};
+
+} // namespace
+
+BackgroundFetchInitializationData::BackgroundFetchInitializationData() =
+ default;
+
+BackgroundFetchInitializationData::BackgroundFetchInitializationData(
+ BackgroundFetchInitializationData&&) = default;
+
+BackgroundFetchInitializationData::~BackgroundFetchInitializationData() =
+ default;
+
+GetInitializationDataTask::GetInitializationDataTask(
+ DatabaseTaskHost* host,
+ GetInitializationDataCallback callback)
+ : DatabaseTask(host), callback_(std::move(callback)), weak_factory_(this) {}
+
+GetInitializationDataTask::~GetInitializationDataTask() = default;
+
+void GetInitializationDataTask::Start() {
+ service_worker_context()->GetUserDataForAllRegistrationsByKeyPrefix(
+ kActiveRegistrationUniqueIdKeyPrefix,
+ base::BindOnce(&GetInitializationDataTask::DidGetRegistrations,
+ weak_factory_.GetWeakPtr()));
+}
+
+void GetInitializationDataTask::DidGetRegistrations(
+ const std::vector<std::pair<int64_t, std::string>>& user_data,
+ blink::ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kFailed:
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ case DatabaseStatus::kNotFound:
+ case DatabaseStatus::kOk:
+ break;
+ }
+
+ if (user_data.empty()) {
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+ return;
+ }
+
+ base::RepeatingClosure barrier_closure = base::BarrierClosure(
+ user_data.size(),
+ base::BindOnce(&GetInitializationDataTask::FinishWithError,
+ weak_factory_.GetWeakPtr(),
+ blink::mojom::BackgroundFetchError::NONE));
+
+ for (const auto& ud : user_data) {
+ auto insertion_result = initialization_data_map_.emplace(
+ ud.second, BackgroundFetchInitializationData());
+ DCHECK(insertion_result.second); // Check unique_id is in fact unique.
+
+ AddSubTask(std::make_unique<FillBackgroundFetchInitializationDataTask>(
+ this,
+ InitializationSubTask::SubTaskInit{
+ ud.first, ud.second,
+ &insertion_result.first->second /* initialization_data */},
+ barrier_closure));
+ }
+}
+void GetInitializationDataTask::FinishWithError(
+ blink::mojom::BackgroundFetchError error) {
+ std::vector<BackgroundFetchInitializationData> results;
+ results.reserve(initialization_data_map_.size());
+
+ for (auto& data : initialization_data_map_) {
+ if (data.second.error == blink::mojom::BackgroundFetchError::NONE) {
+ // If we successfully extracted all the data, move it to the
+ // initialization vector to be handed over to create a controller.
+ results.emplace_back(std::move(data.second));
+ } else if (!data.second.registration_id.developer_id().empty()) {
+ // There was an error in getting the initialization data
+ // (e.g. corrupt data, SWDB error). If the Developer ID of the fetch
+ // is available, mark the registration for deletion.
+ // Note that the Developer ID isn't available if the metadata extraction
+ // failed.
+ // TODO(crbug.com/865388): Getting the Developer ID should be possible
+ // since it is part of the key for when we got the Unique ID.
+ AddDatabaseTask(std::make_unique<MarkRegistrationForDeletionTask>(
+ data_manager(), data.second.registration_id, base::DoNothing()));
+ }
+ }
+
+ std::move(callback_).Run(error, std::move(results));
+ Finished(); // Destroys |this|.
+}
+
+} // namespace background_fetch
+
+} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/get_initialization_data_task.h b/chromium/content/browser/background_fetch/storage/get_initialization_data_task.h
new file mode 100644
index 00000000000..7946ba0a1f6
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/get_initialization_data_task.h
@@ -0,0 +1,100 @@
+// Copyright 2018 The Chromium Authors. All 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_FETCH_STORAGE_GET_INITIALIZATION_DATA_TASK_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_INITIALIZATION_DATA_TASK_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "content/browser/background_fetch/background_fetch_registration_id.h"
+#include "content/browser/background_fetch/storage/database_task.h"
+#include "content/browser/service_worker/service_worker_info.h"
+#include "content/common/background_fetch/background_fetch_types.h"
+#include "content/common/content_export.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace content {
+
+namespace background_fetch {
+
+// All the information needed to create a JobController and resume the fetch
+// after start-up.
+struct CONTENT_EXPORT BackgroundFetchInitializationData {
+ BackgroundFetchInitializationData();
+ BackgroundFetchInitializationData(BackgroundFetchInitializationData&&);
+ ~BackgroundFetchInitializationData();
+
+ BackgroundFetchRegistrationId registration_id;
+ BackgroundFetchOptions options;
+ SkBitmap icon;
+ BackgroundFetchRegistration registration;
+ size_t num_requests;
+ size_t num_completed_requests;
+ std::vector<std::string> active_fetch_guids;
+ std::string ui_title;
+
+ // The error, if any, when getting the registration data.
+ blink::mojom::BackgroundFetchError error =
+ blink::mojom::BackgroundFetchError::NONE;
+
+ DISALLOW_COPY_AND_ASSIGN(BackgroundFetchInitializationData);
+};
+
+using GetInitializationDataCallback =
+ base::OnceCallback<void(blink::mojom::BackgroundFetchError,
+ std::vector<BackgroundFetchInitializationData>)>;
+
+// Gets all the data needed to resume fetches. The task starts by getting
+// all the <ServiceWorker Registration ID, Background Fetch Unique ID>
+// pairs available.
+// * TODO(crbug.com/853060): Consider persisting which SWIDs contain BGF
+// info.
+// Then for every Background Fetch Unique ID the required information is
+// queried from the ServiceWorker Database to fill an instance of
+// BackgroundFetchInitializationData.
+//
+// Note: All of this must run in one DatabaseTask, to ensure the
+// BackgroundFetchContext is properly initialized with JobControllers before
+// running any additional DatabaseTasks and reaching an incorrect state.
+class GetInitializationDataTask : public DatabaseTask {
+ public:
+ using InitializationDataMap =
+ std::map<std::string, BackgroundFetchInitializationData>;
+
+ GetInitializationDataTask(DatabaseTaskHost* host,
+ GetInitializationDataCallback callback);
+
+ ~GetInitializationDataTask() override;
+
+ // DatabaseTask implementation:
+ void Start() override;
+
+ private:
+ void DidGetRegistrations(
+ const std::vector<std::pair<int64_t, std::string>>& user_data,
+ blink::ServiceWorkerStatusCode status);
+
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+
+ GetInitializationDataCallback callback_;
+
+ // Map from the unique_id to the initialization data.
+ InitializationDataMap initialization_data_map_;
+
+ base::WeakPtrFactory<GetInitializationDataTask>
+ weak_factory_; // Keep as last.
+
+ DISALLOW_COPY_AND_ASSIGN(GetInitializationDataTask);
+};
+
+} // namespace background_fetch
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_INITIALIZATION_DATA_TASK_H_
diff --git a/chromium/content/browser/background_fetch/storage/get_metadata_task.cc b/chromium/content/browser/background_fetch/storage/get_metadata_task.cc
index e80738b9b2e..f6888b1cd44 100644
--- a/chromium/content/browser/background_fetch/storage/get_metadata_task.cc
+++ b/chromium/content/browser/background_fetch/storage/get_metadata_task.cc
@@ -14,12 +14,12 @@ namespace content {
namespace background_fetch {
-GetMetadataTask::GetMetadataTask(BackgroundFetchDataManager* data_manager,
+GetMetadataTask::GetMetadataTask(DatabaseTaskHost* host,
int64_t service_worker_registration_id,
const url::Origin& origin,
const std::string& developer_id,
GetMetadataCallback callback)
- : DatabaseTask(data_manager),
+ : DatabaseTask(host),
service_worker_registration_id_(service_worker_registration_id),
origin_(origin),
developer_id_(developer_id),
@@ -37,12 +37,10 @@ void GetMetadataTask::Start() {
}
void GetMetadataTask::DidGetUniqueId(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kNotFound:
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::INVALID_ID,
- nullptr /* metadata */);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::INVALID_ID);
return;
case DatabaseStatus::kOk:
DCHECK_EQ(1u, data.size());
@@ -52,34 +50,25 @@ void GetMetadataTask::DidGetUniqueId(const std::vector<std::string>& data,
weak_factory_.GetWeakPtr()));
return;
case DatabaseStatus::kFailed:
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR,
- nullptr /* metadata */);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
}
void GetMetadataTask::DidGetMetadata(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kNotFound:
// The database is corrupt as there's no registration data despite there
// being an active developer_id pointing to it.
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR,
- nullptr /* metadata */);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
case DatabaseStatus::kOk:
DCHECK_EQ(1u, data.size());
ProcessMetadata(data[0]);
return;
case DatabaseStatus::kFailed:
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR,
- nullptr /* metadata */);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
}
@@ -87,9 +76,7 @@ void GetMetadataTask::DidGetMetadata(const std::vector<std::string>& data,
void GetMetadataTask::ProcessMetadata(const std::string& metadata) {
metadata_proto_ = std::make_unique<proto::BackgroundFetchMetadata>();
if (!metadata_proto_->ParseFromString(metadata)) {
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR,
- nullptr /* metadata */);
- Finished();
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
@@ -97,14 +84,20 @@ void GetMetadataTask::ProcessMetadata(const std::string& metadata) {
if (registration_proto.developer_id() != developer_id_ ||
!origin_.IsSameOriginWith(
url::Origin::Create(GURL(metadata_proto_->origin())))) {
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR,
- nullptr /* metadata */);
- Finished();
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::NONE,
- std::move(metadata_proto_));
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+}
+
+void GetMetadataTask::FinishWithError(
+ blink::mojom::BackgroundFetchError error) {
+ // We want to return a nullptr instead of an empty proto in case of an error.
+ if (error != blink::mojom::BackgroundFetchError::NONE)
+ metadata_proto_.reset();
+
+ std::move(callback_).Run(error, std::move(metadata_proto_));
Finished();
}
diff --git a/chromium/content/browser/background_fetch/storage/get_metadata_task.h b/chromium/content/browser/background_fetch/storage/get_metadata_task.h
index bf51554aa3d..68cb068ade6 100644
--- a/chromium/content/browser/background_fetch/storage/get_metadata_task.h
+++ b/chromium/content/browser/background_fetch/storage/get_metadata_task.h
@@ -12,7 +12,7 @@
#include "base/callback_forward.h"
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/origin.h"
namespace content {
@@ -26,7 +26,7 @@ class GetMetadataTask : public DatabaseTask {
base::OnceCallback<void(blink::mojom::BackgroundFetchError,
std::unique_ptr<proto::BackgroundFetchMetadata>)>;
- GetMetadataTask(BackgroundFetchDataManager* data_manager,
+ GetMetadataTask(DatabaseTaskHost* host,
int64_t service_worker_registration_id,
const url::Origin& origin,
const std::string& developer_id,
@@ -39,13 +39,15 @@ class GetMetadataTask : public DatabaseTask {
private:
void DidGetUniqueId(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void DidGetMetadata(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void ProcessMetadata(const std::string& metadata);
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
+
int64_t service_worker_registration_id_;
url::Origin origin_;
std::string developer_id_;
diff --git a/chromium/content/browser/background_fetch/storage/get_num_requests_task.cc b/chromium/content/browser/background_fetch/storage/get_num_requests_task.cc
deleted file mode 100644
index 6e4fbf2f566..00000000000
--- a/chromium/content/browser/background_fetch/storage/get_num_requests_task.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights 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_fetch/storage/get_num_requests_task.h"
-
-#include "content/browser/background_fetch/background_fetch.pb.h"
-#include "content/browser/background_fetch/storage/database_helpers.h"
-#include "content/browser/background_fetch/storage/get_metadata_task.h"
-#include "content/browser/service_worker/service_worker_context_wrapper.h"
-
-namespace content {
-
-namespace background_fetch {
-
-namespace {
-
-void HandleGetMetadataCallback(
- GetNumRequestsTask::NumRequestsCallback callback,
- blink::mojom::BackgroundFetchError error,
- std::unique_ptr<proto::BackgroundFetchMetadata> metadata) {
- if (error != blink::mojom::BackgroundFetchError::NONE) {
- std::move(callback).Run(0u);
- return;
- }
-
- DCHECK(metadata);
- std::move(callback).Run(metadata->num_fetches());
-}
-
-} // namespace
-
-GetNumRequestsTask::GetNumRequestsTask(
- BackgroundFetchDataManager* data_manager,
- const BackgroundFetchRegistrationId& registration_id,
- RequestType type,
- NumRequestsCallback callback)
- : DatabaseTask(data_manager),
- registration_id_(registration_id),
- type_(type),
- callback_(std::move(callback)),
- weak_factory_(this) {}
-
-GetNumRequestsTask::~GetNumRequestsTask() = default;
-
-void GetNumRequestsTask::Start() {
- switch (type_) {
- case RequestType::kAny:
- GetMetadata();
- return;
- case RequestType::kPending:
- GetRequests(PendingRequestKeyPrefix(registration_id_.unique_id()));
- return;
- case RequestType::kActive:
- GetRequests(ActiveRequestKeyPrefix(registration_id_.unique_id()));
- return;
- case RequestType::kCompleted:
- GetRequests(CompletedRequestKeyPrefix(registration_id_.unique_id()));
- return;
- }
- NOTREACHED();
-}
-
-void GetNumRequestsTask::GetMetadata() {
- AddDatabaseTask(std::make_unique<GetMetadataTask>(
- data_manager(), registration_id_.service_worker_registration_id(),
- registration_id_.origin(), registration_id_.developer_id(),
- base::BindOnce(&HandleGetMetadataCallback, std::move(callback_))));
- Finished(); // Destroys |this|.
-}
-
-void GetNumRequestsTask::GetRequests(const std::string& key_prefix) {
- service_worker_context()->GetRegistrationUserDataByKeyPrefix(
- registration_id_.service_worker_registration_id(), key_prefix,
- base::BindOnce(&GetNumRequestsTask::DidGetRequests,
- weak_factory_.GetWeakPtr()));
-}
-
-void GetNumRequestsTask::DidGetRequests(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
- DCHECK_EQ(ToDatabaseStatus(status), DatabaseStatus::kOk);
- std::move(callback_).Run(data.size());
- Finished(); // Destroys |this|.
-}
-
-} // namespace background_fetch
-
-} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/get_num_requests_task.h b/chromium/content/browser/background_fetch/storage/get_num_requests_task.h
deleted file mode 100644
index fe4857b4b91..00000000000
--- a/chromium/content/browser/background_fetch/storage/get_num_requests_task.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2018 The Chromium Authors. All 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_FETCH_STORAGE_GET_NUM_REQUESTS_TASK_H_
-#define CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_NUM_REQUESTS_TASK_H_
-
-#include "base/callback_forward.h"
-#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/common/content_export.h"
-#include "content/common/service_worker/service_worker_status_code.h"
-
-namespace content {
-
-namespace background_fetch {
-
-enum class RequestType { kAny, kPending, kActive, kCompleted };
-
-// Gets the number of requests per registration of the given type.
-class CONTENT_EXPORT GetNumRequestsTask : public DatabaseTask {
- public:
- using NumRequestsCallback = base::OnceCallback<void(size_t)>;
-
- GetNumRequestsTask(BackgroundFetchDataManager* data_manager,
- const BackgroundFetchRegistrationId& registration_id,
- RequestType type,
- NumRequestsCallback callback);
-
- ~GetNumRequestsTask() override;
-
- // DatabaseTask implementation:
- void Start() override;
-
- private:
- void GetMetadata();
- void GetRequests(const std::string& key_prefix);
- void DidGetRequests(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
-
- BackgroundFetchRegistrationId registration_id_;
- RequestType type_;
- NumRequestsCallback callback_;
-
- base::WeakPtrFactory<GetNumRequestsTask> weak_factory_; // Keep as last.
-
- DISALLOW_COPY_AND_ASSIGN(GetNumRequestsTask);
-};
-
-} // namespace background_fetch
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_NUM_REQUESTS_TASK_H_
diff --git a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc
index 9ea3c390098..d74d797949a 100644
--- a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc
+++ b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc
@@ -5,8 +5,9 @@
#include "content/browser/background_fetch/storage/get_settled_fetches_task.h"
#include "base/barrier_closure.h"
-#include "content/browser/background_fetch/background_fetch.pb.h"
+#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
namespace content {
@@ -14,10 +15,10 @@ namespace content {
namespace background_fetch {
GetSettledFetchesTask::GetSettledFetchesTask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
BackgroundFetchRegistrationId registration_id,
SettledFetchesCallback callback)
- : DatabaseTask(data_manager),
+ : DatabaseTask(host),
registration_id_(registration_id),
settled_fetches_callback_(std::move(callback)),
weak_factory_(this) {}
@@ -25,80 +26,140 @@ GetSettledFetchesTask::GetSettledFetchesTask(
GetSettledFetchesTask::~GetSettledFetchesTask() = default;
void GetSettledFetchesTask::Start() {
+ base::RepeatingClosure barrier_closure = base::BarrierClosure(
+ 2u, base::BindOnce(&GetSettledFetchesTask::GetResponses,
+ weak_factory_.GetWeakPtr()));
+
+ cache_manager()->OpenCache(
+ registration_id_.origin(), CacheStorageOwner::kBackgroundFetch,
+ registration_id_.unique_id() /* cache_name */,
+ base::BindOnce(&GetSettledFetchesTask::DidOpenCache,
+ weak_factory_.GetWeakPtr(), barrier_closure));
+
service_worker_context()->GetRegistrationUserDataByKeyPrefix(
registration_id_.service_worker_registration_id(),
{CompletedRequestKeyPrefix(registration_id_.unique_id())},
base::BindOnce(&GetSettledFetchesTask::DidGetCompletedRequests,
- weak_factory_.GetWeakPtr()));
+ weak_factory_.GetWeakPtr(), barrier_closure));
+}
+
+void GetSettledFetchesTask::DidOpenCache(
+ base::OnceClosure done_closure,
+ CacheStorageCacheHandle handle,
+ blink::mojom::CacheStorageError error) {
+ if (error != blink::mojom::CacheStorageError::kSuccess) {
+ // TODO(crbug.com/780025): Log failures to UMA.
+ error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ } else {
+ DCHECK(handle.value());
+ handle_ = std::move(handle);
+ }
+ std::move(done_closure).Run();
}
void GetSettledFetchesTask::DidGetCompletedRequests(
+ base::OnceClosure done_closure,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
break;
// TODO(crbug.com/780025): Log failures to UMA.
case DatabaseStatus::kFailed:
- FinishTaskWithErrorCode(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR);
- return;
+ error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ break;
case DatabaseStatus::kNotFound:
background_fetch_succeeded_ = false;
- FinishTaskWithErrorCode(blink::mojom::BackgroundFetchError::INVALID_ID);
- return;
+ error_ = blink::mojom::BackgroundFetchError::INVALID_ID;
+ break;
}
- // Nothing failed yet so the default state is success.
- if (data.empty()) {
- FinishTaskWithErrorCode(blink::mojom::BackgroundFetchError::NONE);
+ completed_requests_.reserve(data.size());
+ for (const std::string& serialized_completed_request : data) {
+ completed_requests_.emplace_back();
+ if (!completed_requests_.back().ParseFromString(
+ serialized_completed_request)) {
+ // Service worker database has been corrupted. Abandon fetches.
+ error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ background_fetch_succeeded_ = false;
+ AbandonFetches(registration_id_.service_worker_registration_id());
+ break;
+ }
+ if (!completed_requests_.back().succeeded())
+ background_fetch_succeeded_ = false;
+ }
+ std::move(done_closure).Run();
+}
+
+void GetSettledFetchesTask::GetResponses() {
+ if (error_ != blink::mojom::BackgroundFetchError::NONE) {
+ FinishWithError(error_);
+ return;
+ }
+ if (completed_requests_.empty()) {
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
return;
}
base::RepeatingClosure barrier_closure = base::BarrierClosure(
- data.size(),
- base::BindOnce(&GetSettledFetchesTask::FinishTaskWithErrorCode,
+ completed_requests_.size(),
+ base::BindOnce(&GetSettledFetchesTask::FinishWithError,
weak_factory_.GetWeakPtr(),
blink::mojom::BackgroundFetchError::NONE));
- settled_fetches_.reserve(data.size());
- for (const std::string& serialized_completed_request : data) {
- proto::BackgroundFetchCompletedRequest completed_request;
- if (!completed_request.ParseFromString(serialized_completed_request)) {
- NOTREACHED()
- << "Database is corrupt"; // TODO(crbug.com/780027): Nuke it.
- }
-
- settled_fetches_.emplace_back(BackgroundFetchSettledFetch());
+ settled_fetches_.reserve(completed_requests_.size());
+ for (const auto& completed_request : completed_requests_) {
+ settled_fetches_.emplace_back();
settled_fetches_.back().request =
std::move(ServiceWorkerFetchRequest::ParseFromString(
completed_request.serialized_request()));
- if (!completed_request.succeeded()) {
- FillFailedResponse(&settled_fetches_.back().response, barrier_closure);
- continue;
- }
- FillSuccessfulResponse(&settled_fetches_.back().response, barrier_closure);
+ FillResponse(&settled_fetches_.back(), barrier_closure);
}
}
-void GetSettledFetchesTask::FillFailedResponse(
- ServiceWorkerResponse* response,
- const base::RepeatingClosure& callback) {
- DCHECK(response);
- background_fetch_succeeded_ = false;
- // TODO(rayankans): Fill failed response with error reports.
+void GetSettledFetchesTask::FillResponse(
+ BackgroundFetchSettledFetch* settled_fetch,
+ base::OnceClosure callback) {
+ DCHECK(settled_fetch);
+ DCHECK(handle_.value());
+
+ auto request =
+ std::make_unique<ServiceWorkerFetchRequest>(settled_fetch->request);
+
+ handle_.value()->Match(std::move(request), nullptr /* match_params */,
+ base::BindOnce(&GetSettledFetchesTask::DidMatchRequest,
+ weak_factory_.GetWeakPtr(),
+ settled_fetch, std::move(callback)));
+}
+
+void GetSettledFetchesTask::DidMatchRequest(
+ BackgroundFetchSettledFetch* settled_fetch,
+ base::OnceClosure callback,
+ blink::mojom::CacheStorageError error,
+ std::unique_ptr<ServiceWorkerResponse> cache_response) {
+ if (error != blink::mojom::CacheStorageError::kSuccess) {
+ DCHECK(settled_fetch);
+ FillUncachedResponse(settled_fetch, std::move(callback));
+ return;
+ }
+ settled_fetch->response = std::move(*cache_response);
std::move(callback).Run();
}
-void GetSettledFetchesTask::FillSuccessfulResponse(
- ServiceWorkerResponse* response,
- const base::RepeatingClosure& callback) {
- DCHECK(response);
- // TODO(rayankans): Get the response stored in Cache Storage.
+void GetSettledFetchesTask::FillUncachedResponse(
+ BackgroundFetchSettledFetch* settled_fetch,
+ base::OnceClosure callback) {
+ background_fetch_succeeded_ = false;
+
+ // TODO(rayankans): Fill unmatched response with error reports.
+ settled_fetch->response.response_type =
+ network::mojom::FetchResponseType::kError;
+ settled_fetch->response.url_list.push_back(settled_fetch->request.url);
+
std::move(callback).Run();
}
-void GetSettledFetchesTask::FinishTaskWithErrorCode(
+void GetSettledFetchesTask::FinishWithError(
blink::mojom::BackgroundFetchError error) {
std::move(settled_fetches_callback_)
.Run(error, background_fetch_succeeded_, std::move(settled_fetches_),
diff --git a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h
index 7fba53179fc..6830c21d924 100644
--- a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h
+++ b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h
@@ -6,9 +6,12 @@
#define CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_SETTLED_FETCHES_TASK_H_
#include "base/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
+#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
@@ -22,7 +25,7 @@ class GetSettledFetchesTask : public DatabaseTask {
std::vector<BackgroundFetchSettledFetch>,
std::vector<std::unique_ptr<storage::BlobDataHandle>>)>;
- GetSettledFetchesTask(BackgroundFetchDataManager* data_manager,
+ GetSettledFetchesTask(DatabaseTaskHost* host,
BackgroundFetchRegistrationId registration_id,
SettledFetchesCallback callback);
@@ -32,23 +35,42 @@ class GetSettledFetchesTask : public DatabaseTask {
void Start() override;
private:
- void DidGetCompletedRequests(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ void DidOpenCache(base::OnceClosure done_closure,
+ CacheStorageCacheHandle handle,
+ blink::mojom::CacheStorageError error);
- void FillFailedResponse(ServiceWorkerResponse* response,
- const base::RepeatingClosure& callback);
+ void DidGetCompletedRequests(base::OnceClosure done_closure,
+ const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status);
- void FillSuccessfulResponse(ServiceWorkerResponse* response,
- const base::RepeatingClosure& callback);
+ void GetResponses();
- void FinishTaskWithErrorCode(blink::mojom::BackgroundFetchError error);
+ void FillUncachedResponse(BackgroundFetchSettledFetch* settled_fetch,
+ base::OnceClosure callback);
+
+ void FillResponse(BackgroundFetchSettledFetch* settled_fetch,
+ base::OnceClosure callback);
+
+ void DidMatchRequest(BackgroundFetchSettledFetch* settled_fetch,
+ base::OnceClosure callback,
+ blink::mojom::CacheStorageError error,
+ std::unique_ptr<ServiceWorkerResponse> cache_response);
+
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
BackgroundFetchRegistrationId registration_id_;
SettledFetchesCallback settled_fetches_callback_;
+ // SettledFetchesCallback params.
std::vector<BackgroundFetchSettledFetch> settled_fetches_;
bool background_fetch_succeeded_ = true;
+ // Storage params.
+ CacheStorageCacheHandle handle_;
+ std::vector<proto::BackgroundFetchCompletedRequest> completed_requests_;
+ blink::mojom::BackgroundFetchError error_ =
+ blink::mojom::BackgroundFetchError::NONE;
+
base::WeakPtrFactory<GetSettledFetchesTask> weak_factory_; // Keep as last.
DISALLOW_COPY_AND_ASSIGN(GetSettledFetchesTask);
diff --git a/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc b/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
index 576d8fb64ab..1f12e1a190d 100644
--- a/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
+++ b/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
@@ -16,10 +16,10 @@ namespace content {
namespace background_fetch {
MarkRegistrationForDeletionTask::MarkRegistrationForDeletionTask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
HandleBackgroundFetchErrorCallback callback)
- : DatabaseTask(data_manager),
+ : DatabaseTask(host),
registration_id_(registration_id),
callback_(std::move(callback)),
weak_factory_(this) {}
@@ -39,18 +39,15 @@ void MarkRegistrationForDeletionTask::Start() {
void MarkRegistrationForDeletionTask::DidGetActiveUniqueId(
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
break;
case DatabaseStatus::kNotFound:
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::INVALID_ID);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::INVALID_ID);
return;
case DatabaseStatus::kFailed:
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
@@ -59,8 +56,7 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId(
// If the |unique_id| does not match, then the registration identified by
// |registration_id_.unique_id()| was already deactivated.
if (data[0] != registration_id_.unique_id()) {
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::INVALID_ID);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::INVALID_ID);
return;
}
@@ -77,20 +73,21 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId(
base::BindOnce(&MarkRegistrationForDeletionTask::DidDeactivate,
weak_factory_.GetWeakPtr()));
} else {
- NOTREACHED() << "Database is corrupt"; // TODO(crbug.com/780027): Nuke it.
+ // Service worker database has been corrupted. Abandon fetches.
+ AbandonFetches(registration_id_.service_worker_registration_id());
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
}
}
void MarkRegistrationForDeletionTask::DidDeactivate(
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
case DatabaseStatus::kNotFound:
break;
case DatabaseStatus::kFailed:
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
@@ -98,7 +95,12 @@ void MarkRegistrationForDeletionTask::DidDeactivate(
// |unique_id| as there may still be JavaScript references to it.
ref_counted_unique_ids().emplace(registration_id_.unique_id());
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::NONE);
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+}
+
+void MarkRegistrationForDeletionTask::FinishWithError(
+ blink::mojom::BackgroundFetchError error) {
+ std::move(callback_).Run(error);
Finished(); // Destroys |this|.
}
diff --git a/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.h b/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.h
index d43a587fe86..0c78c17f2b2 100644
--- a/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.h
+++ b/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.h
@@ -9,7 +9,7 @@
#include <vector>
#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
@@ -21,7 +21,7 @@ namespace background_fetch {
class MarkRegistrationForDeletionTask : public background_fetch::DatabaseTask {
public:
MarkRegistrationForDeletionTask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
HandleBackgroundFetchErrorCallback callback);
@@ -31,9 +31,11 @@ class MarkRegistrationForDeletionTask : public background_fetch::DatabaseTask {
private:
void DidGetActiveUniqueId(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
- void DidDeactivate(ServiceWorkerStatusCode status);
+ void DidDeactivate(blink::ServiceWorkerStatusCode status);
+
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
BackgroundFetchRegistrationId registration_id_;
HandleBackgroundFetchErrorCallback callback_;
diff --git a/chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc
index 63884ce938d..f416b06e4a6 100644
--- a/chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc
+++ b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc
@@ -4,21 +4,43 @@
#include "content/browser/background_fetch/storage/mark_request_complete_task.h"
+#include "base/barrier_closure.h"
+#include "base/guid.h"
+#include "content/browser/background_fetch/background_fetch_cross_origin_filter.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/background_fetch/storage/get_metadata_task.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "services/network/public/cpp/cors/cors.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/blob/blob_impl.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
namespace content {
namespace background_fetch {
+namespace {
+
+// Returns whether the response contained in the Background Fetch |request| is
+// considered OK. See https://fetch.spec.whatwg.org/#ok-status aka a successful
+// 2xx status per https://tools.ietf.org/html/rfc7231#section-6.3.
+bool IsOK(const BackgroundFetchRequestInfo& request) {
+ int status = request.GetResponseCode();
+ return network::cors::IsOkStatus(status);
+}
+
+} // namespace
+
MarkRequestCompleteTask::MarkRequestCompleteTask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
BackgroundFetchRegistrationId registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
MarkedCompleteCallback callback)
- : DatabaseTask(data_manager),
+ : DatabaseTask(host),
registration_id_(registration_id),
request_info_(std::move(request_info)),
callback_(std::move(callback)),
@@ -27,31 +49,134 @@ MarkRequestCompleteTask::MarkRequestCompleteTask(
MarkRequestCompleteTask::~MarkRequestCompleteTask() = default;
void MarkRequestCompleteTask::Start() {
- StoreResponse();
+ base::RepeatingClosure barrier_closure = base::BarrierClosure(
+ 2u, base::BindOnce(&MarkRequestCompleteTask::FinishWithError,
+ weak_factory_.GetWeakPtr(),
+ blink::mojom::BackgroundFetchError::NONE));
+
+ StoreResponse(barrier_closure);
+ UpdateMetadata(barrier_closure);
}
-void MarkRequestCompleteTask::StoreResponse() {
- ServiceWorkerResponse response;
- bool is_response_valid = data_manager()->FillServiceWorkerResponse(
- *request_info_, registration_id_.origin(), &response);
+void MarkRequestCompleteTask::StoreResponse(base::OnceClosure done_closure) {
+ auto response = std::make_unique<ServiceWorkerResponse>();
+ response->url_list = request_info_->GetURLChain();
+ // TODO(crbug.com/838837): fill error and cors_exposed_header_names in
+ // response.
+ response->response_type = network::mojom::FetchResponseType::kDefault;
+ response->response_time = request_info_->GetResponseTime();
+
+ BackgroundFetchCrossOriginFilter filter(registration_id_.origin(),
+ *request_info_);
+ if (filter.CanPopulateBody())
+ PopulateResponseBody(response.get());
+ else
+ is_response_successful_ = false;
+
+ if (!IsOK(*request_info_))
+ is_response_successful_ = false;
- if (!is_response_valid) {
- // No point in caching the response, just do the request state transition.
- CreateAndStoreCompletedRequest(false);
+ // A valid non-empty url is needed if we want to write to the cache.
+ if (!request_info_->fetch_request().url.is_valid()) {
+ CreateAndStoreCompletedRequest(std::move(done_closure));
return;
}
- // TODO(rayankans): Store the request/response pair in cache storage, and call
- // `CreateAndStoreActiveRequest` via a callback.
- CreateAndStoreCompletedRequest(true);
+
+ cache_manager()->OpenCache(
+ registration_id_.origin(), CacheStorageOwner::kBackgroundFetch,
+ registration_id_.unique_id() /* cache_name */,
+ base::BindOnce(&MarkRequestCompleteTask::DidOpenCache,
+ weak_factory_.GetWeakPtr(), std::move(response),
+ std::move(done_closure)));
+}
+
+void MarkRequestCompleteTask::PopulateResponseBody(
+ ServiceWorkerResponse* response) {
+ // Include the status code, status text and the response's body as a blob
+ // when this is allowed by the CORS protocol.
+ response->status_code = request_info_->GetResponseCode();
+ response->status_text = request_info_->GetResponseText();
+ response->headers.insert(request_info_->GetResponseHeaders().begin(),
+ request_info_->GetResponseHeaders().end());
+
+ DCHECK(blob_storage_context());
+ std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
+
+ // Prefer the blob data handle provided by the |request_info_| if one is
+ // available. Otherwise create one based on the file path and size.
+ if (request_info_->GetBlobDataHandle()) {
+ blob_data_handle = std::make_unique<storage::BlobDataHandle>(
+ request_info_->GetBlobDataHandle().value());
+
+ } else if (request_info_->GetFileSize() > 0 &&
+ !request_info_->GetFilePath().empty()) {
+ // TODO(rayankans): Simplify this code by making either the download service
+ // or the BackgroundFetchRequestInfo responsible for files vs. blobs.
+ auto blob_builder =
+ std::make_unique<storage::BlobDataBuilder>(base::GenerateGUID());
+ blob_builder->AppendFile(request_info_->GetFilePath(), 0 /* offset */,
+ request_info_->GetFileSize(),
+ base::Time() /* expected_modification_time */);
+
+ blob_data_handle = GetBlobStorageContext(blob_storage_context())
+ ->AddFinishedBlob(std::move(blob_builder));
+ }
+
+ // TODO(rayankans): Appropriately handle !blob_data_handle
+ if (!blob_data_handle)
+ return;
+
+ response->blob_uuid = blob_data_handle->uuid();
+ response->blob_size = blob_data_handle->size();
+ blink::mojom::BlobPtr blob_ptr;
+ storage::BlobImpl::Create(
+ std::make_unique<storage::BlobDataHandle>(*blob_data_handle),
+ MakeRequest(&blob_ptr));
+
+ response->blob =
+ base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
+}
+
+void MarkRequestCompleteTask::DidOpenCache(
+ std::unique_ptr<ServiceWorkerResponse> response,
+ base::OnceClosure done_closure,
+ CacheStorageCacheHandle handle,
+ blink::mojom::CacheStorageError error) {
+ if (error != blink::mojom::CacheStorageError::kSuccess) {
+ // TODO(crbug.com/780025): Log failures to UMA.
+ CreateAndStoreCompletedRequest(std::move(done_closure));
+ return;
+ }
+ DCHECK(handle.value());
+
+ auto request = std::make_unique<ServiceWorkerFetchRequest>(
+ request_info_->fetch_request());
+
+ // We need to keep the handle refcounted while the write is happening,
+ // so it's passed along to the callback.
+ handle.value()->Put(
+ std::move(request), std::move(response),
+ base::BindOnce(&MarkRequestCompleteTask::DidWriteToCache,
+ weak_factory_.GetWeakPtr(), std::move(handle),
+ std::move(done_closure)));
}
-void MarkRequestCompleteTask::CreateAndStoreCompletedRequest(bool succeeded) {
+void MarkRequestCompleteTask::DidWriteToCache(
+ CacheStorageCacheHandle handle,
+ base::OnceClosure done_closure,
+ blink::mojom::CacheStorageError error) {
+ // TODO(crbug.com/780025): Log failures to UMA.
+ CreateAndStoreCompletedRequest(std::move(done_closure));
+}
+
+void MarkRequestCompleteTask::CreateAndStoreCompletedRequest(
+ base::OnceClosure done_closure) {
completed_request_.set_unique_id(registration_id_.unique_id());
completed_request_.set_request_index(request_info_->request_index());
completed_request_.set_serialized_request(
request_info_->fetch_request().Serialize());
completed_request_.set_download_guid(request_info_->download_guid());
- completed_request_.set_succeeded(succeeded);
+ completed_request_.set_succeeded(is_response_successful_);
service_worker_context()->StoreRegistrationUserData(
registration_id_.service_worker_registration_id(),
@@ -59,19 +184,20 @@ void MarkRequestCompleteTask::CreateAndStoreCompletedRequest(bool succeeded) {
{{CompletedRequestKey(completed_request_.unique_id(),
completed_request_.request_index()),
completed_request_.SerializeAsString()}},
- base::BindRepeating(&MarkRequestCompleteTask::DidStoreCompletedRequest,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&MarkRequestCompleteTask::DidStoreCompletedRequest,
+ weak_factory_.GetWeakPtr(), std::move(done_closure)));
}
void MarkRequestCompleteTask::DidStoreCompletedRequest(
- ServiceWorkerStatusCode status) {
+ base::OnceClosure done_closure,
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
break;
case DatabaseStatus::kFailed:
case DatabaseStatus::kNotFound:
// TODO(crbug.com/780025): Log failures to UMA.
- Finished(); // Destroys |this|.
+ std::move(done_closure).Run();
return;
}
@@ -81,26 +207,64 @@ void MarkRequestCompleteTask::DidStoreCompletedRequest(
{ActiveRequestKey(completed_request_.unique_id(),
completed_request_.request_index())},
base::BindOnce(&MarkRequestCompleteTask::DidDeleteActiveRequest,
- weak_factory_.GetWeakPtr()));
+ weak_factory_.GetWeakPtr(), std::move(done_closure)));
}
void MarkRequestCompleteTask::DidDeleteActiveRequest(
- ServiceWorkerStatusCode status) {
- switch (ToDatabaseStatus(status)) {
- case DatabaseStatus::kNotFound:
- case DatabaseStatus::kFailed:
- // TODO(crbug.com/780025): Log failures to UMA.
- break;
- case DatabaseStatus::kOk:
- std::move(callback_).Run();
- break;
+ base::OnceClosure done_closure,
+ blink::ServiceWorkerStatusCode status) {
+ // TODO(crbug.com/780025): Log failures to UMA.
+ std::move(done_closure).Run();
+}
+
+void MarkRequestCompleteTask::UpdateMetadata(base::OnceClosure done_closure) {
+ if (!request_info_->IsResultSuccess() || request_info_->GetFileSize() == 0u) {
+ std::move(done_closure).Run();
+ return;
}
- Finished(); // Destroys |this|.
+ AddSubTask(std::make_unique<GetMetadataTask>(
+ this, registration_id_.service_worker_registration_id(),
+ registration_id_.origin(), registration_id_.developer_id(),
+ base::BindOnce(&MarkRequestCompleteTask::DidGetMetadata,
+ weak_factory_.GetWeakPtr(), std::move(done_closure))));
+}
+
+void MarkRequestCompleteTask::DidGetMetadata(
+ base::OnceClosure done_closure,
+ blink::mojom::BackgroundFetchError error,
+ std::unique_ptr<proto::BackgroundFetchMetadata> metadata) {
+ if (!metadata || error != blink::mojom::BackgroundFetchError::NONE) {
+ // TODO(crbug.com/780025): Log failures to UMA.
+ std::move(done_closure).Run();
+ return;
+ }
+
+ metadata->mutable_registration()->set_download_total(
+ metadata->registration().download_total() + request_info_->GetFileSize());
+
+ service_worker_context()->StoreRegistrationUserData(
+ registration_id_.service_worker_registration_id(),
+ registration_id_.origin().GetURL(),
+ {{RegistrationKey(registration_id_.unique_id()),
+ metadata->SerializeAsString()}},
+ base::BindOnce(&MarkRequestCompleteTask::DidStoreMetadata,
+ weak_factory_.GetWeakPtr(), std::move(done_closure)));
+}
+
+void MarkRequestCompleteTask::DidStoreMetadata(
+ base::OnceClosure done_closure,
+ blink::ServiceWorkerStatusCode status) {
+ // TODO(crbug.com/780025): Log failures to UMA.
+ std::move(done_closure).Run();
+}
- // TODO(rayankans): Update download stats.
+void MarkRequestCompleteTask::FinishWithError(
+ blink::mojom::BackgroundFetchError error) {
+ std::move(callback_).Run();
+ Finished();
}
} // namespace background_fetch
-} // namespace content \ No newline at end of file
+} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h
index b36c836ba04..9e96d1db298 100644
--- a/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h
+++ b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h
@@ -10,7 +10,8 @@
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/browser/cache_storage/cache_storage_cache_handle.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
@@ -23,7 +24,7 @@ class MarkRequestCompleteTask : public DatabaseTask {
using MarkedCompleteCallback = base::OnceCallback<void()>;
MarkRequestCompleteTask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
BackgroundFetchRegistrationId registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
MarkedCompleteCallback callback);
@@ -34,19 +35,44 @@ class MarkRequestCompleteTask : public DatabaseTask {
void Start() override;
private:
- void StoreResponse();
+ void StoreResponse(base::OnceClosure done_closure);
- void CreateAndStoreCompletedRequest(bool succeeded);
+ void PopulateResponseBody(ServiceWorkerResponse* response);
- void DidStoreCompletedRequest(ServiceWorkerStatusCode status);
+ void DidOpenCache(std::unique_ptr<ServiceWorkerResponse> response,
+ base::OnceClosure done_closure,
+ CacheStorageCacheHandle handle,
+ blink::mojom::CacheStorageError error);
- void DidDeleteActiveRequest(ServiceWorkerStatusCode status);
+ void DidWriteToCache(CacheStorageCacheHandle handle,
+ base::OnceClosure done_closure,
+ blink::mojom::CacheStorageError error);
+
+ void CreateAndStoreCompletedRequest(base::OnceClosure done_closure);
+
+ void DidStoreCompletedRequest(base::OnceClosure done_closure,
+ blink::ServiceWorkerStatusCode status);
+
+ void DidDeleteActiveRequest(base::OnceClosure done_closure,
+ blink::ServiceWorkerStatusCode status);
+
+ void UpdateMetadata(base::OnceClosure done_closure);
+
+ void DidGetMetadata(base::OnceClosure done_closure,
+ blink::mojom::BackgroundFetchError error,
+ std::unique_ptr<proto::BackgroundFetchMetadata> metadata);
+
+ void DidStoreMetadata(base::OnceClosure done_closure,
+ blink::ServiceWorkerStatusCode status);
+
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
BackgroundFetchRegistrationId registration_id_;
scoped_refptr<BackgroundFetchRequestInfo> request_info_;
MarkedCompleteCallback callback_;
proto::BackgroundFetchCompletedRequest completed_request_;
+ bool is_response_successful_ = true;
base::WeakPtrFactory<MarkRequestCompleteTask> weak_factory_; // Keep as last.
diff --git a/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc
index 107bb160409..1cc5c796f32 100644
--- a/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc
+++ b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc
@@ -5,6 +5,7 @@
#include "content/browser/background_fetch/storage/start_next_pending_request_task.h"
#include "base/guid.h"
+#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -13,11 +14,11 @@ namespace content {
namespace background_fetch {
StartNextPendingRequestTask::StartNextPendingRequestTask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
int64_t service_worker_registration_id,
std::unique_ptr<proto::BackgroundFetchMetadata> metadata,
NextRequestCallback callback)
- : DatabaseTask(data_manager),
+ : DatabaseTask(host),
service_worker_registration_id_(service_worker_registration_id),
metadata_(std::move(metadata)),
callback_(std::move(callback)),
@@ -41,25 +42,26 @@ void StartNextPendingRequestTask::GetPendingRequests() {
void StartNextPendingRequestTask::DidGetPendingRequests(
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kNotFound:
case DatabaseStatus::kFailed:
// TODO(crbug.com/780025): Log failures to UMA.
- std::move(callback_).Run(nullptr /* request */);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
case DatabaseStatus::kOk:
if (data.empty()) {
// There are no pending requests.
- std::move(callback_).Run(nullptr /* request */);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
return;
}
}
if (!pending_request_.ParseFromString(data.front())) {
- NOTREACHED() << "Database is corrupt"; // TODO(crbug.com/780027): Nuke it.
+ // Service Worker database has been corrupted. Abandon fetches.
+ AbandonFetches(service_worker_registration_id_);
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
}
// Make sure there isn't already an Active Request.
@@ -74,12 +76,10 @@ void StartNextPendingRequestTask::DidGetPendingRequests(
void StartNextPendingRequestTask::DidFindActiveRequest(
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kFailed:
- // TODO(crbug.com/780025): Log failures to UMA.
- std::move(callback_).Run(nullptr /* request */);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
case DatabaseStatus::kNotFound:
CreateAndStoreActiveRequest();
@@ -87,8 +87,10 @@ void StartNextPendingRequestTask::DidFindActiveRequest(
case DatabaseStatus::kOk:
// We already stored the active request.
if (!active_request_.ParseFromString(data.front())) {
- NOTREACHED()
- << "Database is corrupt"; // TODO(crbug.com/780027): Nuke it.
+ // Service worker database has been corrupted. Abandon fetches.
+ AbandonFetches(service_worker_registration_id_);
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
}
StartDownload();
return;
@@ -116,15 +118,13 @@ void StartNextPendingRequestTask::CreateAndStoreActiveRequest() {
}
void StartNextPendingRequestTask::DidStoreActiveRequest(
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
break;
case DatabaseStatus::kFailed:
case DatabaseStatus::kNotFound:
- // TODO(crbug.com/780025): Log failures to UMA.
- std::move(callback_).Run(nullptr /* request */);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
return;
}
StartDownload();
@@ -151,8 +151,15 @@ void StartNextPendingRequestTask::StartDownload() {
}
void StartNextPendingRequestTask::DidDeletePendingRequest(
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
// TODO(crbug.com/780025): Log failures to UMA.
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+}
+
+void StartNextPendingRequestTask::FinishWithError(
+ blink::mojom::BackgroundFetchError error) {
+ if (callback_)
+ std::move(callback_).Run(nullptr /* request */);
Finished(); // Destroys |this|.
}
diff --git a/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h
index 476db6aa670..89ae0fb1bdf 100644
--- a/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h
+++ b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h
@@ -9,7 +9,7 @@
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
@@ -23,7 +23,7 @@ class StartNextPendingRequestTask : public DatabaseTask {
base::OnceCallback<void(scoped_refptr<BackgroundFetchRequestInfo>)>;
StartNextPendingRequestTask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
int64_t service_worker_registration_id,
std::unique_ptr<proto::BackgroundFetchMetadata> metadata,
NextRequestCallback callback);
@@ -37,18 +37,20 @@ class StartNextPendingRequestTask : public DatabaseTask {
void GetPendingRequests();
void DidGetPendingRequests(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void DidFindActiveRequest(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void CreateAndStoreActiveRequest();
- void DidStoreActiveRequest(ServiceWorkerStatusCode status);
+ void DidStoreActiveRequest(blink::ServiceWorkerStatusCode status);
void StartDownload();
- void DidDeletePendingRequest(ServiceWorkerStatusCode status);
+ void DidDeletePendingRequest(blink::ServiceWorkerStatusCode status);
+
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
int64_t service_worker_registration_id_;
std::unique_ptr<proto::BackgroundFetchMetadata> metadata_;
diff --git a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc
index 5927855db09..38ad299080f 100644
--- a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc
+++ b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc
@@ -4,6 +4,8 @@
#include "content/browser/background_fetch/storage/update_registration_ui_task.h"
+#include "content/browser/background_fetch/background_fetch_data_manager.h"
+#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
@@ -13,11 +15,11 @@ namespace content {
namespace background_fetch {
UpdateRegistrationUITask::UpdateRegistrationUITask(
- BackgroundFetchDataManager* data_manager,
+ DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
const std::string& updated_title,
UpdateRegistrationUICallback callback)
- : DatabaseTask(data_manager),
+ : DatabaseTask(host),
registration_id_(registration_id),
updated_title_(updated_title),
callback_(std::move(callback)),
@@ -34,20 +36,26 @@ void UpdateRegistrationUITask::Start() {
weak_factory_.GetWeakPtr()));
}
-void UpdateRegistrationUITask::DidUpdateTitle(ServiceWorkerStatusCode status) {
+void UpdateRegistrationUITask::DidUpdateTitle(
+ blink::ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
break;
case DatabaseStatus::kFailed:
case DatabaseStatus::kNotFound:
- // TODO(crbug.com/780025): Log failures to UMA.
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR);
- Finished(); // Destroys |this|.
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
return;
}
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::NONE);
+ for (auto& observer : data_manager()->observers())
+ observer.OnUpdatedUI(registration_id_, updated_title_);
+
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+}
+
+void UpdateRegistrationUITask::FinishWithError(
+ blink::mojom::BackgroundFetchError error) {
+ std::move(callback_).Run(error);
Finished(); // Destroys |this|.
}
diff --git a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h
index 08167977bd2..45a0a0fe8c5 100644
--- a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h
+++ b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h
@@ -11,7 +11,7 @@
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/storage/database_task.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
@@ -23,7 +23,7 @@ class UpdateRegistrationUITask : public DatabaseTask {
using UpdateRegistrationUICallback =
base::OnceCallback<void(blink::mojom::BackgroundFetchError)>;
- UpdateRegistrationUITask(BackgroundFetchDataManager* data_manager,
+ UpdateRegistrationUITask(DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
const std::string& updated_title,
UpdateRegistrationUICallback callback);
@@ -33,7 +33,9 @@ class UpdateRegistrationUITask : public DatabaseTask {
void Start() override;
private:
- void DidUpdateTitle(ServiceWorkerStatusCode status);
+ void DidUpdateTitle(blink::ServiceWorkerStatusCode status);
+
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override;
BackgroundFetchRegistrationId registration_id_;
std::string updated_title_;
diff --git a/chromium/content/browser/background_sync/background_sync_browsertest.cc b/chromium/content/browser/background_sync/background_sync_browsertest.cc
index e7afc3f8759..678766f9341 100644
--- a/chromium/content/browser/background_sync/background_sync_browsertest.cc
+++ b/chromium/content/browser/background_sync/background_sync_browsertest.cc
@@ -93,9 +93,9 @@ void RegistrationPendingDidGetSWRegistration(
const scoped_refptr<BackgroundSyncContext> sync_context,
const std::string& tag,
base::OnceCallback<void(bool)> callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
- ASSERT_EQ(SERVICE_WORKER_OK, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
int64_t service_worker_id = registration->id();
BackgroundSyncManager* sync_manager = sync_context->background_sync_manager();
sync_manager->GetRegistrations(
@@ -111,9 +111,8 @@ void RegistrationPendingOnIOThread(
const GURL& url,
base::OnceCallback<void(bool)> callback) {
sw_context->FindReadyRegistrationForDocument(
- url, base::AdaptCallbackForRepeating(
- base::BindOnce(&RegistrationPendingDidGetSWRegistration,
- sync_context, tag, std::move(callback))));
+ url, base::BindOnce(&RegistrationPendingDidGetSWRegistration,
+ sync_context, tag, std::move(callback)));
}
void SetMaxSyncAttemptsOnIOThread(
diff --git a/chromium/content/browser/background_sync/background_sync_manager.cc b/chromium/content/browser/background_sync/background_sync_manager.cc
index 62d6f5a2d7d..0b5b90e9d39 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager.cc
@@ -21,15 +21,15 @@
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_storage.h"
-#include "content/browser/service_worker/service_worker_type_converters.h"
#include "content/browser/storage_partition_impl.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "content/common/service_worker/service_worker_utils.h"
#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_controller.h"
#include "content/public/browser/permission_type.h"
+#include "third_party/blink/public/common/service_worker/service_worker_type_converters.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#if defined(OS_ANDROID)
@@ -80,8 +80,6 @@ BackgroundSyncController* GetBackgroundSyncControllerOnUIThread(
return browser_context->GetBackgroundSyncController();
}
-// Returns PermissionStatus::DENIED if the permission manager cannot be
-// accessed for any reason.
blink::mojom::PermissionStatus GetBackgroundSyncPermissionOnUIThread(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
const GURL& origin) {
@@ -92,13 +90,12 @@ blink::mojom::PermissionStatus GetBackgroundSyncPermissionOnUIThread(
if (!browser_context)
return blink::mojom::PermissionStatus::DENIED;
- PermissionManager* permission_manager =
- browser_context->GetPermissionManager();
- if (!permission_manager)
- return blink::mojom::PermissionStatus::DENIED;
+ PermissionController* permission_controller =
+ BrowserContext::GetPermissionController(browser_context);
+ DCHECK(permission_controller);
// The requesting origin always matches the embedding origin.
- return permission_manager->GetPermissionStatus(
+ return permission_controller->GetPermissionStatus(
PermissionType::BACKGROUND_SYNC, origin, origin);
}
@@ -159,14 +156,15 @@ void OnSyncEventFinished(scoped_refptr<ServiceWorkerVersion> active_version,
dispatch_event_time)) {
return;
}
- std::move(callback).Run(mojo::ConvertTo<ServiceWorkerStatusCode>(status));
+ std::move(callback).Run(
+ mojo::ConvertTo<blink::ServiceWorkerStatusCode>(status));
}
void DidStartWorkerForSyncEvent(
base::OnceCallback<void(ServiceWorkerVersion::StatusCallback)> task,
ServiceWorkerVersion::StatusCallback callback,
- ServiceWorkerStatusCode start_worker_status) {
- if (start_worker_status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode start_worker_status) {
+ if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(start_worker_status);
return;
}
@@ -279,8 +277,8 @@ void BackgroundSyncManager::EmulateDispatchSyncEvent(
bool last_chance,
ServiceWorkerVersion::StatusCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- ServiceWorkerStatusCode code = CanEmulateSyncEvent(active_version);
- if (code != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode code = CanEmulateSyncEvent(active_version);
+ if (code != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(code);
return;
}
@@ -367,19 +365,20 @@ void BackgroundSyncManager::InitDidGetControllerParameters(
return;
}
- GetDataFromBackend(kBackgroundSyncUserDataKey,
- base::AdaptCallbackForRepeating(base::BindOnce(
- &BackgroundSyncManager::InitDidGetDataFromBackend,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback))));
+ GetDataFromBackend(
+ kBackgroundSyncUserDataKey,
+ base::BindOnce(&BackgroundSyncManager::InitDidGetDataFromBackend,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void BackgroundSyncManager::InitDidGetDataFromBackend(
base::OnceClosure callback,
const std::vector<std::pair<int64_t, std::string>>& user_data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
+ if (status != blink::ServiceWorkerStatusCode::kOk &&
+ status != blink::ServiceWorkerStatusCode::kErrorNotFound) {
LOG(ERROR) << "BackgroundSync failed to init due to backend failure.";
DisableAndClearManager(std::move(callback));
return;
@@ -597,18 +596,17 @@ void BackgroundSyncManager::DisableAndClearManager(base::OnceClosure callback) {
// loading from storage), so reload the registrations from storage again.
GetDataFromBackend(
kBackgroundSyncUserDataKey,
- base::AdaptCallbackForRepeating(base::BindOnce(
- &BackgroundSyncManager::DisableAndClearDidGetRegistrations,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback))));
+ base::BindOnce(&BackgroundSyncManager::DisableAndClearDidGetRegistrations,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void BackgroundSyncManager::DisableAndClearDidGetRegistrations(
base::OnceClosure callback,
const std::vector<std::pair<int64_t, std::string>>& user_data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK || user_data.empty()) {
+ if (status != blink::ServiceWorkerStatusCode::kOk || user_data.empty()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
std::move(callback));
return;
@@ -620,15 +618,14 @@ void BackgroundSyncManager::DisableAndClearDidGetRegistrations(
for (const auto& sw_id_and_regs : user_data) {
service_worker_context_->ClearRegistrationUserData(
sw_id_and_regs.first, {kBackgroundSyncUserDataKey},
- base::AdaptCallbackForRepeating(base::BindOnce(
- &BackgroundSyncManager::DisableAndClearManagerClearedOne,
- weak_ptr_factory_.GetWeakPtr(), barrier_closure)));
+ base::BindOnce(&BackgroundSyncManager::DisableAndClearManagerClearedOne,
+ weak_ptr_factory_.GetWeakPtr(), barrier_closure));
}
}
void BackgroundSyncManager::DisableAndClearManagerClearedOne(
base::OnceClosure barrier_closure,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// The status doesn't matter at this point, there is nothing else to be done.
@@ -695,10 +692,10 @@ void BackgroundSyncManager::RegisterDidStore(
int64_t sw_registration_id,
const BackgroundSyncRegistration& new_registration,
StatusAndRegistrationCallback callback,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
+ if (status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
// The service worker registration is gone.
active_registrations_.erase(sw_registration_id);
RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
@@ -706,7 +703,7 @@ void BackgroundSyncManager::RegisterDidStore(
return;
}
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
LOG(ERROR) << "BackgroundSync failed to store registration due to backend "
"failure.";
BackgroundSyncMetrics::CountRegisterFailure(
@@ -767,8 +764,7 @@ void BackgroundSyncManager::StoreDataInBackend(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_worker_context_->StoreRegistrationUserData(
- sw_registration_id, origin, {{backend_key, data}},
- base::AdaptCallbackForRepeating(std::move(callback)));
+ sw_registration_id, origin, {{backend_key, data}}, std::move(callback));
}
void BackgroundSyncManager::GetDataFromBackend(
@@ -794,7 +790,7 @@ void BackgroundSyncManager::DispatchSyncEvent(
base::BindOnce(&DidStartWorkerForSyncEvent,
base::BindOnce(&BackgroundSyncManager::DispatchSyncEvent,
weak_ptr_factory_.GetWeakPtr(), tag,
- std::move(active_version), last_chance),
+ active_version, last_chance),
std::move(callback)));
return;
}
@@ -807,10 +803,10 @@ void BackgroundSyncManager::DispatchSyncEvent(
parameters_->max_sync_event_duration,
ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);
- active_version->event_dispatcher()->DispatchSyncEvent(
+ active_version->endpoint()->DispatchSyncEvent(
tag, last_chance, parameters_->max_sync_event_duration,
- base::BindOnce(&OnSyncEventFinished, std::move(active_version),
- request_id, std::move(repeating_callback)));
+ base::BindOnce(&OnSyncEventFinished, active_version, request_id,
+ std::move(repeating_callback)));
}
void BackgroundSyncManager::ScheduleDelayedTask(base::OnceClosure callback,
@@ -821,8 +817,8 @@ void BackgroundSyncManager::ScheduleDelayedTask(base::OnceClosure callback,
void BackgroundSyncManager::HasMainFrameProviderHost(const GURL& origin,
BoolCallback callback) {
- service_worker_context_->HasMainFrameProviderHost(
- origin, base::AdaptCallbackForRepeating(std::move(callback)));
+ service_worker_context_->HasMainFrameProviderHost(origin,
+ std::move(callback));
}
void BackgroundSyncManager::GetRegistrationsImpl(
@@ -1012,10 +1008,10 @@ void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
BackgroundSyncRegistration::RegistrationId registration_id,
base::OnceClosure event_fired_callback,
base::OnceClosure event_completed_callback,
- ServiceWorkerStatusCode service_worker_status,
+ blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (service_worker_status != SERVICE_WORKER_OK) {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, std::move(event_fired_callback));
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -1063,7 +1059,7 @@ void BackgroundSyncManager::EventComplete(
int64_t service_worker_id,
const std::string& tag,
base::OnceClosure callback,
- ServiceWorkerStatusCode status_code) {
+ blink::ServiceWorkerStatusCode status_code) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (disabled_) {
@@ -1081,7 +1077,7 @@ void BackgroundSyncManager::EventComplete(
void BackgroundSyncManager::EventCompleteImpl(
int64_t service_worker_id,
const std::string& tag,
- ServiceWorkerStatusCode status_code,
+ blink::ServiceWorkerStatusCode status_code,
base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -1114,7 +1110,7 @@ void BackgroundSyncManager::EventCompleteImpl(
HasMainFrameProviderHost(
sw_registration->pattern().GetOrigin(),
base::BindOnce(&BackgroundSyncMetrics::RecordEventResult,
- status_code == SERVICE_WORKER_OK));
+ status_code == blink::ServiceWorkerStatusCode::kOk));
}
bool registration_completed = true;
@@ -1126,7 +1122,7 @@ void BackgroundSyncManager::EventCompleteImpl(
registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING);
registration->set_num_attempts(0);
registration_completed = false;
- } else if (status_code != SERVICE_WORKER_OK &&
+ } else if (status_code != blink::ServiceWorkerStatusCode::kOk &&
can_retry) { // Sync failed but can retry
registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING);
registration->set_delay_until(clock_->Now() +
@@ -1156,10 +1152,10 @@ void BackgroundSyncManager::EventCompleteImpl(
void BackgroundSyncManager::EventCompleteDidStore(
int64_t service_worker_id,
base::OnceClosure callback,
- ServiceWorkerStatusCode status_code) {
+ blink::ServiceWorkerStatusCode status_code) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status_code == SERVICE_WORKER_ERROR_NOT_FOUND) {
+ if (status_code == blink::ServiceWorkerStatusCode::kErrorNotFound) {
// The registration is gone.
active_registrations_.erase(service_worker_id);
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
@@ -1167,7 +1163,7 @@ void BackgroundSyncManager::EventCompleteDidStore(
return;
}
- if (status_code != SERVICE_WORKER_OK) {
+ if (status_code != blink::ServiceWorkerStatusCode::kOk) {
LOG(ERROR) << "BackgroundSync failed to store registration due to backend "
"failure.";
DisableAndClearManager(std::move(callback));
@@ -1227,16 +1223,16 @@ base::OnceClosure BackgroundSyncManager::MakeEmptyCompletion() {
return op_scheduler_.WrapCallbackToRunNext(base::DoNothing::Once());
}
-ServiceWorkerStatusCode BackgroundSyncManager::CanEmulateSyncEvent(
+blink::ServiceWorkerStatusCode BackgroundSyncManager::CanEmulateSyncEvent(
scoped_refptr<ServiceWorkerVersion> active_version) {
if (!active_version)
- return SERVICE_WORKER_ERROR_FAILED;
+ return blink::ServiceWorkerStatusCode::kErrorFailed;
if (!network_observer_->NetworkSufficient(NETWORK_STATE_ONLINE))
- return SERVICE_WORKER_ERROR_NETWORK;
+ return blink::ServiceWorkerStatusCode::kErrorNetwork;
int64_t registration_id = active_version->registration_id();
if (base::ContainsKey(emulated_offline_sw_, registration_id))
- return SERVICE_WORKER_ERROR_NETWORK;
- return SERVICE_WORKER_OK;
+ return blink::ServiceWorkerStatusCode::kErrorNetwork;
+ return blink::ServiceWorkerStatusCode::kOk;
}
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_manager.h b/chromium/content/browser/background_sync/background_sync_manager.h
index 38091eaa269..84449a91006 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.h
+++ b/chromium/content/browser/background_sync/background_sync_manager.h
@@ -26,9 +26,9 @@
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/common/content_export.h"
-#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/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/platform/modules/background_sync/background_sync.mojom.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
#include "url/gurl.h"
@@ -166,9 +166,9 @@ class CONTENT_EXPORT BackgroundSyncManager
void DisableAndClearDidGetRegistrations(
base::OnceClosure callback,
const std::vector<std::pair<int64_t, std::string>>& user_data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void DisableAndClearManagerClearedOne(base::OnceClosure barrier_closure,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// Returns the existing registration or nullptr if it cannot be found.
BackgroundSyncRegistration* LookupActiveRegistration(
@@ -196,7 +196,7 @@ class CONTENT_EXPORT BackgroundSyncManager
void InitDidGetDataFromBackend(
base::OnceClosure callback,
const std::vector<std::pair<int64_t, std::string>>& user_data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// Register callbacks
void RegisterCheckIfHasMainFrame(
@@ -219,7 +219,7 @@ class CONTENT_EXPORT BackgroundSyncManager
void RegisterDidStore(int64_t sw_registration_id,
const BackgroundSyncRegistration& new_registration,
StatusAndRegistrationCallback callback,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// GetRegistrations callbacks
void GetRegistrationsImpl(int64_t sw_registration_id,
@@ -247,7 +247,7 @@ class CONTENT_EXPORT BackgroundSyncManager
BackgroundSyncRegistration::RegistrationId registration_id,
base::OnceClosure event_fired_callback,
base::OnceClosure event_completed_callback,
- ServiceWorkerStatusCode service_worker_status,
+ blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration);
void FireReadyEventsAllEventsFiring(base::OnceClosure callback);
@@ -257,14 +257,14 @@ class CONTENT_EXPORT BackgroundSyncManager
int64_t service_worker_id,
const std::string& tag,
base::OnceClosure callback,
- ServiceWorkerStatusCode status_code);
+ blink::ServiceWorkerStatusCode status_code);
void EventCompleteImpl(int64_t service_worker_id,
const std::string& tag,
- ServiceWorkerStatusCode status_code,
+ blink::ServiceWorkerStatusCode status_code,
base::OnceClosure callback);
void EventCompleteDidStore(int64_t service_worker_id,
base::OnceClosure callback,
- ServiceWorkerStatusCode status_code);
+ blink::ServiceWorkerStatusCode status_code);
// Called when all sync events have completed.
static void OnAllSyncEventsCompleted(const base::TimeTicks& start_time,
@@ -285,7 +285,7 @@ class CONTENT_EXPORT BackgroundSyncManager
base::OnceClosure MakeEmptyCompletion();
- ServiceWorkerStatusCode CanEmulateSyncEvent(
+ blink::ServiceWorkerStatusCode CanEmulateSyncEvent(
scoped_refptr<ServiceWorkerVersion> active_version);
SWIdToRegistrationsMap active_registrations_;
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 5fc543bee78..077a39c679d 100644
--- a/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -25,7 +25,6 @@
#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_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_registration_object_host.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/storage_partition_impl.h"
@@ -58,25 +57,27 @@ const char kScript2[] = "https://example.com/b/script.js";
void RegisterServiceWorkerCallback(bool* called,
int64_t* store_registration_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
- EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
*called = true;
*store_registration_id = registration_id;
}
void FindServiceWorkerRegistrationCallback(
scoped_refptr<ServiceWorkerRegistration>* out_registration,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
- EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
*out_registration = std::move(registration);
}
void UnregisterServiceWorkerCallback(bool* called,
- ServiceWorkerStatusCode code) {
- EXPECT_EQ(SERVICE_WORKER_OK, code);
+ blink::ServiceWorkerStatusCode code) {
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, code);
*called = true;
}
@@ -108,7 +109,7 @@ class BackgroundSyncManagerTest : public testing::Test {
ON_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::BACKGROUND_SYNC, _, _))
.WillByDefault(Return(blink::mojom::PermissionStatus::GRANTED));
- helper_->browser_context()->SetPermissionManager(
+ helper_->browser_context()->SetPermissionControllerDelegate(
std::move(mock_permission_manager));
// Create a StoragePartition with the correct BrowserContext so that the
@@ -140,15 +141,13 @@ class BackgroundSyncManagerTest : public testing::Test {
options2.scope = GURL(kPattern2);
helper_->context()->RegisterServiceWorker(
GURL(kScript1), options1,
- base::AdaptCallbackForRepeating(
- base::BindOnce(&RegisterServiceWorkerCallback, &called_1,
- &sw_registration_id_1_)));
+ base::BindOnce(&RegisterServiceWorkerCallback, &called_1,
+ &sw_registration_id_1_));
helper_->context()->RegisterServiceWorker(
GURL(kScript2), options2,
- base::AdaptCallbackForRepeating(
- base::BindOnce(&RegisterServiceWorkerCallback, &called_2,
- &sw_registration_id_2_)));
+ base::BindOnce(&RegisterServiceWorkerCallback, &called_2,
+ &sw_registration_id_2_));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called_1);
EXPECT_TRUE(called_2);
@@ -157,13 +156,13 @@ class BackgroundSyncManagerTest : public testing::Test {
// calling BackgroundSyncManager::Register.
helper_->context_wrapper()->FindReadyRegistrationForId(
sw_registration_id_1_, GURL(kPattern1).GetOrigin(),
- base::AdaptCallbackForRepeating(base::BindOnce(
- FindServiceWorkerRegistrationCallback, &sw_registration_1_)));
+ base::BindOnce(FindServiceWorkerRegistrationCallback,
+ &sw_registration_1_));
helper_->context_wrapper()->FindReadyRegistrationForId(
sw_registration_id_2_, GURL(kPattern1).GetOrigin(),
- base::AdaptCallbackForRepeating(base::BindOnce(
- FindServiceWorkerRegistrationCallback, &sw_registration_2_)));
+ base::BindOnce(FindServiceWorkerRegistrationCallback,
+ &sw_registration_2_));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(sw_registration_1_);
EXPECT_TRUE(sw_registration_2_);
@@ -265,9 +264,9 @@ class BackgroundSyncManagerTest : public testing::Test {
return callback_status_ == BACKGROUND_SYNC_STATUS_OK;
}
- MockPermissionManager* GetPermissionManager() {
+ MockPermissionManager* GetPermissionControllerDelegate() {
return static_cast<MockPermissionManager*>(
- helper_->browser_context()->GetPermissionManager());
+ helper_->browser_context()->GetPermissionControllerDelegate());
}
bool GetRegistration(
@@ -325,7 +324,7 @@ class BackgroundSyncManagerTest : public testing::Test {
helper_->browser_context()->GetBackgroundSyncController());
}
- void StorageRegistrationCallback(ServiceWorkerStatusCode result) {
+ void StorageRegistrationCallback(blink::ServiceWorkerStatusCode result) {
callback_sw_status_code_ = result;
}
@@ -333,8 +332,7 @@ class BackgroundSyncManagerTest : public testing::Test {
bool called = false;
helper_->context()->UnregisterServiceWorker(
PatternForSWId(sw_registration_id),
- base::AdaptCallbackForRepeating(
- base::BindOnce(&UnregisterServiceWorkerCallback, &called)));
+ base::BindOnce(&UnregisterServiceWorkerCallback, &called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
}
@@ -352,7 +350,7 @@ class BackgroundSyncManagerTest : public testing::Test {
}
void DispatchSyncStatusCallback(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerVersion> active_version,
ServiceWorkerVersion::StatusCallback callback) {
sync_events_called_++;
@@ -362,13 +360,13 @@ class BackgroundSyncManagerTest : public testing::Test {
void InitSyncEventTest() {
SetupForSyncEvent(base::BindRepeating(
&BackgroundSyncManagerTest::DispatchSyncStatusCallback,
- base::Unretained(this), SERVICE_WORKER_OK));
+ base::Unretained(this), blink::ServiceWorkerStatusCode::kOk));
}
void InitFailedSyncEventTest() {
SetupForSyncEvent(base::BindRepeating(
&BackgroundSyncManagerTest::DispatchSyncStatusCallback,
- base::Unretained(this), SERVICE_WORKER_ERROR_FAILED));
+ base::Unretained(this), blink::ServiceWorkerStatusCode::kErrorFailed));
}
void DispatchSyncDelayedCallback(
@@ -433,7 +431,8 @@ class BackgroundSyncManagerTest : public testing::Test {
std::unique_ptr<BackgroundSyncRegistration> callback_registration_;
std::vector<std::unique_ptr<BackgroundSyncRegistration>>
callback_registrations_;
- ServiceWorkerStatusCode callback_sw_status_code_ = SERVICE_WORKER_OK;
+ blink::ServiceWorkerStatusCode callback_sw_status_code_ =
+ blink::ServiceWorkerStatusCode::kOk;
int sync_events_called_ = 0;
ServiceWorkerVersion::StatusCallback sync_fired_callback_;
};
@@ -485,7 +484,8 @@ TEST_F(BackgroundSyncManagerTest, RegisterBadBackend) {
TEST_F(BackgroundSyncManagerTest, RegisterPermissionDenied) {
GURL expected_origin = GURL(kPattern1).GetOrigin();
- MockPermissionManager* mock_permission_manager = GetPermissionManager();
+ MockPermissionManager* mock_permission_manager =
+ GetPermissionControllerDelegate();
EXPECT_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::BACKGROUND_SYNC,
@@ -496,7 +496,8 @@ TEST_F(BackgroundSyncManagerTest, RegisterPermissionDenied) {
TEST_F(BackgroundSyncManagerTest, RegisterPermissionGranted) {
GURL expected_origin = GURL(kPattern1).GetOrigin();
- MockPermissionManager* mock_permission_manager = GetPermissionManager();
+ MockPermissionManager* mock_permission_manager =
+ GetPermissionControllerDelegate();
EXPECT_CALL(*mock_permission_manager,
GetPermissionStatus(PermissionType::BACKGROUND_SYNC,
@@ -652,14 +653,12 @@ TEST_F(BackgroundSyncManagerTest, SequentialOperations) {
bool get_registrations_called = false;
test_background_sync_manager_->Register(
sw_registration_id_1_, sync_options_1_,
- base::AdaptCallbackForRepeating(base::BindOnce(
- &BackgroundSyncManagerTest::StatusAndRegistrationCallback,
- base::Unretained(this), &register_called)));
+ base::BindOnce(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
+ base::Unretained(this), &register_called));
test_background_sync_manager_->GetRegistrations(
sw_registration_id_1_,
- base::AdaptCallbackForRepeating(base::BindOnce(
- &BackgroundSyncManagerTest::StatusAndRegistrationsCallback,
- base::Unretained(this), &get_registrations_called)));
+ base::BindOnce(&BackgroundSyncManagerTest::StatusAndRegistrationsCallback,
+ base::Unretained(this), &get_registrations_called));
base::RunLoop().RunUntilIdle();
// Init should be blocked while loading from the backend.
@@ -694,9 +693,8 @@ TEST_F(BackgroundSyncManagerTest,
bool callback_called = false;
test_background_sync_manager_->Register(
sw_registration_id_1_, sync_options_2_,
- base::AdaptCallbackForRepeating(base::BindOnce(
- &BackgroundSyncManagerTest::StatusAndRegistrationCallback,
- base::Unretained(this), &callback_called)));
+ base::BindOnce(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
+ base::Unretained(this), &callback_called));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(callback_called);
@@ -821,13 +819,14 @@ TEST_F(BackgroundSyncManagerTest, ReregisterMidSyncFirstAttemptFails) {
// The first sync attempt fails.
ASSERT_TRUE(sync_fired_callback_);
- std::move(sync_fired_callback_).Run(SERVICE_WORKER_ERROR_FAILED);
+ std::move(sync_fired_callback_)
+ .Run(blink::ServiceWorkerStatusCode::kErrorFailed);
base::RunLoop().RunUntilIdle();
// It should fire again since it was reregistered mid-sync.
EXPECT_TRUE(GetRegistration(sync_options_1_));
ASSERT_TRUE(sync_fired_callback_);
- std::move(sync_fired_callback_).Run(SERVICE_WORKER_OK);
+ std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
@@ -840,13 +839,13 @@ TEST_F(BackgroundSyncManagerTest, ReregisterMidSyncFirstAttemptSucceeds) {
// The first sync event succeeds.
ASSERT_TRUE(sync_fired_callback_);
- std::move(sync_fired_callback_).Run(SERVICE_WORKER_OK);
+ std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
base::RunLoop().RunUntilIdle();
// It should fire again since it was reregistered mid-sync.
EXPECT_TRUE(GetRegistration(sync_options_1_));
ASSERT_TRUE(sync_fired_callback_);
- std::move(sync_fired_callback_).Run(SERVICE_WORKER_OK);
+ std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
@@ -900,7 +899,7 @@ TEST_F(BackgroundSyncManagerTest, DisableWhileFiring) {
// Successfully complete the firing event. We can't verify that it actually
// completed but at least we can test that it doesn't crash.
ASSERT_TRUE(sync_fired_callback_);
- std::move(sync_fired_callback_).Run(SERVICE_WORKER_OK);
+ std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
base::RunLoop().RunUntilIdle();
}
@@ -989,7 +988,7 @@ TEST_F(BackgroundSyncManagerTest, DelayMidSync) {
// Finish firing the event and verify that the registration is removed.
ASSERT_TRUE(sync_fired_callback_);
- std::move(sync_fired_callback_).Run(SERVICE_WORKER_OK);
+ std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
@@ -1002,7 +1001,7 @@ TEST_F(BackgroundSyncManagerTest, BadBackendMidSync) {
test_background_sync_manager_->set_corrupt_backend(true);
ASSERT_TRUE(sync_fired_callback_);
- std::move(sync_fired_callback_).Run(SERVICE_WORKER_OK);
+ std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
base::RunLoop().RunUntilIdle();
// The backend should now be disabled because it couldn't unregister the
@@ -1019,7 +1018,7 @@ TEST_F(BackgroundSyncManagerTest, UnregisterServiceWorkerMidSync) {
UnregisterServiceWorker(sw_registration_id_1_);
ASSERT_TRUE(sync_fired_callback_);
- std::move(sync_fired_callback_).Run(SERVICE_WORKER_OK);
+ std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
// The backend isn't disabled, but the first service worker registration is
// gone.
@@ -1158,7 +1157,7 @@ TEST_F(BackgroundSyncManagerTest, WakeBrowserCalled) {
// Finish the sync.
ASSERT_TRUE(sync_fired_callback_);
- std::move(sync_fired_callback_).Run(SERVICE_WORKER_OK);
+ std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetController()->run_in_background_enabled());
}
@@ -1402,8 +1401,8 @@ TEST_F(BackgroundSyncManagerTest, EmulateOfflineMultipleClients) {
static void EmulateDispatchSyncEventCallback(
bool* was_called,
- ServiceWorkerStatusCode* code,
- ServiceWorkerStatusCode status_code) {
+ blink::ServiceWorkerStatusCode* code,
+ blink::ServiceWorkerStatusCode status_code) {
*was_called = true;
*code = status_code;
}
@@ -1411,13 +1410,14 @@ static void EmulateDispatchSyncEventCallback(
TEST_F(BackgroundSyncManagerTest, EmulateDispatchSyncEvent) {
InitSyncEventTest();
bool was_called = false;
- ServiceWorkerStatusCode code = SERVICE_WORKER_ERROR_MAX_VALUE;
+ blink::ServiceWorkerStatusCode code =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
background_sync_manager_->EmulateDispatchSyncEvent(
"emulated_tag", sw_registration_1_->active_version(), false,
base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- EXPECT_EQ(SERVICE_WORKER_OK, code);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, code);
EXPECT_EQ(1, sync_events_called_);
@@ -1425,36 +1425,34 @@ TEST_F(BackgroundSyncManagerTest, EmulateDispatchSyncEvent) {
true);
was_called = false;
- code = SERVICE_WORKER_ERROR_MAX_VALUE;
background_sync_manager_->EmulateDispatchSyncEvent(
"emulated_tag", sw_registration_1_->active_version(), false,
base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, code);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNetwork, code);
background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
false);
SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
was_called = false;
- code = SERVICE_WORKER_ERROR_MAX_VALUE;
+ code = blink::ServiceWorkerStatusCode::kOk;
background_sync_manager_->EmulateDispatchSyncEvent(
"emulated_tag", sw_registration_1_->active_version(), false,
base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, code);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNetwork, code);
SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
was_called = false;
- code = SERVICE_WORKER_ERROR_MAX_VALUE;
background_sync_manager_->EmulateDispatchSyncEvent(
"emulated_tag", sw_registration_1_->active_version(), false,
base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- EXPECT_EQ(SERVICE_WORKER_OK, code);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, code);
EXPECT_EQ(2, sync_events_called_);
}
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 aecf773c011..4f6d1aa3caf 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
@@ -41,19 +41,21 @@ const char kServiceWorkerScript[] = "https://example.com/a/script.js";
// Callbacks from SetUp methods
void RegisterServiceWorkerCallback(bool* called,
int64_t* store_registration_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
- EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
*called = true;
*store_registration_id = registration_id;
}
void FindServiceWorkerRegistrationCallback(
scoped_refptr<ServiceWorkerRegistration>* out_registration,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
- EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
*out_registration = std::move(registration);
}
@@ -126,7 +128,7 @@ class BackgroundSyncServiceImplTest : public testing::Test {
GetPermissionStatus(PermissionType::BACKGROUND_SYNC, _, _))
.WillByDefault(
testing::Return(blink::mojom::PermissionStatus::GRANTED));
- embedded_worker_helper_->browser_context()->SetPermissionManager(
+ embedded_worker_helper_->browser_context()->SetPermissionControllerDelegate(
std::move(mock_permission_manager));
}
@@ -167,15 +169,15 @@ class BackgroundSyncServiceImplTest : public testing::Test {
options.scope = GURL(kServiceWorkerPattern);
embedded_worker_helper_->context()->RegisterServiceWorker(
GURL(kServiceWorkerScript), options,
- base::AdaptCallbackForRepeating(base::BindOnce(
- &RegisterServiceWorkerCallback, &called, &sw_registration_id_)));
+ base::BindOnce(&RegisterServiceWorkerCallback, &called,
+ &sw_registration_id_));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
embedded_worker_helper_->context_wrapper()->FindReadyRegistrationForId(
sw_registration_id_, GURL(kServiceWorkerPattern).GetOrigin(),
- base::AdaptCallbackForRepeating(base::BindOnce(
- FindServiceWorkerRegistrationCallback, &sw_registration_)));
+ base::BindOnce(FindServiceWorkerRegistrationCallback,
+ &sw_registration_));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(sw_registration_);
}
diff --git a/chromium/content/browser/bad_message.h b/chromium/content/browser/bad_message.h
index 20115161d55..f5e39320ca6 100644
--- a/chromium/content/browser/bad_message.h
+++ b/chromium/content/browser/bad_message.h
@@ -199,9 +199,9 @@ enum BadMessageReason {
RFH_BASE_URL_FOR_DATA_URL_SPECIFIED = 171,
RFPH_ILLEGAL_UPLOAD_PARAMS = 172,
OBSOLETE_SWDH_PROVIDER_CREATED_ILLEGAL_TYPE = 173,
- SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_NOT_WINDOW = 174,
- SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_SERVICE_WORKER = 175,
- SWDH_PROVIDER_CREATED_DUPLICATE_ID = 176,
+ OBSOLETE_SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_NOT_WINDOW = 174,
+ OBSOLETE_SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_SERVICE_WORKER = 175,
+ OBSOLETE_SWDH_PROVIDER_CREATED_DUPLICATE_ID = 176,
OBSOLETE_SWDH_PROVIDER_CREATED_BAD_ID = 177,
RFH_KEEP_ALIVE_HANDLE_REQUESTED_INCORRECTLY = 178,
BFSI_INVALID_UNIQUE_ID = 179,
diff --git a/chromium/content/browser/battery_monitor_browsertest.cc b/chromium/content/browser/battery_monitor_browsertest.cc
index 47fd0272c78..ebbad43bd15 100644
--- a/chromium/content/browser/battery_monitor_browsertest.cc
+++ b/chromium/content/browser/battery_monitor_browsertest.cc
@@ -71,9 +71,7 @@ class MockBatteryMonitor : public device::mojom::BatteryMonitor {
class BatteryMonitorTest : public ContentBrowserTest {
public:
- BatteryMonitorTest() = default;
-
- void SetUpOnMainThread() override {
+ BatteryMonitorTest() {
mock_battery_monitor_ = std::make_unique<MockBatteryMonitor>();
// Because Device Service also runs in this process(browser process), here
// we can directly set our binder to intercept interface requests against
@@ -84,6 +82,11 @@ class BatteryMonitorTest : public ContentBrowserTest {
base::Unretained(mock_battery_monitor_.get())));
}
+ ~BatteryMonitorTest() override {
+ service_manager::ServiceContext::ClearGlobalBindersForTesting(
+ device::mojom::kServiceName);
+ }
+
protected:
MockBatteryMonitor* mock_battery_monitor() {
return mock_battery_monitor_.get();
diff --git a/chromium/content/browser/blob_storage/OWNERS b/chromium/content/browser/blob_storage/OWNERS
index e77e62a6a6f..49592325cf3 100644
--- a/chromium/content/browser/blob_storage/OWNERS
+++ b/chromium/content/browser/blob_storage/OWNERS
@@ -2,4 +2,4 @@ dmurph@chromium.org
mek@chromium.org
# TEAM: storage-dev@chromium.org
-# COMPONENT: Blink>FileAPI
+# COMPONENT: Blink>Storage>FileAPI
diff --git a/chromium/content/browser/blob_storage/blob_internals_url_loader.cc b/chromium/content/browser/blob_storage/blob_internals_url_loader.cc
index f41b5cdcf39..4c48d46dd28 100644
--- a/chromium/content/browser/blob_storage/blob_internals_url_loader.cc
+++ b/chromium/content/browser/blob_storage/blob_internals_url_loader.cc
@@ -22,7 +22,7 @@ void StartBlobInternalsURLLoader(
network::mojom::URLLoaderClientPtr client;
client.Bind(std::move(client_info));
- client->OnReceiveResponse(resource_response, nullptr);
+ client->OnReceiveResponse(resource_response);
std::string output = storage::ViewBlobInternalsJob::GenerateHTML(
blob_storage_context->context());
diff --git a/chromium/content/browser/blob_storage/blob_url_browsertest.cc b/chromium/content/browser/blob_storage/blob_url_browsertest.cc
index c74d2578ddf..dfb724f3c95 100644
--- a/chromium/content/browser/blob_storage/blob_url_browsertest.cc
+++ b/chromium/content/browser/blob_storage/blob_url_browsertest.cc
@@ -4,8 +4,10 @@
#include "base/macros.h"
#include "base/strings/pattern.h"
+#include "base/test/scoped_feature_list.h"
#include "build/build_config.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"
@@ -14,15 +16,20 @@
#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 "third_party/blink/public/common/features.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
// Tests of the blob: URL scheme.
-class BlobUrlBrowserTest : public ContentBrowserTest {
+class BlobUrlBrowserTest : public ContentBrowserTest,
+ public testing::WithParamInterface<bool> {
public:
- BlobUrlBrowserTest() {}
+ BlobUrlBrowserTest() {
+ if (GetParam())
+ scoped_feature_list_.InitAndEnableFeature(blink::features::kMojoBlobURLs);
+ }
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
@@ -31,10 +38,14 @@ class BlobUrlBrowserTest : public ContentBrowserTest {
}
private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+
DISALLOW_COPY_AND_ASSIGN(BlobUrlBrowserTest);
};
-IN_PROC_BROWSER_TEST_F(BlobUrlBrowserTest, LinkToUniqueOriginBlob) {
+INSTANTIATE_TEST_CASE_P(_, BlobUrlBrowserTest, ::testing::Bool());
+
+IN_PROC_BROWSER_TEST_P(BlobUrlBrowserTest, LinkToUniqueOriginBlob) {
// Use a data URL to obtain a test page in a unique origin. The page
// contains a link to a "blob:null/SOME-GUID-STRING" URL.
NavigateToURL(
@@ -68,7 +79,7 @@ IN_PROC_BROWSER_TEST_F(BlobUrlBrowserTest, LinkToUniqueOriginBlob) {
EXPECT_EQ("null potato", page_content);
}
-IN_PROC_BROWSER_TEST_F(BlobUrlBrowserTest, LinkToSameOriginBlob) {
+IN_PROC_BROWSER_TEST_P(BlobUrlBrowserTest, LinkToSameOriginBlob) {
// Using an http page, click a link that opens a popup to a same-origin blob.
GURL url = embedded_test_server()->GetURL("chromium.org", "/title1.html");
url::Origin origin = url::Origin::Create(url);
@@ -100,7 +111,7 @@ IN_PROC_BROWSER_TEST_F(BlobUrlBrowserTest, LinkToSameOriginBlob) {
}
// Regression test for https://crbug.com/646278
-IN_PROC_BROWSER_TEST_F(BlobUrlBrowserTest, LinkToSameOriginBlobWithAuthority) {
+IN_PROC_BROWSER_TEST_P(BlobUrlBrowserTest, LinkToSameOriginBlobWithAuthority) {
// Using an http page, click a link that opens a popup to a same-origin blob
// that has a spoofy authority section applied. This should be blocked.
GURL url = embedded_test_server()->GetURL("chromium.org", "/title1.html");
@@ -138,7 +149,7 @@ IN_PROC_BROWSER_TEST_F(BlobUrlBrowserTest, LinkToSameOriginBlobWithAuthority) {
}
// Regression test for https://crbug.com/646278
-IN_PROC_BROWSER_TEST_F(BlobUrlBrowserTest, ReplaceStateToAddAuthorityToBlob) {
+IN_PROC_BROWSER_TEST_P(BlobUrlBrowserTest, ReplaceStateToAddAuthorityToBlob) {
// history.replaceState from a validly loaded blob URL shouldn't allow adding
// an authority to the inner URL, which would be spoofy.
GURL url = embedded_test_server()->GetURL("chromium.org", "/title1.html");
diff --git a/chromium/content/browser/blob_storage/blob_url_loader_factory.cc b/chromium/content/browser/blob_storage/blob_url_loader_factory.cc
deleted file mode 100644
index 32904bea130..00000000000
--- a/chromium/content/browser/blob_storage/blob_url_loader_factory.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights 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_url_loader_factory.h"
-
-#include <stddef.h>
-#include <utility>
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "content/public/browser/browser_thread.h"
-#include "storage/browser/blob/blob_data_handle.h"
-#include "storage/browser/blob/blob_storage_context.h"
-#include "storage/browser/blob/blob_url_loader.h"
-
-namespace content {
-
-// static
-scoped_refptr<BlobURLLoaderFactory> BlobURLLoaderFactory::Create(
- BlobContextGetter blob_storage_context_getter) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- auto factory = base::MakeRefCounted<BlobURLLoaderFactory>();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&BlobURLLoaderFactory::InitializeOnIO, factory,
- std::move(blob_storage_context_getter)));
- return factory;
-}
-
-void BlobURLLoaderFactory::HandleRequest(
- network::mojom::URLLoaderFactoryRequest request) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&BlobURLLoaderFactory::BindOnIO, this,
- std::move(request)));
-}
-
-BlobURLLoaderFactory::BlobURLLoaderFactory() {}
-
-BlobURLLoaderFactory::~BlobURLLoaderFactory() {}
-
-void BlobURLLoaderFactory::InitializeOnIO(
- BlobContextGetter blob_storage_context_getter) {
- blob_storage_context_ = std::move(blob_storage_context_getter).Run();
-}
-
-void BlobURLLoaderFactory::BindOnIO(
- network::mojom::URLLoaderFactoryRequest request) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- loader_factory_bindings_.AddBinding(this, std::move(request));
-}
-
-// static
-void BlobURLLoaderFactory::CreateLoaderAndStart(
- network::mojom::URLLoaderRequest loader,
- const network::ResourceRequest& request,
- network::mojom::URLLoaderClientPtr client,
- std::unique_ptr<storage::BlobDataHandle> blob_handle) {
- storage::BlobURLLoader::CreateAndStart(
- std::move(loader), request, std::move(client), std::move(blob_handle));
-}
-
-void BlobURLLoaderFactory::CreateLoaderAndStart(
- network::mojom::URLLoaderRequest loader,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- const network::ResourceRequest& request,
- network::mojom::URLLoaderClientPtr client,
- const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
- DCHECK(!request.download_to_file);
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- std::unique_ptr<storage::BlobDataHandle> blob_handle;
- if (blob_storage_context_) {
- blob_handle = blob_storage_context_->GetBlobDataFromPublicURL(request.url);
- }
- CreateLoaderAndStart(std::move(loader), request, std::move(client),
- std::move(blob_handle));
-}
-
-void BlobURLLoaderFactory::Clone(
- network::mojom::URLLoaderFactoryRequest request) {
- loader_factory_bindings_.AddBinding(this, std::move(request));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/blob_storage/blob_url_loader_factory.h b/chromium/content/browser/blob_storage/blob_url_loader_factory.h
deleted file mode 100644
index 5f69c439c7e..00000000000
--- a/chromium/content/browser/blob_storage/blob_url_loader_factory.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2017 The Chromium Authors. All 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_URL_LOADER_FACTORY_H_
-#define CONTENT_BROWSER_BLOB_STORAGE_BLOB_URL_LOADER_FACTORY_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/browser_thread.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-
-namespace storage {
-class BlobDataHandle;
-class BlobStorageContext;
-}
-
-namespace content {
-
-// A class for creating URLLoaderFactory for blob scheme.
-// There should be one owned per StoragePartition.
-//
-// This class is deprecated, as it's impossible to use this to load blob URLs
-// without running into various race conditions between revoking blob URLs and
-// fetching them. Ultimately usage of this class will somehow be replaced with
-// usage of storage::BlobURLLoaderFactory.
-class BlobURLLoaderFactory
- : public base::RefCountedThreadSafe<BlobURLLoaderFactory,
- BrowserThread::DeleteOnIOThread>,
- public network::mojom::URLLoaderFactory {
- public:
- using BlobContextGetter =
- base::OnceCallback<base::WeakPtr<storage::BlobStorageContext>()>;
-
- static CONTENT_EXPORT scoped_refptr<BlobURLLoaderFactory> Create(
- BlobContextGetter blob_storage_context_getter);
-
- // Creates a URLLoaderFactory interface pointer for serving blob requests.
- // Called on the UI thread.
- void HandleRequest(network::mojom::URLLoaderFactoryRequest request);
-
- // Creates a URLLoader for given Blob UUID. This method is supposed to
- // be called on the IO thread.
- // Note that given |request|'s URL is not referenced, but only method and
- // range headers are used.
- static void CreateLoaderAndStart(
- network::mojom::URLLoaderRequest url_loader_request,
- const network::ResourceRequest& request,
- network::mojom::URLLoaderClientPtr client,
- std::unique_ptr<storage::BlobDataHandle> blob_handle);
-
- // network::mojom::URLLoaderFactory implementation:
- void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- const network::ResourceRequest& request,
- network::mojom::URLLoaderClientPtr client,
- const net::MutableNetworkTrafficAnnotationTag&
- traffic_annotation) override;
- void Clone(network::mojom::URLLoaderFactoryRequest request) override;
-
- private:
- friend class base::DeleteHelper<BlobURLLoaderFactory>;
- friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
- template <typename T, typename... Args>
- friend scoped_refptr<T> base::MakeRefCounted(Args&&... args);
-
- BlobURLLoaderFactory();
- ~BlobURLLoaderFactory() override;
-
- void InitializeOnIO(BlobContextGetter blob_storage_context_getter);
- void BindOnIO(network::mojom::URLLoaderFactoryRequest request);
-
- base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
-
- // Used on the IO thread.
- mojo::BindingSet<network::mojom::URLLoaderFactory> loader_factory_bindings_;
-
- DISALLOW_COPY_AND_ASSIGN(BlobURLLoaderFactory);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_BLOB_STORAGE_BLOB_URL_LOADER_FACTORY_H_
diff --git a/chromium/content/browser/blob_storage/blob_url_unittest.cc b/chromium/content/browser/blob_storage/blob_url_unittest.cc
index e7d27de9650..702da3728bd 100644
--- a/chromium/content/browser/blob_storage/blob_url_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_url_unittest.cc
@@ -17,7 +17,6 @@
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
-#include "content/browser/blob_storage/blob_url_loader_factory.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
@@ -102,7 +101,8 @@ disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache,
const std::string& data) {
disk_cache::Entry* temp_entry = nullptr;
net::TestCompletionCallback callback;
- int rv = cache->CreateEntry(key, &temp_entry, callback.callback());
+ int rv =
+ cache->CreateEntry(key, net::HIGHEST, &temp_entry, callback.callback());
if (callback.GetResult(rv) != net::OK)
return nullptr;
disk_cache::ScopedEntryPtr entry(temp_entry);
@@ -130,7 +130,6 @@ disk_cache::ScopedEntryPtr CreateDiskCacheEntryWithSideData(
}
enum class RequestTestType {
- kNetworkServiceRequest,
kNetRequest,
kRequestFromBlobImpl
};
@@ -284,34 +283,6 @@ class BlobURLRequestJobTest : public testing::TestWithParam<RequestTestType> {
request.headers = extra_headers;
switch (GetParam()) {
- case RequestTestType::kNetworkServiceRequest: {
- GetHandleFromBuilder(); // To add to StorageContext.
- const_cast<storage::BlobStorageRegistry&>(blob_context_.registry())
- .CreateUrlMapping(url, blob_uuid_);
-
- network::mojom::URLLoaderPtr url_loader;
- network::TestURLLoaderClient url_loader_client;
- scoped_refptr<BlobURLLoaderFactory> factory =
- BlobURLLoaderFactory::Create(
- base::BindOnce(&BlobURLRequestJobTest::GetStorageContext,
- base::Unretained(this)));
- base::RunLoop().RunUntilIdle();
- factory->CreateLoaderAndStart(mojo::MakeRequest(&url_loader), 0, 0,
- network::mojom::kURLLoadOptionNone,
- request,
- url_loader_client.CreateInterfacePtr(),
- net::MutableNetworkTrafficAnnotationTag(
- TRAFFIC_ANNOTATION_FOR_TESTS));
- url_loader_client.RunUntilComplete();
-
- if (url_loader_client.response_body().is_valid()) {
- EXPECT_TRUE(mojo::BlockingCopyToString(
- url_loader_client.response_body_release(), &response_));
- }
- response_headers_ = url_loader_client.response_head().headers;
- response_metadata_ = url_loader_client.cached_metadata();
- response_error_code_ = url_loader_client.completion_status().error_code;
- } break;
case RequestTestType::kNetRequest: {
std::unique_ptr<net::URLRequest> request =
url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY,
@@ -719,8 +690,7 @@ TEST_P(BlobURLRequestJobTest, BrokenBlob) {
INSTANTIATE_TEST_CASE_P(
BlobURLRequestJobTest,
BlobURLRequestJobTest,
- ::testing::Values(RequestTestType::kNetworkServiceRequest,
- RequestTestType::kNetRequest,
+ ::testing::Values(RequestTestType::kNetRequest,
RequestTestType::kRequestFromBlobImpl));
} // namespace content
diff --git a/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc b/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
index 17347dbfd10..0900dbb6898 100644
--- a/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
+++ b/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
@@ -197,6 +197,49 @@ ChromeBlobStorageContext::URLLoaderFactoryForToken(
std::move(blob_url_loader_factory_ptr));
}
+// static
+scoped_refptr<network::SharedURLLoaderFactory>
+ChromeBlobStorageContext::URLLoaderFactoryForUrl(
+ BrowserContext* browser_context,
+ const GURL& url) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ network::mojom::URLLoaderFactoryPtr blob_url_loader_factory_ptr;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ [](scoped_refptr<ChromeBlobStorageContext> context,
+ network::mojom::URLLoaderFactoryRequest request, const GURL& url) {
+ auto blob_handle =
+ context->context()->GetBlobDataFromPublicURL(url);
+ storage::BlobURLLoaderFactory::Create(std::move(blob_handle), url,
+ std::move(request));
+ },
+ base::WrapRefCounted(GetFor(browser_context)),
+ MakeRequest(&blob_url_loader_factory_ptr), url));
+ return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(blob_url_loader_factory_ptr));
+}
+
+// static
+blink::mojom::BlobPtr ChromeBlobStorageContext::GetBlobPtr(
+ BrowserContext* browser_context,
+ const std::string& uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ blink::mojom::BlobPtr blob_ptr;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ [](scoped_refptr<ChromeBlobStorageContext> context,
+ blink::mojom::BlobRequest request, const std::string& uuid) {
+ auto handle = context->context()->GetBlobDataFromUUID(uuid);
+ if (handle)
+ storage::BlobImpl::Create(std::move(handle), std::move(request));
+ },
+ base::WrapRefCounted(GetFor(browser_context)), MakeRequest(&blob_ptr),
+ uuid));
+ return blob_ptr;
+}
+
ChromeBlobStorageContext::~ChromeBlobStorageContext() {}
void ChromeBlobStorageContext::DeleteOnCorrectThread() const {
diff --git a/chromium/content/browser/blob_storage/chrome_blob_storage_context.h b/chromium/content/browser/blob_storage/chrome_blob_storage_context.h
index 812a6a5cebe..26cf1ebfdff 100644
--- a/chromium/content/browser/blob_storage/chrome_blob_storage_context.h
+++ b/chromium/content/browser/blob_storage/chrome_blob_storage_context.h
@@ -65,11 +65,32 @@ class CONTENT_EXPORT ChromeBlobStorageContext
size_t length,
const std::string& content_type);
+ // Returns a SharedURLLoaderFactory capable of creating URLLoaders for exactly
+ // the one URL associated with the passed in |token|. Attempting to load any
+ // other URL through the factory will result in an error. If the |token|
+ // itself is invalid all requests will result in errors.
// Must be called on the UI thread.
static scoped_refptr<network::SharedURLLoaderFactory>
URLLoaderFactoryForToken(BrowserContext* browser_context,
blink::mojom::BlobURLTokenPtr token);
+ // Similar to the above method this also returns a factory capable of loading
+ // a single (blob) URL. If the |url| isn't a valid/registered blob URL at the
+ // time this method is called, using the resulting factory will always result
+ // in an error.
+ // Generally you should prefer using the above method and pass around a
+ // BlobURLToken rather than a blob URL. This is because the BlobURLToken will
+ // ensure that the URL and the blob it refers to stay alive, while merely
+ // holding on to the URL has no such guarantees.
+ // Must be called on the UI thread.
+ static scoped_refptr<network::SharedURLLoaderFactory> URLLoaderFactoryForUrl(
+ BrowserContext* browser_context,
+ const GURL& url);
+
+ // Must be called on the UI thread.
+ static blink::mojom::BlobPtr GetBlobPtr(BrowserContext* browser_context,
+ const std::string& uuid);
+
protected:
virtual ~ChromeBlobStorageContext();
diff --git a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
index 4d08d443e55..bea76778640 100644
--- a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
@@ -281,8 +281,7 @@ BluetoothDeviceChooserController::BluetoothDeviceChooserController(
base::Bind(&BluetoothDeviceChooserController::StopDeviceDiscovery,
// base::Timer guarantees it won't call back after its
// destructor starts.
- base::Unretained(this)),
- /*is_repeating=*/false),
+ base::Unretained(this))),
weak_ptr_factory_(this) {
CHECK(adapter_);
}
diff --git a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h
index 54eb7a113e2..b2e16cb09f8 100644
--- a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h
+++ b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h
@@ -147,7 +147,7 @@ class CONTENT_EXPORT BluetoothDeviceChooserController final {
// Automatically stops Bluetooth discovery a set amount of time after it was
// started.
- base::Timer discovery_session_timer_;
+ base::RetainingOneShotTimer discovery_session_timer_;
// The last discovery session to be started.
// TODO(ortuno): This should be null unless there is an active discovery
diff --git a/chromium/content/browser/bluetooth/tools/BUILD.gn b/chromium/content/browser/bluetooth/tools/BUILD.gn
index 8615c6dfef0..4971caa1715 100644
--- a/chromium/content/browser/bluetooth/tools/BUILD.gn
+++ b/chromium/content/browser/bluetooth/tools/BUILD.gn
@@ -9,7 +9,6 @@ executable("bluetooth_metrics_hash") {
deps = [
"//base",
- "//build/config:exe_and_shlib_deps",
"//build/win:default_exe_manifest",
"//device/bluetooth",
]
diff --git a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
index cda94e43e86..f061eca7c86 100644
--- a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -1242,6 +1242,10 @@ BluetoothAllowedDevices& WebBluetoothServiceImpl::allowed_devices() {
}
void WebBluetoothServiceImpl::ClearState() {
+ // Releasing the adapter will drop references to callbacks that have not yet
+ // been executed. The binding must be closed first so that this is allowed.
+ binding_.Close();
+
characteristic_id_to_notify_session_.clear();
pending_primary_services_requests_.clear();
descriptor_id_to_characteristic_id_.clear();
diff --git a/chromium/content/browser/browser_child_process_host_impl.cc b/chromium/content/browser/browser_child_process_host_impl.cc
index 1686c7a9f2b..3fc3aa2f44c 100644
--- a/chromium/content/browser/browser_child_process_host_impl.cc
+++ b/chromium/content/browser/browser_child_process_host_impl.cc
@@ -47,7 +47,6 @@
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "content/public/common/service_manager_connection.h"
-#include "mojo/edk/embedder/embedder.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "services/service_manager/embedder/switches.h"
@@ -153,7 +152,6 @@ BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
const std::string& service_name)
: data_(process_type),
delegate_(delegate),
- broker_client_invitation_(new mojo::edk::OutgoingBrokerClientInvitation),
channel_(nullptr),
is_channel_connected_(false),
notify_child_disconnected_(false),
@@ -172,9 +170,10 @@ BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
service_name, service_manager::mojom::kInheritUserID,
base::StringPrintf("%d", data_.id));
child_connection_.reset(
- new ChildConnection(child_identity, broker_client_invitation_.get(),
+ new ChildConnection(child_identity, &mojo_invitation_,
ServiceManagerContext::GetConnectorForIOThread(),
base::ThreadTaskRunnerHandle::Get()));
+ data_.metrics_name = service_name;
}
// Create a persistent memory segment for subprocess histograms.
@@ -267,11 +266,13 @@ void BrowserChildProcessHostImpl::Launch(
child_connection_->service_token());
}
- DCHECK(broker_client_invitation_);
+ // All processes should have a non-empty metrics name.
+ DCHECK(!data_.metrics_name.empty());
+
notify_child_disconnected_ = true;
child_process_.reset(new ChildProcessLauncher(
std::move(delegate), std::move(cmd_line), data_.id, this,
- std::move(broker_client_invitation_),
+ std::move(mojo_invitation_),
base::Bind(&BrowserChildProcessHostImpl::OnMojoError,
weak_factory_.GetWeakPtr(),
base::ThreadTaskRunnerHandle::Get()),
@@ -307,6 +308,12 @@ void BrowserChildProcessHostImpl::SetName(const base::string16& name) {
data_.name = name;
}
+void BrowserChildProcessHostImpl::SetMetricsName(
+ const std::string& metrics_name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ data_.metrics_name = metrics_name;
+}
+
void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
data_.handle = handle;
@@ -314,11 +321,9 @@ void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) {
service_manager::mojom::ServiceRequest
BrowserChildProcessHostImpl::TakeInProcessServiceRequest() {
- DCHECK(broker_client_invitation_);
- auto invitation = std::move(broker_client_invitation_);
+ auto invitation = std::move(mojo_invitation_);
return service_manager::mojom::ServiceRequest(
- invitation->ExtractInProcessMessagePipe(
- child_connection_->service_token()));
+ invitation.ExtractMessagePipe(child_connection_->service_token()));
}
void BrowserChildProcessHostImpl::ForceShutdown() {
diff --git a/chromium/content/browser/browser_child_process_host_impl.h b/chromium/content/browser/browser_child_process_host_impl.h
index ee21de31936..39c277f11ea 100644
--- a/chromium/content/browser/browser_child_process_host_impl.h
+++ b/chromium/content/browser/browser_child_process_host_impl.h
@@ -22,7 +22,7 @@
#include "content/public/browser/browser_child_process_host.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/common/child_process_host_delegate.h"
-#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
+#include "mojo/public/cpp/system/invitation.h"
#if defined(OS_WIN)
#include "base/win/object_watcher.h"
@@ -79,6 +79,7 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
std::unique_ptr<base::SharedPersistentMemoryAllocator> TakeMetricsAllocator()
override;
void SetName(const base::string16& name) override;
+ void SetMetricsName(const std::string& metrics_name) override;
void SetHandle(base::ProcessHandle handle) override;
service_manager::mojom::ServiceRequest TakeInProcessServiceRequest() override;
@@ -111,9 +112,8 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
return child_connection_.get();
}
- mojo::edk::OutgoingBrokerClientInvitation*
- GetInProcessBrokerClientInvitation() {
- return broker_client_invitation_.get();
+ mojo::OutgoingInvitation* GetInProcessMojoInvitation() {
+ return &mojo_invitation_;
}
IPC::Channel* child_channel() const { return channel_; }
@@ -155,11 +155,11 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
#endif
ChildProcessData data_;
+ std::string metrics_name_;
BrowserChildProcessHostDelegate* delegate_;
std::unique_ptr<ChildProcessHost> child_process_host_;
- std::unique_ptr<mojo::edk::OutgoingBrokerClientInvitation>
- broker_client_invitation_;
+ mojo::OutgoingInvitation mojo_invitation_;
std::unique_ptr<ChildConnection> child_connection_;
std::unique_ptr<ChildProcessLauncher> child_process_;
diff --git a/chromium/content/browser/browser_context.cc b/chromium/content/browser/browser_context.cc
index 69271e39f27..199a676de55 100644
--- a/chromium/content/browser/browser_context.cc
+++ b/chromium/content/browser/browser_context.cc
@@ -23,14 +23,17 @@
#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
#include "base/task_scheduler/post_task.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browsing_data/browsing_data_remover_impl.h"
+#include "content/browser/content_service_delegate_impl.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/push_messaging/push_messaging_router.h"
#include "content/browser/service_manager/common_browser_interfaces.h"
#include "content/browser/storage_partition_impl_map.h"
@@ -51,6 +54,8 @@
#include "net/ssl/channel_id_store.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/content/public/mojom/constants.mojom.h"
+#include "services/content/service.h"
#include "services/file/file_service.h"
#include "services/file/public/mojom/constants.mojom.h"
#include "services/file/user_id_map.h"
@@ -84,8 +89,24 @@ class ServiceUserIdHolder : public base::SupportsUserData::Data {
DISALLOW_COPY_AND_ASSIGN(ServiceUserIdHolder);
};
+class ContentServiceDelegateHolder : public base::SupportsUserData::Data {
+ public:
+ explicit ContentServiceDelegateHolder(BrowserContext* browser_context)
+ : delegate_(browser_context) {}
+ ~ContentServiceDelegateHolder() override = default;
+
+ ContentServiceDelegateImpl* delegate() { return &delegate_; }
+
+ private:
+ ContentServiceDelegateImpl delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentServiceDelegateHolder);
+};
+
// Key names on BrowserContext.
const char kBrowsingDataRemoverKey[] = "browsing-data-remover";
+const char kContentServiceDelegateKey[] = "content-service-delegate";
+const char kPermissionControllerKey[] = "permission-controller";
const char kDownloadManagerKeyName[] = "download_manager";
const char kMojoWasInitialized[] = "mojo-was-initialized";
const char kServiceManagerConnection[] = "service-manager-connection";
@@ -269,6 +290,20 @@ content::BrowsingDataRemover* content::BrowserContext::GetBrowsingDataRemover(
context->GetUserData(kBrowsingDataRemoverKey));
}
+// static
+content::PermissionController* content::BrowserContext::GetPermissionController(
+ BrowserContext* context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!context->GetUserData(kPermissionControllerKey)) {
+ context->SetUserData(kPermissionControllerKey,
+ std::make_unique<PermissionControllerImpl>(context));
+ }
+
+ return static_cast<PermissionControllerImpl*>(
+ context->GetUserData(kPermissionControllerKey));
+}
+
StoragePartition* BrowserContext::GetStoragePartition(
BrowserContext* browser_context,
SiteInstance* site_instance,
@@ -349,6 +384,14 @@ BrowserContext::BlobContextGetter BrowserContext::GetBlobStorageContext(
}
// static
+blink::mojom::BlobPtr BrowserContext::GetBlobPtr(
+ BrowserContext* browser_context,
+ const std::string& uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return ChromeBlobStorageContext::GetBlobPtr(browser_context, uuid);
+}
+
+// static
void BrowserContext::DeliverPushMessage(
BrowserContext* browser_context,
const GURL& origin,
@@ -371,6 +414,12 @@ void BrowserContext::NotifyWillBeDestroyed(BrowserContext* browser_context) {
return;
browser_context->was_notify_will_be_destroyed_called_ = true;
+ // Subclasses of BrowserContext may expect there to be no more
+ // RenderProcessHosts using them by the time this function returns. We
+ // therefore explicitly tear down embedded Content Service instances now to
+ // ensure that all their WebContents (and therefore RPHs) are torn down too.
+ browser_context->RemoveUserData(kContentServiceDelegateKey);
+
// Service Workers must shutdown before the browser context is destroyed,
// since they keep render process hosts alive and the codebase assumes that
// render process hosts die before their profile (browser context) dies.
@@ -419,13 +468,14 @@ void BrowserContext::SaveSessionState(BrowserContext* browser_context) {
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&SaveSessionStateOnIOThread,
- base::WrapRefCounted(
- BrowserContext::GetDefaultStoragePartition(browser_context)
- ->GetURLRequestContext()),
+ base::WrapRefCounted(storage_partition->GetURLRequestContext()),
static_cast<AppCacheServiceImpl*>(
storage_partition->GetAppCacheService())));
}
+ storage_partition->GetCookieManagerForBrowserProcess()
+ ->SetForceKeepSessionState();
+
DOMStorageContextWrapper* dom_storage_context_proxy =
static_cast<DOMStorageContextWrapper*>(
storage_partition->GetDOMStorageContext());
@@ -502,9 +552,32 @@ void BrowserContext::Initialize(
// New embedded service factories should be added to |connection| here.
- service_manager::EmbeddedServiceInfo info;
- info.factory = base::BindRepeating(&file::CreateFileService);
- connection->AddEmbeddedService(file::mojom::kServiceName, info);
+ {
+ service_manager::EmbeddedServiceInfo info;
+ info.factory = base::BindRepeating(&file::CreateFileService);
+ connection->AddEmbeddedService(file::mojom::kServiceName, info);
+ }
+
+ browser_context->SetUserData(
+ kContentServiceDelegateKey,
+ std::make_unique<ContentServiceDelegateHolder>(browser_context));
+
+ {
+ service_manager::EmbeddedServiceInfo info;
+ info.task_runner = base::SequencedTaskRunnerHandle::Get();
+ info.factory = base::BindRepeating(
+ [](BrowserContext* context)
+ -> std::unique_ptr<service_manager::Service> {
+ auto* holder = static_cast<ContentServiceDelegateHolder*>(
+ context->GetUserData(kContentServiceDelegateKey));
+ auto* delegate = holder->delegate();
+ auto service = std::make_unique<content::Service>(delegate);
+ delegate->AddService(service.get());
+ return service;
+ },
+ browser_context);
+ connection->AddEmbeddedService(content::mojom::kServiceName, info);
+ }
ContentBrowserClient::StaticServiceMap services;
browser_context->RegisterInProcessServices(&services);
@@ -519,7 +592,7 @@ void BrowserContext::Initialize(
if (!browser_context->IsOffTheRecord()) {
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
- logger->EnableForBrowserContext(browser_context);
+ logger->EnableForBrowserContext(browser_context, base::OnceClosure());
}
}
}
@@ -576,7 +649,7 @@ BrowserContext::~BrowserContext() {
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
- logger->DisableForBrowserContext(this);
+ logger->DisableForBrowserContext(this, base::OnceClosure());
}
RemoveBrowserContextFromUserIdMap(this);
diff --git a/chromium/content/browser/browser_main.cc b/chromium/content/browser/browser_main.cc
index f06e59b43ff..65668ab3f5f 100644
--- a/chromium/content/browser/browser_main.cc
+++ b/chromium/content/browser/browser_main.cc
@@ -8,7 +8,6 @@
#include "base/trace_event/trace_event.h"
#include "content/browser/browser_main_runner_impl.h"
-#include "content/browser/browser_process_sub_thread.h"
#include "content/common/content_constants_internal.h"
namespace content {
@@ -31,9 +30,7 @@ class ScopedBrowserMainEvent {
} // namespace
// Main routine for running as the Browser process.
-int BrowserMain(
- const MainFunctionParams& parameters,
- std::unique_ptr<BrowserProcessSubThread> service_manager_thread) {
+int BrowserMain(const MainFunctionParams& parameters) {
ScopedBrowserMainEvent scoped_browser_main_event;
base::trace_event::TraceLog::GetInstance()->set_process_name("Browser");
@@ -43,8 +40,7 @@ int BrowserMain(
std::unique_ptr<BrowserMainRunnerImpl> main_runner(
BrowserMainRunnerImpl::Create());
- int exit_code =
- main_runner->Initialize(parameters, std::move(service_manager_thread));
+ int exit_code = main_runner->Initialize(parameters);
if (exit_code >= 0)
return exit_code;
diff --git a/chromium/content/browser/browser_main.h b/chromium/content/browser/browser_main.h
index 02f3af601fe..c4a5c719ff0 100644
--- a/chromium/content/browser/browser_main.h
+++ b/chromium/content/browser/browser_main.h
@@ -11,12 +11,9 @@
namespace content {
-class BrowserProcessSubThread;
struct MainFunctionParams;
-CONTENT_EXPORT int BrowserMain(
- const content::MainFunctionParams& parameters,
- std::unique_ptr<BrowserProcessSubThread> service_manager_thread);
+CONTENT_EXPORT int BrowserMain(const content::MainFunctionParams& parameters);
} // namespace content
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index 10de251accf..eb942391306 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -16,7 +16,6 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/alias.h"
-#include "base/debug/stack_trace.h"
#include "base/deferred_sequenced_task_runner.h"
#include "base/feature_list.h"
#include "base/location.h"
@@ -28,6 +27,7 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
+#include "base/path_service.h"
#include "base/pending_task.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_device_source.h"
@@ -47,6 +47,7 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "cc/base/histograms.h"
#include "components/discardable_memory/service/discardable_shared_memory_manager.h"
#include "components/tracing/common/trace_startup_config.h"
#include "components/tracing/common/trace_to_console.h"
@@ -63,6 +64,7 @@
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/compositor/viz_process_transport_factory.h"
#include "content/browser/dom_storage/dom_storage_area.h"
+#include "content/browser/dom_storage/storage_area_impl.h"
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/download/save_file_manager.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
@@ -72,7 +74,6 @@
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/browser/histogram_synchronizer.h"
-#include "content/browser/leveldb_wrapper_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader_delegate_impl.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
@@ -84,6 +85,7 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/service_manager/service_manager_context.h"
#include "content/browser/speech/speech_recognition_manager_impl.h"
+#include "content/browser/startup_data_impl.h"
#include "content/browser/startup_task_runner.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/tracing/tracing_controller_impl.h"
@@ -108,6 +110,7 @@
#include "content/public/common/result_codes.h"
#include "content/public/common/service_names.mojom.h"
#include "device/gamepad/gamepad_service.h"
+#include "gpu/config/gpu_switches.h"
#include "media/audio/audio_manager.h"
#include "media/audio/audio_system.h"
#include "media/audio/audio_thread_impl.h"
@@ -116,8 +119,8 @@
#include "media/media_buildflags.h"
#include "media/midi/midi_service.h"
#include "media/mojo/buildflags.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/scoped_ipc_support.h"
+#include "mojo/core/embedder/embedder.h"
+#include "mojo/core/embedder/scoped_ipc_support.h"
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
#include "net/base/network_change_notifier.h"
#include "net/socket/client_socket_factory.h"
@@ -136,6 +139,7 @@
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/ui_base_features.h"
#include "ui/display/display_switches.h"
+#include "ui/gfx/font_render_params.h"
#include "ui/gfx/switches.h"
#if defined(USE_AURA) || defined(OS_MACOSX)
@@ -201,10 +205,10 @@
#endif
#if defined(OS_FUCHSIA)
-#include <zircon/process.h>
-#include <zircon/syscalls.h>
+#include <lib/zx/job.h>
#include "base/fuchsia/default_job.h"
+#include "base/fuchsia/fuchsia_logging.h"
#endif // defined(OS_FUCHSIA)
#if defined(OS_POSIX) && !defined(OS_MACOSX)
@@ -230,8 +234,8 @@
#include "crypto/nss_util.h"
#endif
-#if BUILDFLAG(ENABLE_MUS)
-#include "services/ui/common/image_cursors_set.h"
+#if defined(ENABLE_IPC_FUZZER) && defined(OS_MACOSX)
+#include "base/mac/foundation_util.h"
#endif
// One of the linux specific headers defines this as a macro.
@@ -261,12 +265,6 @@ static void GLibLogHandler(const gchar* log_domain,
LOG(DFATAL) << log_domain << ": " << message;
} else if (log_level & (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL)) {
LOG(ERROR) << log_domain << ": " << message;
-#if defined(THREAD_SANITIZER)
- // TODO(thomasanderson): This is temporary debugging for
- // https://crbug.com/821704. Revert this CL once we have the stack trace:
- // https://chromium-review.googlesource.com/#/c/chromium/src/+/1069247
- base::debug::StackTrace().Print();
-#endif
} else if (log_level & (G_LOG_LEVEL_WARNING)) {
LOG(WARNING) << log_domain << ": " << message;
} else if (log_level &
@@ -397,14 +395,47 @@ constexpr base::TimeDelta kSwapMetricsInterval =
// Create and register the job which will contain all child processes
// of the browser process as well as their descendents.
void InitDefaultJob() {
- base::ScopedZxHandle handle;
- zx_status_t result = zx_job_create(zx_job_default(), 0, handle.receive());
- CHECK_EQ(ZX_OK, result) << "zx_job_create(job): "
- << zx_status_get_string(result);
- base::SetDefaultJob(std::move(handle));
+ zx::job job;
+ zx_status_t result = zx::job::create(*zx::job::default_job(), 0, &job);
+ ZX_CHECK(ZX_OK == result, result) << "zx_job_create";
+ base::SetDefaultJob(std::move(job));
}
#endif // defined(OS_FUCHSIA)
+#if defined(ENABLE_IPC_FUZZER)
+bool GetBuildDirectory(base::FilePath* result) {
+ if (!base::PathService::Get(base::DIR_EXE, result))
+ return false;
+
+#if defined(OS_MACOSX)
+ if (base::mac::AmIBundled()) {
+ // The bundled app executables (Chromium, TestShell, etc) live three
+ // levels down from the build directory, eg:
+ // Chromium.app/Contents/MacOS/Chromium
+ *result = result->DirName().DirName().DirName();
+ }
+#endif
+ return true;
+}
+
+void SetFileUrlPathAliasForIpcFuzzer() {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kFileUrlPathAlias))
+ return;
+
+ base::FilePath build_directory;
+ if (!GetBuildDirectory(&build_directory)) {
+ LOG(ERROR) << "Failed to get build directory for /gen path alias.";
+ return;
+ }
+
+ const base::CommandLine::StringType alias_switch =
+ FILE_PATH_LITERAL("/gen=") + build_directory.AppendASCII("gen").value();
+ base::CommandLine::ForCurrentProcess()->AppendSwitchNative(
+ switches::kFileUrlPathAlias, alias_switch);
+}
+#endif
+
} // namespace
#if defined(USE_X11)
@@ -503,6 +534,11 @@ BrowserMainLoop* BrowserMainLoop::GetInstance() {
return g_current_browser_main_loop;
}
+// static
+media::AudioManager* BrowserMainLoop::GetAudioManager() {
+ return g_current_browser_main_loop->audio_manager();
+}
+
BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters)
: parameters_(parameters),
parsed_command_line_(parameters.command_line),
@@ -512,9 +548,7 @@ BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters)
g_current_browser_main_loop = this;
if (GetContentClient()->browser()->ShouldCreateTaskScheduler()) {
- // Use an empty string as TaskScheduler name to match the suffix of browser
- // process TaskScheduler histograms.
- base::TaskScheduler::Create("Browser");
+ DCHECK(base::TaskScheduler::GetInstance());
}
}
@@ -524,13 +558,20 @@ BrowserMainLoop::~BrowserMainLoop() {
g_current_browser_main_loop = nullptr;
}
-void BrowserMainLoop::Init(
- std::unique_ptr<BrowserProcessSubThread> service_manager_thread) {
+void BrowserMainLoop::Init() {
TRACE_EVENT0("startup", "BrowserMainLoop::Init");
- // This is always invoked before |io_thread_| is initialized (i.e. never
- // resets it).
- io_thread_ = std::move(service_manager_thread);
+ // |startup_data| is optional. If set, the thread owned by the data
+ // will be registered as BrowserThread::IO in CreateThreads() instead of
+ // creating a brand new thread.
+ if (parameters_.startup_data) {
+ StartupDataImpl* startup_data =
+ static_cast<StartupDataImpl*>(parameters_.startup_data);
+ // This is always invoked before |io_thread_| is initialized (i.e. never
+ // resets it).
+ io_thread_ = std::move(startup_data->thread);
+ }
+
parts_.reset(
GetContentClient()->browser()->CreateBrowserMainParts(parameters_));
}
@@ -597,6 +638,17 @@ int BrowserMainLoop::EarlyInitialization() {
command_line->GetSwitchValueASCII(switches::kDisableFeatures));
}
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+ // Up the priority of the UI thread unless it was already high (since recent
+ // versions of Android (O+) do this automatically).
+ if (base::PlatformThread::GetCurrentThreadPriority() <
+ base::ThreadPriority::DISPLAY ||
+ base::FeatureList::IsEnabled(features::kOverrideUIThreadPriority)) {
+ base::PlatformThread::SetCurrentThreadPriority(
+ base::ThreadPriority::DISPLAY);
+ }
+#endif // defined(OS_ANDROID) || defined(OS_CHROMEOS)
+
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
defined(OS_ANDROID)
// We use quite a few file descriptors for our IPC as well as disk the disk
@@ -652,9 +704,8 @@ void BrowserMainLoop::MainMessageLoopStart() {
TRACE_EVENT0("startup", "BrowserMainLoop::MainMessageLoopStart");
- // Create a MessageLoop if one does not already exist for the current thread.
- if (!base::MessageLoopCurrent::Get())
- main_message_loop_.reset(new base::MessageLoopForUI);
+ if (!base::MessageLoopCurrentForUI::IsSet())
+ main_message_loop_ = std::make_unique<base::MessageLoopForUI>();
InitializeMainThread();
}
@@ -706,7 +757,7 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
}
- if (!base::FeatureList::IsEnabled(::features::kMash)) {
+ if (features::IsAshInBrowserProcess()) {
discardable_shared_memory_manager_ =
std::make_unique<discardable_memory::DiscardableSharedMemoryManager>();
// TODO(boliu): kSingleProcess check is a temporary workaround for
@@ -744,14 +795,18 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
TRACE_EVENT0("startup",
"BrowserMainLoop::Subsystem:EnableAggressiveCommitDelay");
DOMStorageArea::EnableAggressiveCommitDelay();
- LevelDBWrapperImpl::EnableAggressiveCommitDelay();
+ StorageAreaImpl::EnableAggressiveCommitDelay();
}
// Enable memory-infra dump providers.
InitSkiaEventTracer();
- base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
- viz::ServerSharedBitmapManager::current(),
- "viz::ServerSharedBitmapManager", nullptr);
+#if !defined(OS_ANDROID)
+ if (server_shared_bitmap_manager_) {
+ base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+ server_shared_bitmap_manager_.get(), "viz::ServerSharedBitmapManager",
+ base::ThreadTaskRunnerHandle::Get());
+ }
+#endif
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
skia::SkiaMemoryDumpProvider::GetInstance(), "Skia", nullptr);
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
@@ -836,10 +891,11 @@ void BrowserMainLoop::CreateStartupTasks() {
DCHECK(!startup_task_runner_);
#if defined(OS_ANDROID)
startup_task_runner_ = std::make_unique<StartupTaskRunner>(
- base::Bind(&BrowserStartupComplete), base::ThreadTaskRunnerHandle::Get());
+ base::BindOnce(&BrowserStartupComplete),
+ base::ThreadTaskRunnerHandle::Get());
#else
startup_task_runner_ = std::make_unique<StartupTaskRunner>(
- base::Callback<void(int)>(), base::ThreadTaskRunnerHandle::Get());
+ base::OnceCallback<void(int)>(), base::ThreadTaskRunnerHandle::Get());
#endif
StartupTask pre_create_threads =
base::Bind(&BrowserMainLoop::PreCreateThreads, base::Unretained(this));
@@ -916,7 +972,7 @@ int BrowserMainLoop::CreateThreads() {
task_scheduler_init_params->foreground_worker_pool_params =
base::SchedulerWorkerPoolParams(
std::max(GetMinThreadsInRendererTaskSchedulerForegroundPool(),
- current_foreground_worker_pool_params.max_threads()),
+ current_foreground_worker_pool_params.max_tasks()),
current_foreground_worker_pool_params.suggested_reclaim_time(),
current_foreground_worker_pool_params.backward_compatibility());
}
@@ -1005,12 +1061,6 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
if (RenderProcessHost::run_renderer_in_process())
RenderProcessHostImpl::ShutDownInProcessRenderer();
-#if BUILDFLAG(ENABLE_MUS)
- // NOTE: because of dependencies this has to happen before
- // PostMainMessageLoopRun().
- image_cursors_set_.reset();
-#endif
-
if (parts_) {
TRACE_EVENT0("shutdown",
"BrowserMainLoop::Subsystem:PostMainMessageLoopRun");
@@ -1054,6 +1104,7 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
host_frame_sink_manager_.reset();
frame_sink_manager_impl_.reset();
compositing_mode_reporter_impl_.reset();
+ server_shared_bitmap_manager_.reset();
#endif
// The device monitors are using |system_monitor_| as dependency, so delete
@@ -1138,17 +1189,15 @@ media::AudioManager* BrowserMainLoop::audio_manager() const {
return audio_manager_.get();
}
-base::SequencedTaskRunner* BrowserMainLoop::audio_service_runner() {
- DCHECK(audio_service_runner_) << "The audio service task runner is not "
- "instantiated - running the audio service "
- "out of process?";
- return audio_service_runner_.get();
-}
-
#if !defined(OS_ANDROID)
viz::FrameSinkManagerImpl* BrowserMainLoop::GetFrameSinkManager() const {
return frame_sink_manager_impl_.get();
}
+
+viz::ServerSharedBitmapManager* BrowserMainLoop::GetServerSharedBitmapManager()
+ const {
+ return server_shared_bitmap_manager_.get();
+}
#endif
void BrowserMainLoop::GetCompositingModeReporter(
@@ -1158,7 +1207,7 @@ void BrowserMainLoop::GetCompositingModeReporter(
// CompositingModeReporter.
return;
#else
- if (features::IsMashEnabled()) {
+ if (!features::IsAshInBrowserProcess()) {
// Mash == ChromeOS, which doesn't support software compositing, so no need
// to report compositing mode.
return;
@@ -1187,26 +1236,31 @@ void BrowserMainLoop::InitializeMainThread() {
int BrowserMainLoop::BrowserThreadsStarted() {
TRACE_EVENT0("startup", "BrowserMainLoop::BrowserThreadsStarted");
- audio_service_runner_ =
- base::MakeRefCounted<base::DeferredSequencedTaskRunner>();
-
// Bring up Mojo IPC and the embedded Service Manager as early as possible.
// Initializaing mojo requires the IO thread to have been initialized first,
// so this cannot happen any earlier than now.
InitializeMojo();
#if BUILDFLAG(ENABLE_MUS)
- if (features::IsMashEnabled()) {
+ if (!features::IsAshInBrowserProcess()) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableSurfaceSynchronization);
}
#endif
HistogramSynchronizer::GetInstance();
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
- // Up the priority of the UI thread.
- base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY);
-#endif
+
+ // cc assumes a single client name for metrics in a process, which is
+ // is inconsistent with single process mode where both the renderer and
+ // browser compositor run in the same process. In this case, avoid
+ // initializing with a browser metric name to ensure we record metrics for the
+ // renderer compositor.
+ // Note that since single process mode is only used by webview in practice,
+ // which doesn't have a browser compositor, this is not required anyway.
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess)) {
+ cc::SetClientNameForMetrics("Browser");
+ }
// Initialize the GPU shader cache. This needs to be initialized before
// BrowserGpuChannelHostFactory below, since that depends on an initialized
@@ -1214,8 +1268,16 @@ int BrowserMainLoop::BrowserThreadsStarted() {
InitShaderCacheFactorySingleton(
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ // Initialize the FontRenderParams on IO thread. This needs to be initialized
+ // before gpu process initialization below.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &GpuProcessHost::InitFontRenderParamsOnIO,
+ gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr)));
+
// If mus is not hosting viz, then the browser must.
- bool browser_is_viz_host = !base::FeatureList::IsEnabled(::features::kMash);
+ bool browser_is_viz_host = features::IsAshInBrowserProcess();
bool always_uses_gpu = true;
bool established_gpu_channel = false;
@@ -1246,17 +1308,20 @@ int BrowserMainLoop::BrowserThreadsStarted() {
transport_factory->ConnectHostFrameSinkManager();
ImageTransportFactory::SetFactory(std::move(transport_factory));
} else {
+ server_shared_bitmap_manager_ =
+ std::make_unique<viz::ServerSharedBitmapManager>();
frame_sink_manager_impl_ = std::make_unique<viz::FrameSinkManagerImpl>(
+ server_shared_bitmap_manager_.get(),
switches::GetDeadlineToSynchronizeSurfaces());
surface_utils::ConnectWithLocalFrameSinkManager(
host_frame_sink_manager_.get(), frame_sink_manager_impl_.get());
-
ImageTransportFactory::SetFactory(
std::make_unique<GpuProcessTransportFactory>(
BrowserGpuChannelHostFactory::instance(),
- compositing_mode_reporter_impl_.get(), GetResizeTaskRunner()));
+ compositing_mode_reporter_impl_.get(),
+ server_shared_bitmap_manager_.get(), GetResizeTaskRunner()));
}
}
@@ -1395,7 +1460,10 @@ int BrowserMainLoop::BrowserThreadsStarted() {
}
#if defined(OS_WIN)
- GpuDataManagerImpl::GetInstance()->RequestGpuSupportedRuntimeVersion();
+ if (!parsed_command_line_.HasSwitch(
+ switches::kDisableGpuProcessForDX12VulkanInfoCollection)) {
+ GpuDataManagerImpl::GetInstance()->RequestGpuSupportedRuntimeVersion();
+ }
#endif
#if defined(OS_MACOSX)
@@ -1407,6 +1475,9 @@ int BrowserMainLoop::BrowserThreadsStarted() {
media::SetMediaDrmBridgeClient(GetContentClient()->GetMediaDrmBridgeClient());
#endif
+#if defined(ENABLE_IPC_FUZZER)
+ SetFileUrlPathAliasForIpcFuzzer();
+#endif
return result_code_;
}
@@ -1477,16 +1548,11 @@ bool BrowserMainLoop::InitializeToolkit() {
// Env creates the compositor. Aura widgets need the compositor to be created
// before they can be initialized by the browser.
- env_ = aura::Env::CreateInstance(features::IsMashEnabled()
- ? aura::Env::Mode::MUS
- : aura::Env::Mode::LOCAL);
+ env_ = aura::Env::CreateInstance(features::IsAshInBrowserProcess()
+ ? aura::Env::Mode::LOCAL
+ : aura::Env::Mode::MUS);
#endif // defined(USE_AURA)
-#if BUILDFLAG(ENABLE_MUS)
- if (features::IsMashEnabled())
- image_cursors_set_ = std::make_unique<ui::ImageCursorsSet>();
-#endif
-
if (parts_)
parts_->ToolkitInitialized();
@@ -1505,6 +1571,7 @@ void BrowserMainLoop::MainMessageLoopRun() {
}
base::RunLoop run_loop;
+ parts_->PreDefaultMainMessageLoopRun(run_loop.QuitClosure());
run_loop.Run();
#endif
}
@@ -1517,13 +1584,15 @@ void BrowserMainLoop::InitializeMojo() {
mojo::SyncCallRestrictions::DisallowSyncCall();
}
- mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport(
+ mojo_ipc_support_.reset(new mojo::core::ScopedIPCSupport(
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST));
+ mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST));
- service_manager_context_.reset(new ServiceManagerContext);
+ service_manager_context_.reset(
+ new ServiceManagerContext(io_thread_->task_runner()));
+ ServiceManagerContext::StartBrowserConnection();
#if defined(OS_MACOSX)
- mojo::edk::SetMachPortProvider(MachBroker::GetInstance());
+ mojo::core::SetMachPortProvider(MachBroker::GetInstance());
#endif // defined(OS_MACOSX)
GetContentClient()->OnServiceManagerConnected(
ServiceManagerConnection::GetForProcess());
@@ -1573,15 +1642,15 @@ void BrowserMainLoop::InitializeMojo() {
base::FilePath BrowserMainLoop::GetStartupTraceFileName() const {
base::FilePath trace_file;
-#if defined(OS_ANDROID)
- TracingControllerAndroid::GenerateTracingFilePath(&trace_file);
-#else
trace_file = tracing::TraceStartupConfig::GetInstance()->GetResultFile();
if (trace_file.empty()) {
+#if defined(OS_ANDROID)
+ TracingControllerAndroid::GenerateTracingFilePath(&trace_file);
+#else
// Default to saving the startup trace into the current dir.
trace_file = base::FilePath().AppendASCII("chrometrace.log");
- }
#endif
+ }
return trace_file;
}
@@ -1638,13 +1707,25 @@ void BrowserMainLoop::InitializeAudio() {
TRACE_EVENT_INSTANT0("startup", "Starting Audio service task runner",
TRACE_EVENT_SCOPE_THREAD);
- audio_service_runner_->StartWithTaskRunner(audio_manager_->GetTaskRunner());
+ ServiceManagerContext::GetAudioServiceRunner()->StartWithTaskRunner(
+ audio_manager_->GetTaskRunner());
}
if (base::FeatureList::IsEnabled(features::kAudioServiceLaunchOnStartup)) {
- content::ServiceManagerConnection::GetForProcess()
- ->GetConnector()
- ->StartService(audio::mojom::kServiceName);
+ // Schedule the audio service startup on the main thread.
+ BrowserThread::PostAfterStartupTask(
+ FROM_HERE, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
+ base::BindOnce([]() {
+ TRACE_EVENT0("audio", "Starting audio service");
+ ServiceManagerConnection* connection =
+ content::ServiceManagerConnection::GetForProcess();
+ if (connection) {
+ // The browser is not shutting down: |connection| would be null
+ // otherwise.
+ connection->GetConnector()->StartService(
+ audio::mojom::kServiceName);
+ }
+ }));
}
audio_system_ = audio::CreateAudioSystem(
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index c8618c586f5..040f1b63136 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -32,7 +32,6 @@ class Env;
namespace base {
class CommandLine;
-class DeferredSequencedTaskRunner;
class FilePath;
class HighResolutionTimerManager;
class MemoryPressureMonitor;
@@ -72,25 +71,20 @@ class MidiService;
} // namespace midi
namespace mojo {
-namespace edk {
+namespace core {
class ScopedIPCSupport;
-} // namespace edk
+} // namespace core
} // namespace mojo
namespace net {
class NetworkChangeNotifier;
} // namespace net
-#if BUILDFLAG(ENABLE_MUS)
-namespace ui {
-class ImageCursorsSet;
-}
-#endif
-
namespace viz {
class CompositingModeReporterImpl;
class FrameSinkManagerImpl;
class HostFrameSinkManager;
+class ServerSharedBitmapManager;
}
namespace content {
@@ -126,13 +120,14 @@ class CONTENT_EXPORT BrowserMainLoop {
// that return objects which are owned by this class.
static BrowserMainLoop* GetInstance();
+ static media::AudioManager* GetAudioManager();
+
+ // The TaskScheduler instance must exist but not to be started when building
+ // BrowserMainLoop.
explicit BrowserMainLoop(const MainFunctionParams& parameters);
virtual ~BrowserMainLoop();
- // |service_manager_thread| is optional. If set, it will be registered as
- // BrowserThread::IO in CreateThreads() instead of creating a brand new
- // thread.
- void Init(std::unique_ptr<BrowserProcessSubThread> service_manager_thread);
+ void Init();
// Return value is exit status. Anything other than RESULT_CODE_NORMAL_EXIT
// is considered an error.
@@ -163,7 +158,6 @@ class CONTENT_EXPORT BrowserMainLoop {
int GetResultCode() const { return result_code_; }
media::AudioManager* audio_manager() const;
- base::SequencedTaskRunner* audio_service_runner();
bool AudioServiceOutOfProcess() const;
media::AudioSystem* audio_system() const { return audio_system_.get(); }
MediaStreamManager* media_stream_manager() const {
@@ -191,10 +185,6 @@ class CONTENT_EXPORT BrowserMainLoop {
return startup_trace_file_;
}
-#if BUILDFLAG(ENABLE_MUS)
- ui::ImageCursorsSet* image_cursors_set() { return image_cursors_set_.get(); }
-#endif
-
// Returns the task runner for tasks that that are critical to producing a new
// CompositorFrame on resize. On Mac this will be the task runner provided by
// WindowResizeHelperMac, on other platforms it will just be the thread task
@@ -217,6 +207,9 @@ class CONTENT_EXPORT BrowserMainLoop {
// TODO(crbug.com/657959): This will be removed once there are no users, as
// SurfaceManager is being moved out of process.
viz::FrameSinkManagerImpl* GetFrameSinkManager() const;
+
+ // This returns null when the display compositor is out of process.
+ viz::ServerSharedBitmapManager* GetServerSharedBitmapManager() const;
#endif
// Fulfills a mojo pointer to the singleton CompositingModeReporter.
@@ -307,9 +300,6 @@ class CONTENT_EXPORT BrowserMainLoop {
#if defined(USE_AURA)
std::unique_ptr<aura::Env> env_;
#endif
-#if BUILDFLAG(ENABLE_MUS)
- std::unique_ptr<ui::ImageCursorsSet> image_cursors_set_;
-#endif
#if defined(OS_ANDROID)
// Android implementation of ScreenOrientationDelegate
@@ -345,7 +335,7 @@ class CONTENT_EXPORT BrowserMainLoop {
// Members initialized in |BrowserThreadsStarted()| --------------------------
std::unique_ptr<ServiceManagerContext> service_manager_context_;
- std::unique_ptr<mojo::edk::ScopedIPCSupport> mojo_ipc_support_;
+ std::unique_ptr<mojo::core::ScopedIPCSupport> mojo_ipc_support_;
// |user_input_monitor_| has to outlive |audio_manager_|, so declared first.
std::unique_ptr<media::UserInputMonitor> user_input_monitor_;
@@ -354,9 +344,6 @@ class CONTENT_EXPORT BrowserMainLoop {
// process.
std::unique_ptr<media::AudioManager> audio_manager_;
- // Task runner for the audio service when it runs in the browser process.
- scoped_refptr<base::DeferredSequencedTaskRunner> audio_service_runner_;
-
std::unique_ptr<media::AudioSystem> audio_system_;
#if defined(OS_CHROMEOS)
@@ -384,6 +371,11 @@ class CONTENT_EXPORT BrowserMainLoop {
scoped_refptr<SaveFileManager> save_file_manager_;
std::unique_ptr<content::TracingControllerImpl> tracing_controller_;
#if !defined(OS_ANDROID)
+ // A SharedBitmapManager used to sharing and mapping IDs to shared memory
+ // between processes for software compositing. When the display compositor is
+ // in the browser process, then |server_shared_bitmap_manager_| is set, and
+ // when it is in the viz process, then it is null.
+ std::unique_ptr<viz::ServerSharedBitmapManager> server_shared_bitmap_manager_;
std::unique_ptr<viz::HostFrameSinkManager> host_frame_sink_manager_;
// This is owned here so that SurfaceManager will be accessible in process
// when display is in the same process. Other than using SurfaceManager,
diff --git a/chromium/content/browser/browser_main_loop_unittest.cc b/chromium/content/browser/browser_main_loop_unittest.cc
index 24e38ba8a61..46955a01c56 100644
--- a/chromium/content/browser/browser_main_loop_unittest.cc
+++ b/chromium/content/browser/browser_main_loop_unittest.cc
@@ -21,7 +21,7 @@ namespace content {
// the number of cores in its foreground pool.
TEST(BrowserMainLoopTest, CreateThreadsInSingleProcess) {
{
- base::MessageLoop message_loop;
+ base::TaskScheduler::Create("Browser");
base::test::ScopedCommandLine scoped_command_line;
scoped_command_line.GetProcessCommandLine()->AppendSwitch(
switches::kSingleProcess);
@@ -29,7 +29,7 @@ TEST(BrowserMainLoopTest, CreateThreadsInSingleProcess) {
*scoped_command_line.GetProcessCommandLine());
BrowserMainLoop browser_main_loop(main_function_params);
browser_main_loop.MainMessageLoopStart();
- browser_main_loop.Init(nullptr);
+ browser_main_loop.Init();
browser_main_loop.CreateThreads();
EXPECT_GE(base::TaskScheduler::GetInstance()
->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
diff --git a/chromium/content/browser/browser_main_runner_impl.cc b/chromium/content/browser/browser_main_runner_impl.cc
index 6381234ca78..e0c7136869b 100644
--- a/chromium/content/browser/browser_main_runner_impl.cc
+++ b/chromium/content/browser/browser_main_runner_impl.cc
@@ -23,7 +23,6 @@
#include "components/tracing/common/trace_startup_config.h"
#include "components/tracing/common/tracing_switches.h"
#include "content/browser/browser_main_loop.h"
-#include "content/browser/browser_process_sub_thread.h"
#include "content/browser/browser_shutdown_profile_dumper.h"
#include "content/browser/notification_service_impl.h"
#include "content/common/content_switches_internal.h"
@@ -63,12 +62,6 @@ BrowserMainRunnerImpl::~BrowserMainRunnerImpl() {
}
int BrowserMainRunnerImpl::Initialize(const MainFunctionParams& parameters) {
- return Initialize(parameters, nullptr);
-}
-
-int BrowserMainRunnerImpl::Initialize(
- const MainFunctionParams& parameters,
- std::unique_ptr<BrowserProcessSubThread> service_manager_thread) {
SCOPED_UMA_HISTOGRAM_LONG_TIMER(
"Startup.BrowserMainRunnerImplInitializeLongTime");
TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize");
@@ -117,7 +110,7 @@ int BrowserMainRunnerImpl::Initialize(
main_loop_.reset(new BrowserMainLoop(parameters));
- main_loop_->Init(std::move(service_manager_thread));
+ main_loop_->Init();
if (parameters.created_main_parts_closure) {
parameters.created_main_parts_closure->Run(main_loop_->parts());
diff --git a/chromium/content/browser/browser_main_runner_impl.h b/chromium/content/browser/browser_main_runner_impl.h
index adb084fe27c..08e959ff7aa 100644
--- a/chromium/content/browser/browser_main_runner_impl.h
+++ b/chromium/content/browser/browser_main_runner_impl.h
@@ -19,7 +19,6 @@ class ScopedOleInitializer;
namespace content {
-class BrowserProcessSubThread;
class BrowserMainLoop;
class NotificationServiceImpl;
@@ -38,12 +37,6 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
int Run() override;
void Shutdown() override;
- // Initialize all necessary browser state with a |service_manager_thread|
- // on which ServiceManager is currently running.
- int Initialize(
- const MainFunctionParams& parameters,
- std::unique_ptr<BrowserProcessSubThread> service_manager_thread);
-
private:
// True if we have started to initialize the runner.
bool initialization_started_;
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
index c3e3bbd9b50..788d8399321 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
@@ -196,18 +196,18 @@ BrowserPluginGuest* BrowserPluginEmbedder::GetFullPageGuest() {
}
// static
-bool BrowserPluginEmbedder::GuestRecentlyAudibleCallback(WebContents* guest) {
- return guest->WasRecentlyAudible();
+bool BrowserPluginEmbedder::GuestCurrentlyAudibleCallback(WebContents* guest) {
+ return guest->IsCurrentlyAudible();
}
-bool BrowserPluginEmbedder::WereAnyGuestsRecentlyAudible() {
+bool BrowserPluginEmbedder::AreAnyGuestsCurrentlyAudible() {
if (!GetBrowserPluginGuestManager())
return false;
return GetBrowserPluginGuestManager()->ForEachGuest(
web_contents(),
base::BindRepeating(
- &BrowserPluginEmbedder::GuestRecentlyAudibleCallback));
+ &BrowserPluginEmbedder::GuestCurrentlyAudibleCallback));
}
// static
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.h b/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
index e1007f040a7..326a9ac8fdd 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
@@ -80,8 +80,8 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
BrowserPluginGuest* GetFullPageGuest();
// Polls all guests for this web contents and returns true if any of them
- // were audible recently.
- bool WereAnyGuestsRecentlyAudible();
+ // are currently audible.
+ bool AreAnyGuestsCurrentlyAudible();
private:
explicit BrowserPluginEmbedder(WebContentsImpl* web_contents);
@@ -98,7 +98,7 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
static bool UnlockMouseIfNecessaryCallback(bool* mouse_unlocked,
WebContents* guest);
- static bool GuestRecentlyAudibleCallback(WebContents* guest);
+ static bool GuestCurrentlyAudibleCallback(WebContents* guest);
// Message handlers.
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index a0bc9305e62..f56ce93c3d5 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -87,7 +87,6 @@ BrowserPluginGuest::BrowserPluginGuest(bool has_render_view,
: WebContentsObserver(web_contents),
owner_web_contents_(nullptr),
attached_(false),
- has_attached_since_surface_set_(false),
browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
focused_(false),
mouse_locked_(false),
@@ -407,12 +406,11 @@ void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
browser_plugin_instance_id(), allow));
}
-void BrowserPluginGuest::SetChildFrameSurface(
+void BrowserPluginGuest::FirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
- has_attached_since_surface_set_ = false;
- if (!base::FeatureList::IsEnabled(::features::kMash)) {
+ if (features::IsAshInBrowserProcess()) {
SendMessageToEmbedder(
- std::make_unique<BrowserPluginMsg_SetChildFrameSurface>(
+ std::make_unique<BrowserPluginMsg_FirstSurfaceActivation>(
browser_plugin_instance_id(), surface_info));
}
}
@@ -663,7 +661,7 @@ void BrowserPluginGuest::RenderViewReady() {
// In case we've created a new guest render process after a crash, let the
// associated BrowserPlugin know. We only need to send this if we're attached,
// as guest_crashed_ is cleared automatically on attach anyways.
- if (attached() && !base::FeatureList::IsEnabled(::features::kMash)) {
+ if (attached() && features::IsAshInBrowserProcess()) {
RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
web_contents()->GetRenderWidgetHostView());
if (rwhv) {
@@ -796,7 +794,6 @@ void BrowserPluginGuest::OnWillAttachComplete(
InitInternal(params, embedder_web_contents);
attached_ = true;
- has_attached_since_surface_set_ = true;
SendQueuedMessages();
delegate_->DidAttach(GetGuestProxyRoutingID());
@@ -1038,8 +1035,8 @@ void BrowserPluginGuest::OnSynchronizeVisualProperties(
if (local_surface_id_ > local_surface_id ||
((frame_rect_.size() != visual_properties.screen_space_rect.size() ||
screen_info_ != visual_properties.screen_info ||
- capture_sequence_number_ !=
- visual_properties.capture_sequence_number) &&
+ capture_sequence_number_ != visual_properties.capture_sequence_number ||
+ zoom_level_ != visual_properties.zoom_level) &&
local_surface_id_ == local_surface_id)) {
SiteInstance* owner_site_instance = delegate_->GetOwnerSiteInstance();
bad_message::ReceivedBadMessage(
@@ -1050,6 +1047,8 @@ void BrowserPluginGuest::OnSynchronizeVisualProperties(
screen_info_ = visual_properties.screen_info;
frame_rect_ = visual_properties.screen_space_rect;
+ zoom_level_ = visual_properties.zoom_level;
+
GetWebContents()->SendScreenRects();
local_surface_id_ = local_surface_id;
bool capture_sequence_number_changed =
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
index 964137dafc0..aab107192d0 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
@@ -215,12 +215,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
// Returns whether the guest is attached to an embedder.
bool attached() const { return attached_; }
- // Returns true when an attachment has taken place since the last time the
- // compositor surface was set.
- bool has_attached_since_surface_set() const {
- return has_attached_since_surface_set_;
- }
-
// Attaches this BrowserPluginGuest to the provided |embedder_web_contents|
// and initializes the guest with the provided |params|. Attaching a guest
// to an embedder implies that this guest's lifetime is no longer managed
@@ -250,7 +244,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
void PointerLockPermissionResponse(bool allow);
// The next function is virtual for test purposes.
- virtual void SetChildFrameSurface(const viz::SurfaceInfo& surface_info);
+ virtual void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info);
void ResendEventToEmbedder(const blink::WebInputEvent& event);
@@ -271,11 +265,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
WebContentsImpl* web_contents,
BrowserPluginGuestDelegate* delegate);
- // Protected for testing.
- void set_has_attached_since_surface_set_for_test(bool has_attached) {
- has_attached_since_surface_set_ = has_attached;
- }
-
void set_attached_for_test(bool attached) {
attached_ = attached;
}
@@ -397,10 +386,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
// Indicates whether this guest has been attached to a container.
bool attached_;
- // Used to signal if a browser plugin has been attached since the last time
- // the compositing surface was set.
- bool has_attached_since_surface_set_;
-
// An identifier that uniquely identifies a browser plugin within an embedder.
int browser_plugin_instance_id_;
gfx::Rect frame_rect_;
@@ -455,6 +440,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
viz::LocalSurfaceId local_surface_id_;
ScreenInfo screen_info_;
+ double zoom_level_ = 0.0;
uint32_t capture_sequence_number_ = 0u;
// Weak pointer used to ask GeolocationPermissionContext about geolocation
diff --git a/chromium/content/browser/browser_process_sub_thread.cc b/chromium/content/browser/browser_process_sub_thread.cc
index 6f33cee4d65..876318dc799 100644
--- a/chromium/content/browser/browser_process_sub_thread.cc
+++ b/chromium/content/browser/browser_process_sub_thread.cc
@@ -197,14 +197,7 @@ void BrowserProcessSubThread::IOThreadCleanUp() {
static_cast<UtilityProcessHost*>(it.GetDelegate());
if (utility_process->sandbox_type() ==
service_manager::SANDBOX_TYPE_NETWORK) {
- // Even though the TerminateAll call above tries to kill all child
- // processes, that will fail sometimes (e.g. on Windows if there's pending
- // I/O). Once the network service is sandboxed this will be taken care of,
- // since the sandbox ensures child processes are terminated. Until then,
- // wait on the network process for a bit. This is done so that:
- // 1) when Chrome quits, we ensure that cookies & cache are flushed
- // 2) tests aren't killed by swarming because of child processes that
- // outlive the parent process.
+ // This ensures that cookies and cache are flushed to disk on shutdown.
// https://crbug.com/841001
const int kMaxSecondsToWaitForNetworkProcess = 10;
ChildProcessHostImpl* child_process =
diff --git a/chromium/content/browser/browser_side_navigation_browsertest.cc b/chromium/content/browser/browser_side_navigation_browsertest.cc
index bbc595fb84f..b4cf78fea84 100644
--- a/chromium/content/browser/browser_side_navigation_browsertest.cc
+++ b/chromium/content/browser/browser_side_navigation_browsertest.cc
@@ -5,6 +5,7 @@
#include <stdint.h>
#include "base/command_line.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
@@ -15,7 +16,9 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_manager_delegate.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
@@ -29,8 +32,10 @@
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_download_manager_delegate.h"
#include "content/shell/browser/shell_network_delegate.h"
#include "content/test/content_browser_test_utils_internal.h"
+#include "content/test/did_commit_provisional_load_interceptor.h"
#include "ipc/ipc_security_test_util.h"
#include "net/base/filename_util.h"
#include "net/base/load_flags.h"
@@ -43,6 +48,96 @@
namespace content {
+namespace {
+
+class InterceptAndCancelDidCommitProvisionalLoad
+ : public DidCommitProvisionalLoadInterceptor {
+ public:
+ explicit InterceptAndCancelDidCommitProvisionalLoad(WebContents* web_contents)
+ : DidCommitProvisionalLoadInterceptor(web_contents) {}
+ ~InterceptAndCancelDidCommitProvisionalLoad() override {}
+
+ void Wait(size_t number_of_messages) {
+ while (intercepted_messages_.size() < number_of_messages) {
+ loop_.reset(new base::RunLoop);
+ loop_->Run();
+ }
+ }
+
+ const std::vector<::FrameHostMsg_DidCommitProvisionalLoad_Params>&
+ intercepted_messages() const {
+ return intercepted_messages_;
+ }
+
+ std::vector<::service_manager::mojom::InterfaceProviderRequest>&
+ intercepted_requests() {
+ return intercepted_requests_;
+ }
+
+ protected:
+ bool WillDispatchDidCommitProvisionalLoad(
+ RenderFrameHost* render_frame_host,
+ ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
+ service_manager::mojom::InterfaceProviderRequest*
+ interface_provider_request) override {
+ intercepted_messages_.push_back(*params);
+ intercepted_requests_.push_back(std::move(*interface_provider_request));
+ if (loop_)
+ loop_->Quit();
+ // Do not send the message to the RenderFrameHostImpl.
+ return false;
+ }
+
+ std::vector<::FrameHostMsg_DidCommitProvisionalLoad_Params>
+ intercepted_messages_;
+ std::vector<::service_manager::mojom::InterfaceProviderRequest>
+ intercepted_requests_;
+ std::unique_ptr<base::RunLoop> loop_;
+};
+
+// Record every WebContentsObserver's event related to navigation. The goal is
+// to check these events happen and happen in the expected right order.
+class NavigationRecorder : public WebContentsObserver {
+ public:
+ NavigationRecorder(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+
+ // WebContentsObserver implementation.
+ void DidStartNavigation(NavigationHandle* navigation_handle) override {
+ records_.push_back("start " + navigation_handle->GetURL().path());
+ WakeUp();
+ }
+ void ReadyToCommitNavigation(NavigationHandle* navigation_handle) override {
+ records_.push_back("ready-to-commit " + navigation_handle->GetURL().path());
+ WakeUp();
+ }
+ void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+ records_.push_back("did-commit " + navigation_handle->GetURL().path());
+ WakeUp();
+ }
+
+ void WaitForEvents(size_t numbers_of_events) {
+ while (records_.size() < numbers_of_events) {
+ loop_.reset(new base::RunLoop);
+ loop_->Run();
+ loop_.reset();
+ }
+ }
+
+ const std::vector<std::string> records() { return records_; }
+
+ private:
+ void WakeUp() {
+ if (loop_)
+ loop_->Quit();
+ }
+
+ std::unique_ptr<base::RunLoop> loop_;
+ std::vector<std::string> records_;
+};
+
+} // namespace
+
// Test with BrowserSideNavigation enabled (aka PlzNavigate).
// If you don't need a custom embedded test server, please use the next class
// below (BrowserSideNavigationBrowserTest), it will automatically start the
@@ -458,8 +553,6 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserDisableWebSecurityTest,
data_url, Referrer(), ui::PAGE_TRANSITION_LINK,
FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, true /* allow_download */,
false /* should_replace_current_entry */,
- base::TimeTicks() /* ui_timestamp */,
- FrameMsg_UILoadMetricsReportType::NO_REPORT,
file_url, /* base_url_for_data_url */
GURL() /* history_url_for_data_url */, PREVIEWS_UNSPECIFIED,
base::TimeTicks::Now() /* navigation_start */, "GET",
@@ -481,8 +574,18 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserDisableWebSecurityTest,
// Receiving the invalid IPC message should lead to renderer process
// termination.
RenderProcessHostKillWaiter process_kill_waiter(rfh->GetProcess());
- rfh->frame_host_binding_for_testing().impl()->BeginNavigation(
- common_params, std::move(begin_params), nullptr);
+
+ mojom::NavigationClientAssociatedPtr navigation_client;
+ if (IsPerNavigationMojoInterfaceEnabled()) {
+ auto navigation_client_request =
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&navigation_client);
+ rfh->frame_host_binding_for_testing().impl()->BeginNavigation(
+ common_params, std::move(begin_params), nullptr,
+ navigation_client.PassInterface());
+ } else {
+ rfh->frame_host_binding_for_testing().impl()->BeginNavigation(
+ common_params, std::move(begin_params), nullptr, nullptr);
+ }
EXPECT_EQ(bad_message::RFH_BASE_URL_FOR_DATA_URL_SPECIFIED,
process_kill_waiter.Wait());
@@ -704,4 +807,297 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
}
}
+// Regression test for https://crbug.com/260144
+// Back/Forward navigation in an iframe must not stop ongoing XHR.
+IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
+ IframeNavigationsDoNotStopXHR) {
+ // A response for the XHR request. It will be delayed until the end of all the
+ // navigations.
+ net::test_server::ControllableHttpResponse xhr_response(
+ embedded_test_server(), "/xhr");
+ EXPECT_TRUE(embedded_test_server()->Start());
+
+ GURL url(embedded_test_server()->GetURL("/title1.html"));
+ NavigateToURL(shell(), url);
+
+ DOMMessageQueue dom_message_queue(WebContents::FromRenderFrameHost(
+ shell()->web_contents()->GetMainFrame()));
+ std::string message;
+
+ // 1) Send an XHR.
+ ExecuteScriptAsync(
+ shell(),
+ "let xhr = new XMLHttpRequest();"
+ "xhr.open('GET', './xhr', true);"
+ "xhr.onabort = () => window.domAutomationController.send('xhr.onabort');"
+ "xhr.onerror = () => window.domAutomationController.send('xhr.onerror');"
+ "xhr.onload = () => window.domAutomationController.send('xhr.onload');"
+ "xhr.send();");
+
+ // 2) Create an iframe and wait for the initial load.
+ {
+ ExecuteScriptAsync(
+ shell(),
+ "var iframe = document.createElement('iframe');"
+ "iframe.src = './title1.html';"
+ "iframe.onload = function() {"
+ " window.domAutomationController.send('iframe.onload');"
+ "};"
+ "document.body.appendChild(iframe);");
+
+ EXPECT_TRUE(dom_message_queue.WaitForMessage(&message));
+ EXPECT_EQ("\"iframe.onload\"", message);
+ }
+
+ // 3) Navigate the iframe elsewhere.
+ {
+ ExecuteScriptAsync(shell(),
+ "var iframe = document.querySelector('iframe');"
+ "iframe.src = './title2.html';");
+
+ EXPECT_TRUE(dom_message_queue.WaitForMessage(&message));
+ EXPECT_EQ("\"iframe.onload\"", message);
+ }
+
+ // 4) history.back() in the iframe.
+ {
+ ExecuteScriptAsync(shell(),
+ "var iframe = document.querySelector('iframe');"
+ "iframe.contentWindow.history.back()");
+
+ EXPECT_TRUE(dom_message_queue.WaitForMessage(&message));
+ EXPECT_EQ("\"iframe.onload\"", message);
+ }
+
+ // 5) history.forward() in the iframe.
+ {
+ ExecuteScriptAsync(shell(),
+ "var iframe = document.querySelector('iframe');"
+ "iframe.contentWindow.history.forward()");
+
+ EXPECT_TRUE(dom_message_queue.WaitForMessage(&message));
+ EXPECT_EQ("\"iframe.onload\"", message);
+ }
+
+ // 6) Wait for the XHR.
+ {
+ xhr_response.WaitForRequest();
+ xhr_response.Send(
+ "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-Length: 2\r\n"
+ "Content-Type: text/plain; charset=utf-8\r\n"
+ "\r\n"
+ "OK");
+ xhr_response.Done();
+ EXPECT_TRUE(dom_message_queue.WaitForMessage(&message));
+ EXPECT_EQ("\"xhr.onload\"", message);
+ }
+
+ EXPECT_FALSE(dom_message_queue.PopMessage(&message));
+}
+
+// Regression test for https://crbug.com/856396.
+IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
+ ReplacingDocumentLoaderFiresLoadEvent) {
+ net::test_server::ControllableHttpResponse main_document_response(
+ embedded_test_server(), "/main_document");
+ net::test_server::ControllableHttpResponse iframe_response(
+ embedded_test_server(), "/iframe");
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // 1) Load the main document.
+ shell()->LoadURL(embedded_test_server()->GetURL("/main_document"));
+ main_document_response.WaitForRequest();
+ main_document_response.Send(
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/html; charset=utf-8\r\n"
+ "\r\n"
+ "<script>"
+ " var detach_iframe = function() {"
+ " var iframe = document.querySelector('iframe');"
+ " iframe.parentNode.removeChild(iframe);"
+ " }"
+ "</script>"
+ "<body onload='detach_iframe()'>"
+ " <iframe src='/iframe'></iframe>"
+ "</body>");
+ main_document_response.Done();
+
+ // 2) The iframe starts to load, but the server only have time to send the
+ // response's headers, not the response's body. A provisional DocumentLoader
+ // will be created in the renderer process, but it will never commit.
+ iframe_response.WaitForRequest();
+ iframe_response.Send(
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/html; charset=utf-8\r\n"
+ "\r\n");
+
+ // 3) In the meantime the iframe navigates elsewhere. It causes the previous
+ // provisional DocumentLoader to be replaced by the new one. Removing it may
+ // trigger the 'load' event and delete the iframe.
+ EXPECT_TRUE(ExecuteScript(
+ shell(), "document.querySelector('iframe').src = '/title1.html'"));
+
+ // Wait for the iframe to be deleted and check the renderer process is still
+ // alive.
+ int iframe_count = 1;
+ while (iframe_count != 0) {
+ ASSERT_TRUE(ExecuteScriptAndExtractInt(
+ shell(),
+ "var iframe_count = document.getElementsByTagName('iframe').length;"
+ "window.domAutomationController.send(iframe_count);",
+ &iframe_count));
+ }
+}
+
+class NavigationDownloadBrowserTest
+ : public BrowserSideNavigationBaseBrowserTest {
+ protected:
+ void SetUpOnMainThread() override {
+ BrowserSideNavigationBaseBrowserTest::SetUpOnMainThread();
+
+ // Set up a test download directory, in order to prevent prompting for
+ // handling downloads.
+ ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
+ ShellDownloadManagerDelegate* delegate =
+ static_cast<ShellDownloadManagerDelegate*>(
+ shell()
+ ->web_contents()
+ ->GetBrowserContext()
+ ->GetDownloadManagerDelegate());
+ delegate->SetDownloadBehaviorForTesting(downloads_directory_.GetPath());
+ }
+
+ private:
+ base::ScopedTempDir downloads_directory_;
+};
+
+// Regression test for https://crbug.com/855033
+// 1) A page contains many scripts and DOM elements. It forces the parser to
+// yield CPU to other tasks. That way the response body's data are not fully
+// read when URLLoaderClient::OnComplete(..) is received.
+// 2) A script makes the document navigates elsewhere while it is still loading.
+// It cancels the parser of the current document. Due to a bug, the document
+// loader was not marked to be 'loaded' at this step.
+// 3) The request for the new navigation starts and it turns out it is a
+// download. The navigation is dropped.
+// 4) There are no more possibilities for DidStopLoading() to be sent.
+IN_PROC_BROWSER_TEST_F(NavigationDownloadBrowserTest,
+ StopLoadingAfterDroppedNavigation) {
+ net::test_server::ControllableHttpResponse main_response(
+ embedded_test_server(), "/main");
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL main_url(embedded_test_server()->GetURL("/main"));
+ GURL download_url(embedded_test_server()->GetURL("/download-test1.lib"));
+
+ shell()->LoadURL(main_url);
+ main_response.WaitForRequest();
+ std::string headers =
+ "HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/html; charset=utf-8\r\n"
+ "\r\n";
+
+ // Craft special HTML to make the blink::DocumentParser yield CPU to other
+ // tasks. The goal is to ensure the response body datapipe is not fully read
+ // when URLLoaderClient::OnComplete() is called.
+ // This relies on the HTMLParserScheduler::ShouldYield() heuristics.
+ std::string mix_of_script_and_div = "<script></script><div></div>";
+ for (size_t i = 0; i < 10; ++i) {
+ mix_of_script_and_div += mix_of_script_and_div; // Exponential growth.
+ }
+
+ std::string navigate_to_download =
+ "<script>location.href='" + download_url.spec() + "'</script>";
+
+ main_response.Send(headers + navigate_to_download + mix_of_script_and_div);
+ main_response.Done();
+
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+}
+
+// This test reproduces the following race condition:
+// 1) A first navigation starts, the headers are received, the navigation
+// reaches ready-to-commit. It is sent to the renderer to be committed.
+// 2) In the meantime, a second navigation reaches ready-to-commit in the
+// browser.
+// 3) Before the renderer gets notified of the new navigation, the
+// first navigation is committed.
+// 4) The browser gets notified of the commit of the first navigation. This
+// should not destroy the NavigationRequest corresponding to the second
+// navigation.
+IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
+ RaceNewNavigationCommitWhileOldOneFinishesLoading) {
+ // Start the test with an initial document.
+ GURL main_url(embedded_test_server()->GetURL("/simple_page.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameHostImpl* render_frame_host = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+
+ NavigationRecorder recorder(shell()->web_contents());
+ // Note: These two pages contain an image that will never load. The goal is to
+ // prevent RenderFrameHostImpl::DidStopLoading() to be called since it will
+ // cancel any pending navigation.
+ GURL page_1(embedded_test_server()->GetURL("/infinite_load_1.html"));
+ GURL page_2(embedded_test_server()->GetURL("/infinite_load_2.html"));
+ // Intercept and cancel any FrameMsgHost_DidCommitProvisionalLoad events.
+ InterceptAndCancelDidCommitProvisionalLoad interceptor(
+ shell()->web_contents());
+
+ // 1) Navigate to page_1.
+ shell()->LoadURL(page_1);
+
+ // 2) The browser receives the response's headers. The navigation commits in
+ // the browser.
+ recorder.WaitForEvents(2);
+ EXPECT_EQ(2u, recorder.records().size());
+ EXPECT_STREQ("start /infinite_load_1.html", recorder.records()[0].c_str());
+ EXPECT_STREQ("ready-to-commit /infinite_load_1.html",
+ recorder.records()[1].c_str());
+
+ // 3) Wait for the renderer to receive the response's body, but do not notify
+ // the browser of it right now. It is delayed in 6).
+ interceptor.Wait(1);
+ EXPECT_EQ(1u, interceptor.intercepted_messages().size());
+
+ // 4) In the meantime, the browser starts a navigation to page_2.
+ shell()->LoadURL(page_2);
+
+ // 5) The response's headers are received, the navigation reaches
+ // ready-to-commit in the browser. This should not delete the ongoing
+ // NavigationRequest.
+ recorder.WaitForEvents(4);
+ EXPECT_EQ(4u, recorder.records().size());
+ EXPECT_STREQ("start /infinite_load_2.html", recorder.records()[2].c_str());
+ EXPECT_STREQ("ready-to-commit /infinite_load_2.html",
+ recorder.records()[3].c_str());
+
+ // 6) The browser receives the first DidCommitProvisionalLoad message. This
+ // should not delete the second navigation. This is the end of the first
+ // navigation.
+ render_frame_host->DidCommitProvisionalLoadForTesting(
+ std::make_unique<::FrameHostMsg_DidCommitProvisionalLoad_Params>(
+ interceptor.intercepted_messages()[0]),
+ std::move(interceptor.intercepted_requests()[0]));
+ recorder.WaitForEvents(5);
+ EXPECT_EQ(5u, recorder.records().size());
+ EXPECT_STREQ("did-commit /infinite_load_1.html",
+ recorder.records()[4].c_str());
+
+ // 7) Wait for the renderer to receive the second response's body. This is the
+ // end of the second navigation.
+ interceptor.Wait(2);
+ EXPECT_EQ(2u, interceptor.intercepted_messages().size());
+ render_frame_host->DidCommitProvisionalLoadForTesting(
+ std::make_unique<::FrameHostMsg_DidCommitProvisionalLoad_Params>(
+ interceptor.intercepted_messages()[1]),
+ std::move(interceptor.intercepted_requests()[1]));
+ recorder.WaitForEvents(6);
+ EXPECT_EQ(6u, recorder.records().size());
+ EXPECT_STREQ("did-commit /infinite_load_2.html",
+ recorder.records()[5].c_str());
+}
+
} // namespace content
diff --git a/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc b/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
index 4c478ad0079..3226847af60 100644
--- a/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
@@ -16,6 +16,7 @@
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
+#include "base/stl_util.h"
#include "content/browser/browsing_data/storage_partition_http_cache_data_remover.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -67,8 +68,7 @@ bool DoesOriginMatchMaskAndURLs(
const std::vector<std::string>& schemes = url::GetWebStorageSchemes();
bool is_web_scheme =
- (std::find(schemes.begin(), schemes.end(), origin.GetOrigin().scheme()) !=
- schemes.end());
+ base::ContainsValue(schemes, origin.GetOrigin().scheme());
// If a websafe origin is unprotected, it matches iff UNPROTECTED_WEB.
if ((!policy || !policy->IsStorageProtected(origin.GetOrigin())) &&
diff --git a/chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc b/chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
index c7322c1f278..2f95096b273 100644
--- a/chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
@@ -342,7 +342,7 @@ class RemoveChannelIDTester : public net::SSLConfigService::Observer {
}
net::ChannelIDService* channel_id_service_;
- scoped_refptr<net::SSLConfigService> ssl_config_service_;
+ net::SSLConfigService* ssl_config_service_;
int ssl_config_changed_count_ = 0;
DISALLOW_COPY_AND_ASSIGN(RemoveChannelIDTester);
@@ -1492,7 +1492,8 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveNetworkErrorLogging) {
GURL domain("https://google.com");
logging_service->OnHeader(url::Origin::Create(domain),
- "{\"report-to\":\"group\",\"max-age\":86400}");
+ net::IPAddress(192, 168, 0, 1),
+ "{\"report_to\":\"group\",\"max_age\":86400}");
ASSERT_EQ(1u, logging_service->GetPolicyOriginsForTesting().size());
@@ -1513,16 +1514,20 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveNetworkErrorLogging_SpecificOrigins) {
GURL domain1("https://google.com");
logging_service->OnHeader(url::Origin::Create(domain1),
- "{\"report-to\":\"group\",\"max-age\":86400}");
+ net::IPAddress(192, 168, 0, 1),
+ "{\"report_to\":\"group\",\"max_age\":86400}");
GURL domain2("https://host2.com");
logging_service->OnHeader(url::Origin::Create(domain2),
- "{\"report-to\":\"group\",\"max-age\":86400}");
+ net::IPAddress(192, 168, 0, 1),
+ "{\"report_to\":\"group\",\"max_age\":86400}");
GURL domain3("https://host3.com");
logging_service->OnHeader(url::Origin::Create(domain3),
- "{\"report-to\":\"group\",\"max-age\":86400}");
+ net::IPAddress(192, 168, 0, 1),
+ "{\"report_to\":\"group\",\"max_age\":86400}");
GURL domain4("https://host4.com");
logging_service->OnHeader(url::Origin::Create(domain4),
- "{\"report-to\":\"group\",\"max-age\":86400}");
+ net::IPAddress(192, 168, 0, 1),
+ "{\"report_to\":\"group\",\"max_age\":86400}");
ASSERT_EQ(4u, logging_service->GetPolicyOriginsForTesting().size());
diff --git a/chromium/content/browser/cache_storage/README.md b/chromium/content/browser/cache_storage/README.md
index ea05b6c9d5e..77dfc1f4d07 100644
--- a/chromium/content/browser/cache_storage/README.md
+++ b/chromium/content/browser/cache_storage/README.md
@@ -3,12 +3,17 @@ This document describes the browser-process implementation of the [Cache
Storage specification](
https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html).
+As of June 2018, Chrome components can use the Cache Storage interface via
+`CacheStorageManager` to store Request/Response key-value pairs. The concept of
+`CacheStorageOwner` was added to distinguish and isolate the different
+components.
+
## Major Classes and Ownership
### Ownership
Where '=>' represents ownership, '->' is a reference, and '~>' is a weak
reference.
-##### `CacheStorageContextImpl`=>`CacheStorageManager`=>`CacheStorage`=>`CacheStorageCache`
+##### `CacheStorageContextImpl`->`CacheStorageManager`=>`CacheStorage`=>`CacheStorageCache`
* A `CacheStorageManager` can own multiple `CacheStorage` objects.
* A `CacheStorage` can own multiple `CacheStorageCache` objects.
@@ -44,12 +49,12 @@ reference.
mitigate rapid opening/closing/opening churn.
### CacheStorageManager
-1. Forwards calls to the appropriate `CacheStorage` for a given origin,
- loading `CacheStorage`s on demand.
+1. Forwards calls to the appropriate `CacheStorage` for a given origin-owner
+ pair, loading `CacheStorage`s on demand.
2. Handles `QuotaManager` and `BrowsingData` calls.
### CacheStorage
-1. Manages the caches for a single origin.
+1. Manages the caches for a single origin-owner pair.
2. Handles creation/deletion of caches and updates the index on disk
accordingly.
3. Manages operations that span multiple caches (e.g., `CacheStorage::Match`).
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 71a6e088876..103f821e3f8 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
@@ -144,7 +144,8 @@ class CacheStorageBlobToDiskCacheTest : public testing::Test {
std::unique_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*());
disk_cache::Entry** entry_ptr = entry.get();
- rv = cache_backend_->CreateEntry(kEntryKey, entry_ptr, base::DoNothing());
+ rv = cache_backend_->CreateEntry(kEntryKey, net::HIGHEST, entry_ptr,
+ base::DoNothing());
EXPECT_EQ(net::OK, rv);
disk_cache_entry_.reset(*entry);
}
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.cc b/chromium/content/browser/cache_storage/cache_storage_cache.cc
index d5459e40398..f853ed819ad 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.cc
@@ -74,24 +74,6 @@ const uint64_t kPaddingRange = 14431 * 1024;
// 2: Uniform random 14,431K.
const int32_t kCachePaddingAlgorithmVersion = 2;
-// This class ensures that the cache and the entry have a lifetime as long as
-// the blob that is created to contain them.
-class CacheStorageCacheDataHandle
- : public storage::BlobDataBuilder::DataHandle {
- public:
- CacheStorageCacheDataHandle(CacheStorageCacheHandle cache_handle,
- disk_cache::ScopedEntryPtr entry)
- : cache_handle_(std::move(cache_handle)), entry_(std::move(entry)) {}
-
- private:
- ~CacheStorageCacheDataHandle() override {}
-
- CacheStorageCacheHandle cache_handle_;
- disk_cache::ScopedEntryPtr entry_;
-
- DISALLOW_COPY_AND_ASSIGN(CacheStorageCacheDataHandle);
-};
-
using MetadataCallback =
base::OnceCallback<void(std::unique_ptr<proto::CacheMetadata>)>;
@@ -343,6 +325,35 @@ int64_t CalculateResponsePaddingInternal(
} // namespace
+// This class ensures that the cache and the entry have a lifetime as long as
+// the blob that is created to contain them.
+class CacheStorageCache::BlobDataHandle
+ : public storage::BlobDataBuilder::DataHandle {
+ public:
+ BlobDataHandle(CacheStorageCacheHandle cache_handle,
+ disk_cache::ScopedEntryPtr entry)
+ : cache_handle_(std::move(cache_handle)), entry_(std::move(entry)) {}
+
+ bool IsValid() override { return bool{entry_}; }
+
+ void Invalidate() {
+ cache_handle_ = base::nullopt;
+ entry_ = nullptr;
+ }
+
+ private:
+ ~BlobDataHandle() override {
+ if (cache_handle_ && cache_handle_->value()) {
+ cache_handle_->value()->blob_data_handles_.erase(this);
+ }
+ }
+
+ base::Optional<CacheStorageCacheHandle> cache_handle_;
+ disk_cache::ScopedEntryPtr entry_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlobDataHandle);
+};
+
// The state needed to pass between CacheStorageCache::Put callbacks.
struct CacheStorageCache::PutContext {
PutContext(std::unique_ptr<ServiceWorkerFetchRequest> request,
@@ -511,10 +522,9 @@ void CacheStorageCache::WriteSideData(ErrorCallback callback,
quota_manager_proxy_->GetUsageAndQuota(
base::ThreadTaskRunnerHandle::Get().get(), origin_,
blink::mojom::StorageType::kTemporary,
- base::AdaptCallbackForRepeating(
- base::BindOnce(&CacheStorageCache::WriteSideDataDidGetQuota,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback),
- url, expected_response_time, buffer, buf_len)));
+ base::BindOnce(&CacheStorageCache::WriteSideDataDidGetQuota,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback), url,
+ expected_response_time, buffer, buf_len));
}
void CacheStorageCache::BatchOperation(
@@ -557,11 +567,10 @@ void CacheStorageCache::BatchOperation(
quota_manager_proxy_->GetUsageAndQuota(
base::ThreadTaskRunnerHandle::Get().get(), origin_,
blink::mojom::StorageType::kTemporary,
- base::AdaptCallbackForRepeating(base::BindOnce(
- &CacheStorageCache::BatchDidGetUsageAndQuota,
- weak_ptr_factory_.GetWeakPtr(), std::move(operations),
- std::move(callback), std::move(bad_message_callback),
- space_required, side_data_size)));
+ base::BindOnce(&CacheStorageCache::BatchDidGetUsageAndQuota,
+ weak_ptr_factory_.GetWeakPtr(), std::move(operations),
+ std::move(callback), std::move(bad_message_callback),
+ space_required, side_data_size));
return;
}
@@ -804,8 +813,8 @@ void CacheStorageCache::QueryCache(
base::AdaptCallbackForRepeating(base::BindOnce(
&CacheStorageCache::QueryCacheDidOpenFastPath,
weak_ptr_factory_.GetWeakPtr(), std::move(query_cache_context)));
- int rv = backend_->OpenEntry(request_ptr->url.spec(), entry_ptr,
- open_entry_callback);
+ int rv = backend_->OpenEntry(request_ptr->url.spec(), net::HIGHEST,
+ entry_ptr, open_entry_callback);
if (rv != net::ERR_IO_PENDING)
std::move(open_entry_callback).Run(rv);
return;
@@ -1117,7 +1126,11 @@ void CacheStorageCache::WriteSideDataImpl(ErrorCallback callback,
expected_response_time, buffer, buf_len,
std::move(scoped_entry_ptr)));
- int rv = backend_->OpenEntry(url.spec(), entry_ptr, open_entry_callback);
+
+ // Use LOWEST priority here as writing side data is less important than
+ // loading resources on the page.
+ int rv = backend_->OpenEntry(url.spec(), net::LOWEST, entry_ptr,
+ open_entry_callback);
if (rv != net::ERR_IO_PENDING)
std::move(open_entry_callback).Run(rv);
}
@@ -1301,8 +1314,8 @@ void CacheStorageCache::PutDidDeleteEntry(
&CacheStorageCache::PutDidCreateEntry, weak_ptr_factory_.GetWeakPtr(),
std::move(scoped_entry_ptr), std::move(put_context)));
- int rv = backend_ptr->CreateEntry(request_ptr->url.spec(), entry_ptr,
- create_entry_callback);
+ int rv = backend_ptr->CreateEntry(request_ptr->url.spec(), net::HIGHEST,
+ entry_ptr, create_entry_callback);
if (rv != net::ERR_IO_PENDING)
std::move(create_entry_callback).Run(rv);
@@ -1676,6 +1689,8 @@ void CacheStorageCache::SizeImpl(SizeCallback callback) {
void CacheStorageCache::GetSizeThenCloseDidGetSize(SizeCallback callback,
int64_t cache_size) {
+ for (auto* handle : blob_data_handles_)
+ handle->Invalidate();
CloseImpl(base::BindOnce(std::move(callback), cache_size));
}
@@ -1832,9 +1847,11 @@ void CacheStorageCache::PopulateResponseBody(disk_cache::ScopedEntryPtr entry,
std::make_unique<storage::BlobDataBuilder>(response->blob_uuid);
disk_cache::Entry* temp_entry = entry.get();
+ auto data_handle = base::MakeRefCounted<BlobDataHandle>(CreateCacheHandle(),
+ std::move(entry));
+ blob_data_handles_.insert(data_handle.get());
blob_data->AppendDiskCacheEntryWithSideData(
- new CacheStorageCacheDataHandle(CreateCacheHandle(), std::move(entry)),
- temp_entry, INDEX_RESPONSE_BODY, INDEX_SIDE_DATA);
+ std::move(data_handle), temp_entry, INDEX_RESPONSE_BODY, INDEX_SIDE_DATA);
auto blob_handle =
blob_storage_context_->AddFinishedBlob(std::move(blob_data));
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.h b/chromium/content/browser/cache_storage/cache_storage_cache.h
index f343ccbf97d..f065161eedb 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.h
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.h
@@ -476,6 +476,13 @@ class CONTENT_EXPORT CacheStorageCache {
// Owns the elements of the list
BlobToDiskCacheIDMap active_blob_to_disk_cache_writers_;
+ // This class ensures that the cache and the entry have a lifetime as long as
+ // the blob that is created to contain them. We keep track of these instances
+ // to allow us to invalidate them if the cache has to be deleted while there
+ // are still references to data in it.
+ class BlobDataHandle;
+ std::set<BlobDataHandle*> blob_data_handles_;
+
// Whether or not to store data in disk or memory.
bool memory_only_;
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 92d66a32d43..d20905a639a 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -82,41 +82,46 @@ class DelayableBackend : public disk_cache::Backend {
}
int32_t GetEntryCount() const override { return backend_->GetEntryCount(); }
int OpenEntry(const std::string& key,
+ net::RequestPriority request_priority,
disk_cache::Entry** entry,
- const CompletionCallback& callback) override {
+ CompletionOnceCallback callback) override {
if (delay_open_entry_ && open_entry_callback_.is_null()) {
open_entry_callback_ = base::BindOnce(
&DelayableBackend::OpenEntryDelayedImpl, base::Unretained(this), key,
- base::Unretained(entry), callback);
+ base::Unretained(entry), std::move(callback));
return net::ERR_IO_PENDING;
}
- return backend_->OpenEntry(key, entry, callback);
+ return backend_->OpenEntry(key, request_priority, entry,
+ std::move(callback));
}
int CreateEntry(const std::string& key,
+ net::RequestPriority request_priority,
disk_cache::Entry** entry,
- const CompletionCallback& callback) override {
- return backend_->CreateEntry(key, entry, callback);
+ CompletionOnceCallback callback) override {
+ return backend_->CreateEntry(key, request_priority, entry,
+ std::move(callback));
}
int DoomEntry(const std::string& key,
- const CompletionCallback& callback) override {
- return backend_->DoomEntry(key, callback);
+ net::RequestPriority request_priority,
+ CompletionOnceCallback callback) override {
+ return backend_->DoomEntry(key, request_priority, std::move(callback));
}
- int DoomAllEntries(const CompletionCallback& callback) override {
- return backend_->DoomAllEntries(callback);
+ int DoomAllEntries(CompletionOnceCallback callback) override {
+ return backend_->DoomAllEntries(std::move(callback));
}
int DoomEntriesBetween(base::Time initial_time,
base::Time end_time,
- const CompletionCallback& callback) override {
- return backend_->DoomEntriesBetween(initial_time, end_time, callback);
+ CompletionOnceCallback callback) override {
+ return backend_->DoomEntriesBetween(initial_time, end_time,
+ std::move(callback));
}
int DoomEntriesSince(base::Time initial_time,
- const CompletionCallback& callback) override {
- return backend_->DoomEntriesSince(initial_time, callback);
+ CompletionOnceCallback callback) override {
+ return backend_->DoomEntriesSince(initial_time, std::move(callback));
}
- int CalculateSizeOfAllEntries(
- const CompletionCallback& callback) override {
- return backend_->CalculateSizeOfAllEntries(callback);
+ int CalculateSizeOfAllEntries(CompletionOnceCallback callback) override {
+ return backend_->CalculateSizeOfAllEntries(std::move(callback));
}
std::unique_ptr<Iterator> CreateIterator() override {
return backend_->CreateIterator();
@@ -148,10 +153,12 @@ class DelayableBackend : public disk_cache::Backend {
private:
void OpenEntryDelayedImpl(const std::string& key,
disk_cache::Entry** entry,
- const CompletionCallback& callback) {
- int rv = backend_->OpenEntry(key, entry, callback);
+ CompletionOnceCallback callback) {
+ auto copyable_callback =
+ base::AdaptCallbackForRepeating(std::move(callback));
+ int rv = backend_->OpenEntry(key, net::HIGHEST, entry, copyable_callback);
if (rv != net::ERR_IO_PENDING)
- callback.Run(rv);
+ copyable_callback.Run(rv);
}
std::unique_ptr<disk_cache::Backend> backend_;
@@ -746,6 +753,7 @@ class CacheStorageCacheTest : public testing::Test {
class CacheStorageCacheTestP : public CacheStorageCacheTest,
public testing::WithParamInterface<bool> {
+ public:
bool MemoryOnly() override { return !GetParam(); }
};
@@ -1824,10 +1832,19 @@ TEST_F(CacheStorageCacheTest, TestDoubleOpaquePut) {
}
TEST_P(CacheStorageCacheTestP, GetSizeThenClose) {
+ // Create the backend and put something in it.
EXPECT_TRUE(Put(body_request_, body_response_));
+ // Get a reference to the response in the cache.
+ EXPECT_TRUE(Match(body_request_));
+ blink::mojom::BlobPtr blob = callback_response_->blob->TakeBlobPtr();
+ callback_response_ = nullptr;
+
int64_t cache_size = Size();
EXPECT_EQ(cache_size, GetSizeThenClose());
VerifyAllOpsFail();
+
+ // Reading blob should fail.
+ EXPECT_TRUE(ResponseBodiesEqual("", blob.get()));
}
TEST_P(CacheStorageCacheTestP, OpsFailOnClosedBackend) {
@@ -1837,6 +1854,30 @@ TEST_P(CacheStorageCacheTestP, OpsFailOnClosedBackend) {
VerifyAllOpsFail();
}
+TEST_P(CacheStorageCacheTestP, BlobReferenceDelaysClose) {
+ // Create the backend and put something in it.
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ // Get a reference to the response in the cache.
+ EXPECT_TRUE(Match(body_request_));
+ blink::mojom::BlobPtr blob = callback_response_->blob->TakeBlobPtr();
+ callback_response_ = nullptr;
+
+ base::RunLoop loop;
+ cache_->Close(base::BindOnce(&CacheStorageCacheTest::CloseCallback,
+ base::Unretained(this),
+ base::Unretained(&loop)));
+ browser_thread_bundle_.RunUntilIdle();
+ // If MemoryOnly closing does succeed right away.
+ EXPECT_EQ(MemoryOnly(), callback_closed_);
+
+ // Reading blob should succeed.
+ EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_, blob.get()));
+ blob.reset();
+
+ loop.Run();
+ EXPECT_TRUE(callback_closed_);
+}
+
TEST_P(CacheStorageCacheTestP, VerifySerialScheduling) {
// Start two operations, the first one is delayed but the second isn't. The
// second should wait for the first.
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 17157f81340..87c836e3f98 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
@@ -129,7 +129,12 @@ void CacheStorageContextImpl::CreateCacheStorageManager(
void CacheStorageContextImpl::ShutdownOnIO() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- cache_manager_.reset();
+ // Release |cache_manager_|. New clients will get a nullptr if they request
+ // an instance of CacheStorageManager after this. Any other client that
+ // ref-wrapped |cache_manager_| will be able to continue using it, and the
+ // CacheStorageManager will be destroyed when all the references are
+ // destroyed.
+ cache_manager_ = nullptr;
}
} // namespace content
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 47c28f06ce8..cedfd960e13 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.h
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.h
@@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/cache_storage_context.h"
#include "content/public/browser/cache_storage_usage_info.h"
@@ -98,7 +99,7 @@ class CONTENT_EXPORT CacheStorageContextImpl : public CacheStorageContext {
bool is_incognito_ = false;
// Only accessed on the IO thread.
- std::unique_ptr<CacheStorageManager> cache_manager_;
+ scoped_refptr<CacheStorageManager> cache_manager_;
};
} // namespace content
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.cc b/chromium/content/browser/cache_storage/cache_storage_manager.cc
index eb0fbd228dd..be479cf1d69 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.cc
@@ -28,7 +28,6 @@
#include "content/browser/cache_storage/cache_storage.pb.h"
#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/url_util.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/common/database/database_identifier.h"
@@ -153,7 +152,7 @@ void OneOriginSizeReported(base::OnceClosure callback,
} // namespace
// static
-std::unique_ptr<CacheStorageManager> CacheStorageManager::Create(
+scoped_refptr<CacheStorageManager> CacheStorageManager::Create(
const base::FilePath& path,
scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) {
@@ -163,14 +162,14 @@ std::unique_ptr<CacheStorageManager> CacheStorageManager::Create(
.AppendASCII("CacheStorage");
}
- return base::WrapUnique(new CacheStorageManager(
+ return base::WrapRefCounted(new CacheStorageManager(
root_path, std::move(cache_task_runner), std::move(quota_manager_proxy)));
}
// static
-std::unique_ptr<CacheStorageManager> CacheStorageManager::Create(
+scoped_refptr<CacheStorageManager> CacheStorageManager::Create(
CacheStorageManager* old_manager) {
- std::unique_ptr<CacheStorageManager> manager(new CacheStorageManager(
+ scoped_refptr<CacheStorageManager> manager(new CacheStorageManager(
old_manager->root_path(), old_manager->cache_task_runner(),
old_manager->quota_manager_proxy_.get()));
// These values may be NULL, in which case this will be called again later by
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.h b/chromium/content/browser/cache_storage/cache_storage_manager.h
index e94dfa631b4..e7460ce34f8 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.h
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.h
@@ -13,9 +13,11 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
#include "content/browser/cache_storage/cache_storage.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/common/content_export.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cache_storage_context.h"
#include "content/public/browser/cache_storage_usage_info.h"
#include "net/url_request/url_request_context_getter.h"
@@ -55,14 +57,16 @@ enum class CacheStorageOwner {
// CacheStorageManager per ServiceWorkerContextCore.
// TODO(jkarlin): Remove CacheStorage from memory once they're no
// longer in active use.
-class CONTENT_EXPORT CacheStorageManager {
+class CONTENT_EXPORT CacheStorageManager
+ : public base::RefCountedThreadSafe<CacheStorageManager,
+ BrowserThread::DeleteOnIOThread> {
public:
- static std::unique_ptr<CacheStorageManager> Create(
+ static scoped_refptr<CacheStorageManager> Create(
const base::FilePath& path,
scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
- static std::unique_ptr<CacheStorageManager> Create(
+ static scoped_refptr<CacheStorageManager> Create(
CacheStorageManager* old_manager);
// Map a database identifier (computed from an origin) to the path.
@@ -70,8 +74,6 @@ class CONTENT_EXPORT CacheStorageManager {
const url::Origin& origin,
CacheStorageOwner owner);
- virtual ~CacheStorageManager();
-
// Methods to support the CacheStorage spec. These methods call the
// corresponding CacheStorage method on the appropriate thread.
void OpenCache(const url::Origin& origin,
@@ -131,9 +133,12 @@ class CONTENT_EXPORT CacheStorageManager {
base::FilePath root_path() const { return root_path_; }
private:
- friend class CacheStorageContextImpl;
+ friend class base::DeleteHelper<CacheStorageManager>;
+ friend class base::RefCountedThreadSafe<CacheStorageManager>;
friend class cache_storage_manager_unittest::CacheStorageManagerTest;
+ friend class CacheStorageContextImpl;
friend class CacheStorageQuotaClient;
+ friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
typedef std::map<std::pair<url::Origin, CacheStorageOwner>,
std::unique_ptr<CacheStorage>>
@@ -144,6 +149,8 @@ class CONTENT_EXPORT CacheStorageManager {
scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
+ virtual ~CacheStorageManager();
+
// The returned CacheStorage* is owned by this manager.
CacheStorage* FindOrCreateCacheStorage(const url::Origin& origin,
CacheStorageOwner owner);
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 e779d23257c..d62569b7672 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -636,7 +636,7 @@ class CacheStorageManagerTest : public testing::Test {
scoped_refptr<MockSpecialStoragePolicy> quota_policy_;
scoped_refptr<MockQuotaManager> mock_quota_manager_;
scoped_refptr<MockCacheStorageQuotaManagerProxy> quota_manager_proxy_;
- std::unique_ptr<CacheStorageManager> cache_manager_;
+ scoped_refptr<CacheStorageManager> cache_manager_;
CacheStorageCacheHandle callback_cache_handle_;
int callback_bool_;
diff --git a/chromium/content/browser/cache_storage/cache_storage_operation_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_operation_unittest.cc
index b1bd4a25961..5f9597f21cc 100644
--- a/chromium/content/browser/cache_storage/cache_storage_operation_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_operation_unittest.cc
@@ -8,7 +8,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/test_mock_time_task_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc
index b1869a2723c..f071c1d5c05 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -26,9 +26,8 @@ ChildProcessLauncher::ChildProcessLauncher(
std::unique_ptr<base::CommandLine> command_line,
int child_process_id,
Client* client,
- std::unique_ptr<mojo::edk::OutgoingBrokerClientInvitation>
- broker_client_invitation,
- const mojo::edk::ProcessErrorCallback& process_error_callback,
+ mojo::OutgoingInvitation mojo_invitation,
+ const mojo::ProcessErrorCallback& process_error_callback,
bool terminate_on_shutdown)
: client_(client),
starting_(true),
@@ -47,7 +46,7 @@ ChildProcessLauncher::ChildProcessLauncher(
helper_ = new ChildProcessLauncherHelper(
child_process_id, client_thread_id_, std::move(command_line),
std::move(delegate), weak_factory_.GetWeakPtr(), terminate_on_shutdown,
- std::move(broker_client_invitation), process_error_callback);
+ std::move(mojo_invitation), process_error_callback);
helper_->StartLaunchOnClientThread();
}
@@ -169,7 +168,13 @@ ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
bool ChildProcessLauncherPriority::operator==(
const ChildProcessLauncherPriority& other) const {
- return background == other.background && frame_depth == other.frame_depth &&
+ // |should_boost_for_pending_views| is temporary and constant for all
+ // ChildProcessLauncherPriority throughout a session (experiment driven).
+ DCHECK_EQ(should_boost_for_pending_views,
+ other.should_boost_for_pending_views);
+ return visible == other.visible &&
+ has_media_stream == other.has_media_stream &&
+ frame_depth == other.frame_depth &&
boost_for_pending_views == other.boost_for_pending_views
#if defined(OS_ANDROID)
&& importance == other.importance
diff --git a/chromium/content/browser/child_process_launcher.h b/chromium/content/browser/child_process_launcher.h
index 04787554d23..190ee370186 100644
--- a/chromium/content/browser/child_process_launcher.h
+++ b/chromium/content/browser/child_process_launcher.h
@@ -22,8 +22,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_termination_info.h"
#include "content/public/common/result_codes.h"
-#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/public/cpp/system/invitation.h"
#if defined(OS_ANDROID)
#include "content/public/browser/android/child_process_importance.h"
@@ -57,17 +56,75 @@ static_assert(static_cast<int>(LAUNCH_RESULT_START) >
#endif
struct ChildProcessLauncherPriority {
- bool background;
- unsigned int frame_depth;
- bool boost_for_pending_views;
+ ChildProcessLauncherPriority(bool visible,
+ bool has_media_stream,
+ unsigned int frame_depth,
+ bool boost_for_pending_views,
+ bool should_boost_for_pending_views
#if defined(OS_ANDROID)
- ChildProcessImportance importance;
+ ,
+ ChildProcessImportance importance
+#endif
+ )
+ : visible(visible),
+ has_media_stream(has_media_stream),
+ frame_depth(frame_depth),
+ boost_for_pending_views(boost_for_pending_views),
+ should_boost_for_pending_views(should_boost_for_pending_views)
+#if defined(OS_ANDROID)
+ ,
+ importance(importance)
#endif
+ {
+ }
+
+ // Returns true if the child process is backgrounded.
+ bool is_background() const {
+ return !visible && !has_media_stream &&
+ !(should_boost_for_pending_views && boost_for_pending_views);
+ }
bool operator==(const ChildProcessLauncherPriority& other) const;
bool operator!=(const ChildProcessLauncherPriority& other) const {
return !(*this == other);
}
+
+ // Prefer |is_background()| to inspecting these fields individually (to ensure
+ // all logic uses the same notion of "backgrounded").
+
+ // |visible| is true if the process is responsible for one or more widget(s)
+ // in foreground tabs. The notion of "visible" is determined by the embedder
+ // but is ideally a widget in a non-minimized, non-background, non-occluded
+ // tab (i.e. with pixels visible on the screen).
+ bool visible;
+
+ // |has_media_stream| is true when the process is responsible for "hearable"
+ // content.
+ bool has_media_stream;
+
+ // |frame_depth| is the depth of the shallowest frame this process is
+ // responsible for which has |visible| visibility. It only makes sense to
+ // compare this property for two ChildProcessLauncherPriority instances with
+ // matching |visible| properties.
+ unsigned int frame_depth;
+
+ // |boost_for_pending_views| is true if this process is responsible for a
+ // pending view (this is used to boost priority of a process responsible for
+ // foreground content which hasn't yet been added as a visible widget -- i.e.
+ // during navigation).
+ bool boost_for_pending_views;
+
+ // True iff |boost_for_pending_views| should be considered in
+ // |is_background()|. This needs to be a separate parameter as opposed to
+ // having the experiment set |boost_for_pending_views == false| when
+ // |!should_boost_for_pending_views| as that would result in different
+ // |is_background()| logic than before and defeat the purpose of the
+ // experiment. TODO(gab): Remove this field when the
+ // BoostRendererPriorityForPendingViews desktop experiment is over.
+ bool should_boost_for_pending_views;
+#if defined(OS_ANDROID)
+ ChildProcessImportance importance;
+#endif
};
// Launches a process asynchronously and notifies the client of the process
@@ -101,9 +158,8 @@ class CONTENT_EXPORT ChildProcessLauncher {
std::unique_ptr<base::CommandLine> cmd_line,
int child_process_id,
Client* client,
- std::unique_ptr<mojo::edk::OutgoingBrokerClientInvitation>
- broker_client_invitation,
- const mojo::edk::ProcessErrorCallback& process_error_callback,
+ mojo::OutgoingInvitation mojo_invitation,
+ const mojo::ProcessErrorCallback& process_error_callback,
bool terminate_on_shutdown = true);
~ChildProcessLauncher();
diff --git a/chromium/content/browser/child_process_launcher_helper.cc b/chromium/content/browser/child_process_launcher_helper.cc
index b9ad8d7ed5e..d4272efe0e4 100644
--- a/chromium/content/browser/child_process_launcher_helper.cc
+++ b/chromium/content/browser/child_process_launcher_helper.cc
@@ -16,7 +16,7 @@
#include "content/public/browser/child_process_launcher_utils.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
#if defined(OS_ANDROID)
#include "content/browser/android/launcher_thread.h"
@@ -69,32 +69,27 @@ ChildProcessLauncherHelper::ChildProcessLauncherHelper(
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
const base::WeakPtr<ChildProcessLauncher>& child_process_launcher,
bool terminate_on_shutdown,
- std::unique_ptr<mojo::edk::OutgoingBrokerClientInvitation>
- broker_client_invitation,
- const mojo::edk::ProcessErrorCallback& process_error_callback)
+ mojo::OutgoingInvitation mojo_invitation,
+ const mojo::ProcessErrorCallback& process_error_callback)
: child_process_id_(child_process_id),
client_thread_id_(client_thread_id),
command_line_(std::move(command_line)),
delegate_(std::move(delegate)),
child_process_launcher_(child_process_launcher),
terminate_on_shutdown_(terminate_on_shutdown),
- broker_client_invitation_(std::move(broker_client_invitation)),
+ mojo_invitation_(std::move(mojo_invitation)),
process_error_callback_(process_error_callback) {}
-ChildProcessLauncherHelper::~ChildProcessLauncherHelper() {
-}
+ChildProcessLauncherHelper::~ChildProcessLauncherHelper() = default;
void ChildProcessLauncherHelper::StartLaunchOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
BeforeLaunchOnClientThread();
- mojo_server_handle_ = PrepareMojoPipeHandlesOnClientThread();
- if (!mojo_server_handle_.is_valid()) {
- mojo::edk::PlatformChannelPair channel_pair;
- mojo_server_handle_ = channel_pair.PassServerHandle();
- mojo_client_handle_ = channel_pair.PassClientHandle();
- }
+ mojo_named_channel_ = CreateNamedPlatformChannelOnClientThread();
+ if (!mojo_named_channel_)
+ mojo_channel_.emplace();
GetProcessLauncherTaskRunner()->PostTask(
FROM_HERE,
@@ -130,10 +125,8 @@ void ChildProcessLauncherHelper::LaunchOnLauncherThread() {
void ChildProcessLauncherHelper::PostLaunchOnLauncherThread(
ChildProcessLauncherHelper::Process process,
int launch_result) {
- // Release the client handle now that the process has been started (the pipe
- // may not signal when the process dies otherwise and we would not detect the
- // child process died).
- mojo_client_handle_.reset();
+ if (mojo_channel_)
+ mojo_channel_->RemoteProcessLaunchAttempted();
if (process.process.IsValid()) {
RecordHistogramsOnLauncherThread(base::TimeTicks::Now() -
@@ -142,16 +135,20 @@ void ChildProcessLauncherHelper::PostLaunchOnLauncherThread(
// Take ownership of the broker client invitation here so it's destroyed when
// we go out of scope regardless of the outcome below.
- std::unique_ptr<mojo::edk::OutgoingBrokerClientInvitation> invitation =
- std::move(broker_client_invitation_);
+ mojo::OutgoingInvitation invitation = std::move(mojo_invitation_);
if (process.process.IsValid()) {
// Set up Mojo IPC to the new process.
- DCHECK(invitation);
- invitation->Send(
- process.process.Handle(),
- mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy,
- std::move(mojo_server_handle_)),
- process_error_callback_);
+ if (mojo_channel_) {
+ DCHECK(mojo_channel_->local_endpoint().is_valid());
+ mojo::OutgoingInvitation::Send(
+ std::move(invitation), process.process.Handle(),
+ mojo_channel_->TakeLocalEndpoint(), process_error_callback_);
+ } else {
+ DCHECK(mojo_named_channel_);
+ mojo::OutgoingInvitation::Send(
+ std::move(invitation), process.process.Handle(),
+ mojo_named_channel_->TakeServerEndpoint(), process_error_callback_);
+ }
}
BrowserThread::PostTask(
diff --git a/chromium/content/browser/child_process_launcher_helper.h b/chromium/content/browser/child_process_launcher_helper.h
index 51d54bb4ab6..da64a5c3df0 100644
--- a/chromium/content/browser/child_process_launcher_helper.h
+++ b/chromium/content/browser/child_process_launcher_helper.h
@@ -9,14 +9,15 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/optional.h"
#include "base/process/kill.h"
#include "base/process/process.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/result_codes.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/public/cpp/platform/named_platform_channel.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+#include "mojo/public/cpp/system/invitation.h"
#include "services/catalog/public/cpp/manifest_parsing_util.h"
#include "services/service_manager/zygote/common/zygote_buildflags.h"
@@ -34,6 +35,10 @@
#include "sandbox/mac/seatbelt_exec.h"
#endif
+#if defined(OS_FUCHSIA)
+#include "content/common/sandbox_policy_fuchsia.h"
+#endif
+
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
#include "services/service_manager/zygote/common/zygote_handle.h" // nogncheck
#endif
@@ -90,9 +95,8 @@ class ChildProcessLauncherHelper :
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
const base::WeakPtr<ChildProcessLauncher>& child_process_launcher,
bool terminate_on_shutdown,
- std::unique_ptr<mojo::edk::OutgoingBrokerClientInvitation>
- broker_client_invitation,
- const mojo::edk::ProcessErrorCallback& process_error_callback);
+ mojo::OutgoingInvitation mojo_invitation,
+ const mojo::ProcessErrorCallback& process_error_callback);
// The methods below are defined in the order they are called.
@@ -102,10 +106,11 @@ class ChildProcessLauncherHelper :
// Platform specific.
void BeforeLaunchOnClientThread();
- // Called in to give implementors a chance at creating a server pipe.
- // Platform specific.
- mojo::edk::ScopedInternalPlatformHandle
- PrepareMojoPipeHandlesOnClientThread();
+ // Called to give implementors a chance at creating a server pipe. Platform-
+ // specific. Returns |base::nullopt| if the helper should initialize
+ // a regular PlatformChannel for communication instead.
+ base::Optional<mojo::NamedPlatformChannel>
+ CreateNamedPlatformChannelOnClientThread();
// Returns the list of files that should be mapped in the child process.
// Platform specific.
@@ -189,9 +194,6 @@ class ChildProcessLauncherHelper :
void LaunchOnLauncherThread();
- const mojo::edk::InternalPlatformHandle& mojo_client_handle() const {
- return mojo_client_handle_.get();
- }
base::CommandLine* command_line() { return command_line_.get(); }
int child_process_id() const { return child_process_id_; }
@@ -212,12 +214,21 @@ class ChildProcessLauncherHelper :
std::unique_ptr<base::CommandLine> command_line_;
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate_;
base::WeakPtr<ChildProcessLauncher> child_process_launcher_;
- mojo::edk::ScopedInternalPlatformHandle mojo_client_handle_;
- mojo::edk::ScopedInternalPlatformHandle mojo_server_handle_;
+
+ // The PlatformChannel that will be used to transmit an invitation to the
+ // child process in most cases. Only used if the platform's helper
+ // implementation doesn't return a server endpoint from
+ // |CreateNamedPlatformChannelOnClientThread()|.
+ base::Optional<mojo::PlatformChannel> mojo_channel_;
+
+ // May be used in exclusion to the above if the platform helper implementation
+ // returns a valid server endpoint from
+ // |CreateNamedPlatformChannelOnClientThread()|.
+ base::Optional<mojo::NamedPlatformChannel> mojo_named_channel_;
+
bool terminate_on_shutdown_;
- std::unique_ptr<mojo::edk::OutgoingBrokerClientInvitation>
- broker_client_invitation_;
- const mojo::edk::ProcessErrorCallback process_error_callback_;
+ mojo::OutgoingInvitation mojo_invitation_;
+ const mojo::ProcessErrorCallback process_error_callback_;
#if defined(OS_MACOSX)
std::unique_ptr<sandbox::SeatbeltExecClient> seatbelt_exec_client_;
@@ -227,6 +238,10 @@ class ChildProcessLauncherHelper :
base::android::ScopedJavaGlobalRef<jobject> java_peer_;
bool java_peer_avaiable_on_client_thread_ = false;
#endif
+
+#if defined(OS_FUCHSIA)
+ SandboxPolicyFuchsia sandbox_policy_;
+#endif
};
} // namespace internal
diff --git a/chromium/content/browser/child_process_launcher_helper_android.cc b/chromium/content/browser/child_process_launcher_helper_android.cc
index 07c1a74cec2..2115d7f830c 100644
--- a/chromium/content/browser/child_process_launcher_helper_android.cc
+++ b/chromium/content/browser/child_process_launcher_helper_android.cc
@@ -5,6 +5,7 @@
#include <memory>
#include "base/android/apk_assets.h"
+#include "base/android/application_status_listener.h"
#include "base/android/jni_array.h"
#include "base/i18n/icu_util.h"
#include "base/logging.h"
@@ -19,7 +20,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_descriptors.h"
#include "content/public/common/content_switches.h"
-#include "jni/ChildProcessLauncherHelper_jni.h"
+#include "jni/ChildProcessLauncherHelperImpl_jni.h"
#include "services/service_manager/sandbox/switches.h"
using base::android::AttachCurrentThread;
@@ -37,7 +38,7 @@ void StopChildProcess(base::ProcessHandle handle) {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
- Java_ChildProcessLauncherHelper_stop(env, static_cast<jint>(handle));
+ Java_ChildProcessLauncherHelperImpl_stop(env, static_cast<jint>(handle));
}
} // namespace
@@ -48,9 +49,6 @@ void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
command_line()->GetSwitchValueASCII(switches::kProcessType);
CHECK(process_type == switches::kGpuProcess ||
process_type == switches::kRendererProcess ||
-#if BUILDFLAG(ENABLE_PLUGINS)
- process_type == switches::kPpapiPluginProcess ||
-#endif
process_type == switches::kUtilityProcess)
<< "Unsupported process type: " << process_type;
@@ -59,9 +57,9 @@ void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
!command_line()->HasSwitch(service_manager::switches::kNoSandbox));
}
-mojo::edk::ScopedInternalPlatformHandle
-ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
- return mojo::edk::ScopedInternalPlatformHandle();
+base::Optional<mojo::NamedPlatformChannel>
+ChildProcessLauncherHelper::CreateNamedPlatformChannelOnClientThread() {
+ return base::nullopt;
}
std::unique_ptr<PosixFileDescriptorInfo>
@@ -73,7 +71,8 @@ ChildProcessLauncherHelper::GetFilesToMap() {
CHECK(!command_line()->HasSwitch(switches::kSingleProcess));
std::unique_ptr<PosixFileDescriptorInfo> files_to_register =
- CreateDefaultPosixFilesToMap(child_process_id(), mojo_client_handle(),
+ CreateDefaultPosixFilesToMap(child_process_id(),
+ mojo_channel_->remote_endpoint(),
true /* include_service_required_files */,
GetProcessType(), command_line());
@@ -123,8 +122,8 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
const auto& region = files_to_register->GetRegionAt(i);
bool auto_close = files_to_register->OwnsFD(fd);
ScopedJavaLocalRef<jobject> j_file_info =
- Java_ChildProcessLauncherHelper_makeFdInfo(env, id, fd, auto_close,
- region.offset, region.size);
+ Java_ChildProcessLauncherHelperImpl_makeFdInfo(
+ env, id, fd, auto_close, region.offset, region.size);
PCHECK(j_file_info.obj());
env->SetObjectArrayElement(j_file_infos.obj(), i, j_file_info.obj());
if (auto_close) {
@@ -132,7 +131,7 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
}
}
- java_peer_.Reset(Java_ChildProcessLauncherHelper_createAndStart(
+ java_peer_.Reset(Java_ChildProcessLauncherHelperImpl_createAndStart(
env, reinterpret_cast<intptr_t>(this), j_argv, j_file_infos));
AddRef(); // Balanced by OnChildProcessStarted.
BrowserThread::PostTask(
@@ -153,19 +152,21 @@ ChildProcessTerminationInfo ChildProcessLauncherHelper::GetTerminationInfo(
const ChildProcessLauncherHelper::Process& process,
bool known_dead) {
ChildProcessTerminationInfo info;
- info.has_oom_protection_bindings =
- java_peer_avaiable_on_client_thread_ &&
- Java_ChildProcessLauncherHelper_hasOomProtectionBindings(
- AttachCurrentThread(), java_peer_);
- info.was_killed_intentionally_by_browser =
- java_peer_avaiable_on_client_thread_ &&
- Java_ChildProcessLauncherHelper_isKilledByUs(AttachCurrentThread(),
- java_peer_);
+ if (!java_peer_avaiable_on_client_thread_)
+ return info;
+
+ Java_ChildProcessLauncherHelperImpl_getTerminationInfo(
+ AttachCurrentThread(), java_peer_, reinterpret_cast<intptr_t>(&info));
+
+ base::android::ApplicationState app_state =
+ base::android::ApplicationStatusListener::GetState();
bool app_foreground =
- java_peer_avaiable_on_client_thread_ &&
- Java_ChildProcessLauncherHelper_isApplicationInForeground(
- AttachCurrentThread(), java_peer_);
- if (app_foreground && info.has_oom_protection_bindings) {
+ app_state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES ||
+ app_state == base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES;
+
+ if (app_foreground &&
+ (info.binding_state == base::android::ChildBindingState::MODERATE ||
+ info.binding_state == base::android::ChildBindingState::STRONG)) {
info.status = base::TERMINATION_STATUS_OOM_PROTECTED;
} else {
// Note waitpid does not work on Android since these are not actually child
@@ -175,6 +176,28 @@ ChildProcessTerminationInfo ChildProcessLauncherHelper::GetTerminationInfo(
return info;
}
+static void JNI_ChildProcessLauncherHelperImpl_SetTerminationInfo(
+ JNIEnv* env,
+ const JavaParamRef<jclass>&,
+ jlong termination_info_ptr,
+ jint binding_state,
+ jboolean killed_by_us,
+ jint remaining_process_with_strong_binding,
+ jint remaining_process_with_moderate_binding,
+ jint remaining_process_with_waived_binding) {
+ ChildProcessTerminationInfo* info =
+ reinterpret_cast<ChildProcessTerminationInfo*>(termination_info_ptr);
+ info->binding_state =
+ static_cast<base::android::ChildBindingState>(binding_state);
+ info->was_killed_intentionally_by_browser = killed_by_us;
+ info->remaining_process_with_strong_binding =
+ remaining_process_with_strong_binding;
+ info->remaining_process_with_moderate_binding =
+ remaining_process_with_moderate_binding;
+ info->remaining_process_with_waived_binding =
+ remaining_process_with_waived_binding;
+}
+
// static
bool ChildProcessLauncherHelper::TerminateProcess(const base::Process& process,
int exit_code) {
@@ -197,10 +220,10 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
const ChildProcessLauncherPriority& priority) {
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
- return Java_ChildProcessLauncherHelper_setPriority(
- env, java_peer_, process.Handle(), !priority.background,
- priority.frame_depth, priority.boost_for_pending_views,
- static_cast<jint>(priority.importance));
+ return Java_ChildProcessLauncherHelperImpl_setPriority(
+ env, java_peer_, process.Handle(), priority.visible,
+ priority.has_media_stream, priority.frame_depth,
+ priority.boost_for_pending_views, static_cast<jint>(priority.importance));
}
// static
diff --git a/chromium/content/browser/child_process_launcher_helper_fuchsia.cc b/chromium/content/browser/child_process_launcher_helper_fuchsia.cc
index cd3095ce794..c834ebd29b4 100644
--- a/chromium/content/browser/child_process_launcher_helper_fuchsia.cc
+++ b/chromium/content/browser/child_process_launcher_helper_fuchsia.cc
@@ -10,7 +10,6 @@
#include "content/common/sandbox_policy_fuchsia.h"
#include "content/public/browser/child_process_launcher_utils.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
#include "services/service_manager/embedder/result_codes.h"
namespace content {
@@ -55,15 +54,14 @@ void ChildProcessLauncherHelper::ResetRegisteredFilesForTesting() {
void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
+
+ sandbox_policy_.Initialize(delegate_->GetSandboxType());
}
-mojo::edk::ScopedInternalPlatformHandle
-ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
+base::Optional<mojo::NamedPlatformChannel>
+ChildProcessLauncherHelper::CreateNamedPlatformChannelOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
-
- // By doing nothing here, StartLaunchOnClientThread() will construct a channel
- // pair instead.
- return mojo::edk::ScopedInternalPlatformHandle();
+ return base::nullopt;
}
std::unique_ptr<FileMappedForLaunch>
@@ -77,10 +75,9 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
base::LaunchOptions* options) {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
- mojo::edk::PlatformChannelPair::PrepareToPassHandleToChildProcess(
- mojo_client_handle(), command_line(), &options->handles_to_transfer);
-
- UpdateLaunchOptionsForSandbox(delegate_->GetSandboxType(), options);
+ mojo_channel_->PrepareToPassRemoteEndpoint(&options->handles_to_transfer,
+ command_line());
+ sandbox_policy_.UpdateLaunchOptionsForSandbox(options);
return true;
}
@@ -92,7 +89,8 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
bool* is_synchronous_launch,
int* launch_result) {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
- DCHECK(mojo_client_handle().is_valid());
+ DCHECK(mojo_channel_);
+ DCHECK(mojo_channel_->remote_endpoint().is_valid());
// TODO(750938): Implement sandboxed/isolated subprocess launching.
Process child_process;
@@ -103,14 +101,6 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
const ChildProcessLauncherHelper::Process& process,
const base::LaunchOptions& options) {
- DCHECK(CurrentlyOnProcessLauncherTaskRunner());
-
- if (process.process.IsValid()) {
- // |mojo_client_handle_| has already been transferred to the child process
- // by this point. Remove it from the scoped container so that we don't
- // erroneously delete it.
- ignore_result(mojo_client_handle_.release());
- }
}
// static
diff --git a/chromium/content/browser/child_process_launcher_helper_linux.cc b/chromium/content/browser/child_process_launcher_helper_linux.cc
index 5db82c367aa..c981f7fc90f 100644
--- a/chromium/content/browser/child_process_launcher_helper_linux.cc
+++ b/chromium/content/browser/child_process_launcher_helper_linux.cc
@@ -15,7 +15,6 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
-#include "gpu/config/gpu_switches.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
#include "services/service_manager/zygote/common/zygote_handle.h"
@@ -25,10 +24,10 @@
namespace content {
namespace internal {
-mojo::edk::ScopedInternalPlatformHandle
-ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
+base::Optional<mojo::NamedPlatformChannel>
+ChildProcessLauncherHelper::CreateNamedPlatformChannelOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
- return mojo::edk::ScopedInternalPlatformHandle();
+ return base::nullopt;
}
void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
@@ -38,7 +37,8 @@ void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
std::unique_ptr<FileMappedForLaunch>
ChildProcessLauncherHelper::GetFilesToMap() {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
- return CreateDefaultPosixFilesToMap(child_process_id(), mojo_client_handle(),
+ return CreateDefaultPosixFilesToMap(child_process_id(),
+ mojo_channel_->remote_endpoint(),
true /* include_service_required_files */,
GetProcessType(), command_line());
}
@@ -50,10 +50,7 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
options->fds_to_remap = files_to_register.GetMappingWithIDAdjustment(
base::GlobalDescriptors::kBaseDescriptor);
- if (GetProcessType() == switches::kRendererProcess ||
- (GetProcessType() == switches::kGpuProcess &&
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableOOPRasterization))) {
+ if (GetProcessType() == switches::kRendererProcess) {
const int sandbox_fd = SandboxHostLinux::GetInstance()->GetChildSocket();
options->fds_to_remap.push_back(
std::make_pair(sandbox_fd, service_manager::GetSandboxFD()));
@@ -161,7 +158,7 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
const ChildProcessLauncherPriority& priority) {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
if (process.CanBackgroundProcesses())
- process.SetProcessBackgrounded(priority.background);
+ process.SetProcessBackgrounded(priority.is_background());
}
// static
diff --git a/chromium/content/browser/child_process_launcher_helper_mac.cc b/chromium/content/browser/child_process_launcher_helper_mac.cc
index 902177996e1..3fd28bf7589 100644
--- a/chromium/content/browser/child_process_launcher_helper_mac.cc
+++ b/chromium/content/browser/child_process_launcher_helper_mac.cc
@@ -6,6 +6,7 @@
#include "base/feature_list.h"
#include "base/path_service.h"
#include "base/posix/global_descriptors.h"
+#include "base/strings/stringprintf.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/child_process_launcher_helper.h"
#include "content/browser/child_process_launcher_helper_posix.h"
@@ -19,7 +20,6 @@
#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/scoped_platform_handle.h"
#include "sandbox/mac/seatbelt_exec.h"
#include "services/service_manager/embedder/result_codes.h"
#include "services/service_manager/sandbox/mac/cdm.sb.h"
@@ -37,10 +37,10 @@
namespace content {
namespace internal {
-mojo::edk::ScopedInternalPlatformHandle
-ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
+base::Optional<mojo::NamedPlatformChannel>
+ChildProcessLauncherHelper::CreateNamedPlatformChannelOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
- return mojo::edk::ScopedInternalPlatformHandle();
+ return base::nullopt;
}
void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
@@ -51,7 +51,7 @@ std::unique_ptr<PosixFileDescriptorInfo>
ChildProcessLauncherHelper::GetFilesToMap() {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
return CreateDefaultPosixFilesToMap(
- child_process_id(), mojo_client_handle(),
+ child_process_id(), mojo_channel_->remote_endpoint(),
false /* include_service_required_files */, GetProcessType(),
command_line());
}
@@ -171,8 +171,8 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
// Update the command line to enable the V2 sandbox and pass the
// communication FD to the helper executable.
- command_line_->AppendSwitch(switches::kEnableV2Sandbox);
- command_line_->AppendArg("--fd_mapping=" + std::to_string(pipe));
+ command_line_->AppendArg(
+ base::StringPrintf("%s%d", sandbox::switches::kSeatbeltClient, pipe));
}
// Hold the MachBroker lock for the duration of LaunchProcess. The child will
@@ -259,7 +259,7 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
const ChildProcessLauncherPriority& priority) {
if (process.CanBackgroundProcesses()) {
process.SetProcessBackgrounded(MachBroker::GetInstance(),
- priority.background);
+ priority.is_background());
}
}
diff --git a/chromium/content/browser/child_process_launcher_helper_posix.cc b/chromium/content/browser/child_process_launcher_helper_posix.cc
index 60aedf2a364..bdd38c9cc61 100644
--- a/chromium/content/browser/child_process_launcher_helper_posix.cc
+++ b/chromium/content/browser/child_process_launcher_helper_posix.cc
@@ -14,7 +14,7 @@
#include "content/public/common/content_client.h"
#include "content/public/common/content_descriptors.h"
#include "content/public/common/content_switches.h"
-#include "mojo/edk/embedder/platform_handle.h"
+#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
#include "services/catalog/public/cpp/manifest_parsing_util.h"
#include "services/service_manager/embedder/shared_file_util.h"
#include "services/service_manager/embedder/switches.h"
@@ -73,7 +73,7 @@ base::PlatformFile OpenFileIfNecessary(const base::FilePath& path,
std::unique_ptr<PosixFileDescriptorInfo> CreateDefaultPosixFilesToMap(
int child_process_id,
- const mojo::edk::InternalPlatformHandle& mojo_client_handle,
+ const mojo::PlatformChannelEndpoint& mojo_channel_remote_endpoint,
bool include_service_required_files,
const std::string& process_type,
base::CommandLine* command_line) {
@@ -87,9 +87,10 @@ std::unique_ptr<PosixFileDescriptorInfo> CreateDefaultPosixFilesToMap(
base::SharedMemory::GetFdFromSharedMemoryHandle(shm));
}
- DCHECK(mojo_client_handle.is_valid());
- files_to_register->Share(service_manager::kMojoIPCChannel,
- mojo_client_handle.handle);
+ DCHECK(mojo_channel_remote_endpoint.is_valid());
+ files_to_register->Share(
+ service_manager::kMojoIPCChannel,
+ mojo_channel_remote_endpoint.platform_handle().GetFD().get());
// TODO(jcivelli): remove this "if defined" by making
// GetAdditionalMappedFilesForChildProcess a no op on Mac.
diff --git a/chromium/content/browser/child_process_launcher_helper_posix.h b/chromium/content/browser/child_process_launcher_helper_posix.h
index df353a54a11..956c6d3a5a9 100644
--- a/chromium/content/browser/child_process_launcher_helper_posix.h
+++ b/chromium/content/browser/child_process_launcher_helper_posix.h
@@ -17,10 +17,8 @@ class FilePath;
} // namespace base
namespace mojo {
-namespace edk {
-struct InternalPlatformHandle;
+class PlatformChannelEndpoint;
} // namespace mojo
-} // namespace edk
// Contains the common functionalities between the various POSIX child process
// launcher implementations.
@@ -33,7 +31,7 @@ namespace internal {
std::unique_ptr<PosixFileDescriptorInfo> CreateDefaultPosixFilesToMap(
int child_process_id,
- const mojo::edk::InternalPlatformHandle& mojo_client_handle,
+ const mojo::PlatformChannelEndpoint& mojo_channel_remote_endpoint,
bool include_service_required_files,
const std::string& process_type,
base::CommandLine* command_line);
diff --git a/chromium/content/browser/child_process_launcher_helper_win.cc b/chromium/content/browser/child_process_launcher_helper_win.cc
index 46c2dbea83d..4deb9438f18 100644
--- a/chromium/content/browser/child_process_launcher_helper_win.cc
+++ b/chromium/content/browser/child_process_launcher_helper_win.cc
@@ -14,9 +14,8 @@
#include "content/public/common/result_codes.h"
#include "content/public/common/sandbox_init.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
-#include "mojo/edk/embedder/named_platform_channel_pair.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/public/cpp/platform/named_platform_channel.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
#include "sandbox/win/src/sandbox_types.h"
#include "services/service_manager/embedder/result_codes.h"
#include "services/service_manager/sandbox/win/sandbox_win.h"
@@ -28,16 +27,17 @@ void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
}
-mojo::edk::ScopedInternalPlatformHandle
-ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
+base::Optional<mojo::NamedPlatformChannel>
+ChildProcessLauncherHelper::CreateNamedPlatformChannelOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
if (!delegate_->ShouldLaunchElevated())
- return mojo::edk::ScopedInternalPlatformHandle();
+ return base::nullopt;
- mojo::edk::NamedPlatformChannelPair named_pair;
- named_pair.PrepareToPassClientHandleToChildProcess(command_line());
- return named_pair.PassServerHandle();
+ mojo::NamedPlatformChannel::Options options;
+ mojo::NamedPlatformChannel named_channel(options);
+ named_channel.PassServerNameOnCommandLine(command_line());
+ return named_channel;
}
std::unique_ptr<FileMappedForLaunch>
@@ -70,11 +70,8 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
return process;
}
base::HandlesToInheritVector handles;
- handles.push_back(mojo_client_handle().handle);
+ mojo_channel_->PrepareToPassRemoteEndpoint(&handles, command_line());
base::FieldTrialList::AppendFieldTrialHandleIfNeeded(&handles);
- command_line()->AppendSwitchASCII(
- mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch,
- base::UintToString(base::win::HandleToUint32(handles[0])));
ChildProcessLauncherHelper::Process process;
*launch_result = StartSandboxedProcess(
delegate_.get(),
@@ -118,7 +115,7 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
const ChildProcessLauncherPriority& priority) {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
if (process.CanBackgroundProcesses())
- process.SetProcessBackgrounded(priority.background);
+ process.SetProcessBackgrounded(priority.is_background());
}
// static
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index 4bf51fd3352..1272be30040 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -117,13 +117,30 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
file_permissions_.size());
}
- // Grant permission to request URLs with the specified origin.
- void GrantOrigin(const url::Origin& origin) {
- origin_set_.insert(origin);
+ // Grant permission to request and commit URLs with the specified origin.
+ void GrantCommitOrigin(const url::Origin& origin) {
+ if (origin.unique())
+ return;
+ origin_map_[origin] = CommitRequestPolicy::kCommitAndRequest;
+ }
+
+ void GrantRequestOrigin(const url::Origin& origin) {
+ if (origin.unique())
+ return;
+ // Anything already in |origin_map_| must have at least request permission
+ // already. In that case, the emplace() below will be a no-op.
+ origin_map_.emplace(origin, CommitRequestPolicy::kRequestOnly);
+ }
+
+ void GrantCommitScheme(const std::string& scheme) {
+ scheme_map_[scheme] = CommitRequestPolicy::kCommitAndRequest;
}
- // Grant permission to request URLs with the specified scheme.
- void GrantScheme(const std::string& scheme) { scheme_policy_.insert(scheme); }
+ void GrantRequestScheme(const std::string& scheme) {
+ // Anything already in |scheme_map_| must have at least request permission
+ // already. In that case, the emplace() below will be a no-op.
+ scheme_map_.emplace(scheme, CommitRequestPolicy::kRequestOnly);
+ }
// Grant certain permissions to a file.
void GrantPermissionsForFile(const base::FilePath& file, int permissions) {
@@ -194,26 +211,25 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
can_send_midi_sysex_ = true;
}
- bool CanCommitOrigin(const url::Origin& origin) {
- return base::ContainsKey(origin_set_, origin);
- }
-
// Determine whether permission has been granted to commit |url|.
bool CanCommitURL(const GURL& url) {
DCHECK(!url.SchemeIsBlob() && !url.SchemeIsFileSystem())
<< "inner_url extraction should be done already.";
// Having permission to a scheme implies permission to all of its URLs.
- SchemeSet::const_iterator scheme_judgment(
- scheme_policy_.find(url.scheme()));
- if (scheme_judgment != scheme_policy_.end())
+ auto scheme_judgment = scheme_map_.find(url.scheme());
+ if (scheme_judgment != scheme_map_.end() &&
+ scheme_judgment->second == CommitRequestPolicy::kCommitAndRequest) {
return true;
+ }
- // Otherwise, check for permission for specific origin.
+ // Check for permission for specific origin.
if (CanCommitOrigin(url::Origin::Create(url)))
return true;
- // file:// URLs are more granular. The child may have been given
- // permission to a specific file but not the file:// scheme in general.
+ // file:// URLs may sometimes be more granular, e.g. dragging and dropping a
+ // file from the local filesystem. The child itself may not have been
+ // granted access to the entire file:// scheme, but it should still be
+ // allowed to request the dragged and dropped file.
if (url.SchemeIs(url::kFileScheme)) {
base::FilePath path;
if (net::FileURLToFilePath(url, &path))
@@ -223,6 +239,22 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
return false; // Unmentioned schemes are disallowed.
}
+ bool CanRequestURL(const GURL& url) {
+ DCHECK(!url.SchemeIsBlob() && !url.SchemeIsFileSystem())
+ << "inner_url extraction should be done already.";
+ // Having permission to a scheme implies permission to all of its URLs.
+ auto scheme_judgment = scheme_map_.find(url.scheme());
+ if (scheme_judgment != scheme_map_.end())
+ return true;
+
+ if (CanRequestOrigin(url::Origin::Create(url)))
+ return true;
+
+ // Otherwise, delegate to CanCommitURL. Unmentioned schemes are disallowed.
+ // TODO(dcheng): It would be nice to avoid constructing the origin twice.
+ return CanCommitURL(url);
+ }
+
// Determine if the certain permissions have been granted to a file.
bool HasPermissionsForFile(const base::FilePath& file, int permissions) {
#if defined(OS_ANDROID)
@@ -280,7 +312,7 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
}
bool has_web_ui_bindings() const {
- return enabled_bindings_ & BINDINGS_POLICY_WEB_UI;
+ return enabled_bindings_ & kWebUIBindingsPolicyMask;
}
bool can_read_raw_cookies() const {
@@ -292,22 +324,39 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
}
private:
- typedef std::set<std::string> SchemeSet;
- typedef std::set<url::Origin> OriginSet;
+ enum class CommitRequestPolicy {
+ kRequestOnly,
+ kCommitAndRequest,
+ };
+
+ bool CanCommitOrigin(const url::Origin& origin) {
+ auto it = origin_map_.find(origin);
+ if (it == origin_map_.end())
+ return false;
+ return it->second == CommitRequestPolicy::kCommitAndRequest;
+ }
+
+ bool CanRequestOrigin(const url::Origin& origin) {
+ // Anything already in |origin_map_| must have at least request permissions
+ // already.
+ return origin_map_.find(origin) != origin_map_.end();
+ }
+
+ typedef std::map<std::string, CommitRequestPolicy> SchemeMap;
+ typedef std::map<url::Origin, CommitRequestPolicy> OriginMap;
typedef int FilePermissionFlags; // bit-set of base::File::Flags
typedef std::map<base::FilePath, FilePermissionFlags> FileMap;
typedef std::map<std::string, FilePermissionFlags> FileSystemMap;
typedef std::set<base::FilePath> FileSet;
- // Maps URL schemes to whether permission has been granted, containment means
- // that the scheme has been granted, otherwise, it has never been granted.
- // There is no provision for revoking.
- SchemeSet scheme_policy_;
+ // Maps URL schemes to commit/request policies the child process has been
+ // granted. There is no provision for revoking.
+ SchemeMap scheme_map_;
- // The set of URL origins to which the child process has been granted
- // permission.
- OriginSet origin_set_;
+ // The map of URL origins to commit/request policies the child process has
+ // been granted. There is no provision for revoking.
+ OriginMap origin_map_;
// The set of files the child process is permited to upload to the web.
FileMap file_permissions_;
@@ -431,34 +480,57 @@ bool ChildProcessSecurityPolicyImpl::IsPseudoScheme(
return base::ContainsKey(pseudo_schemes_, scheme);
}
-void ChildProcessSecurityPolicyImpl::GrantRequestURL(
- int child_id, const GURL& url) {
-
+void ChildProcessSecurityPolicyImpl::GrantCommitURL(int child_id,
+ const GURL& url) {
+ // Can't grant the capability to commit invalid URLs.
if (!url.is_valid())
- return; // Can't grant the capability to request invalid URLs.
-
- const std::string& scheme = url.scheme();
+ return;
- if (IsWebSafeScheme(scheme))
- return; // The scheme has already been whitelisted for every child process.
+ // Can't grant the capability to commit pseudo schemes.
+ if (IsPseudoScheme(url.scheme()))
+ return;
- if (IsPseudoScheme(scheme)) {
- return; // Can't grant the capability to request pseudo schemes.
- }
+ url::Origin origin = url::Origin::Create(url);
+ // Blob and filesystem URLs require special treatment; grant access to the
+ // inner origin they embed instead.
+ // TODO(dcheng): Can this logic be simplified to just derive an origin up
+ // front and use that? That probably requires fixing GURL canonicalization of
+ // blob URLs though. For now, be consistent with how CanRequestURL and
+ // CanCommitURL normalize.
if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) {
- return; // Don't grant blanket access to blob: or filesystem: schemes.
+ if (IsMalformedBlobUrl(url))
+ return;
+
+ GrantCommitURL(child_id, GURL(origin.Serialize()));
}
- {
- base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
- if (state == security_state_.end())
- return;
+ // TODO(dcheng): In the future, URLs with opaque origins would ideally carry
+ // around an origin with them, so we wouldn't need to grant commit access to
+ // the entire scheme.
+ if (!origin.unique())
+ GrantCommitOrigin(child_id, origin);
+
+ // The scheme has already been whitelisted for every child process, so no need
+ // to do anything else.
+ if (IsWebSafeScheme(url.scheme()))
+ return;
+
+ base::AutoLock lock(lock_);
- // When the child process has been commanded to request this scheme,
- // we grant it the capability to request all URLs of that scheme.
- state->second->GrantScheme(scheme);
+ auto state = security_state_.find(child_id);
+ if (state == security_state_.end())
+ return;
+
+ if (origin.unique()) {
+ // If it's impossible to grant commit rights to just the origin (among other
+ // things, URLs with non-standard schemes will be treated as opaque
+ // origins), then grant access to commit all URLs of that scheme.
+ state->second->GrantCommitScheme(url.scheme());
+ } else {
+ // When the child process has been commanded to request this scheme, grant
+ // it the capability to request all URLs of that scheme.
+ state->second->GrantRequestScheme(url.scheme());
}
}
@@ -565,42 +637,61 @@ void ChildProcessSecurityPolicyImpl::GrantSendMidiSysExMessage(int child_id) {
state->second->GrantPermissionForMidiSysEx();
}
-void ChildProcessSecurityPolicyImpl::GrantOrigin(int child_id,
- const url::Origin& origin) {
+void ChildProcessSecurityPolicyImpl::GrantCommitOrigin(
+ int child_id,
+ const url::Origin& origin) {
base::AutoLock lock(lock_);
SecurityStateMap::iterator state = security_state_.find(child_id);
if (state == security_state_.end())
return;
- state->second->GrantOrigin(origin);
+ state->second->GrantCommitOrigin(origin);
}
-void ChildProcessSecurityPolicyImpl::GrantScheme(int child_id,
- const std::string& scheme) {
+void ChildProcessSecurityPolicyImpl::GrantRequestOrigin(
+ int child_id,
+ const url::Origin& origin) {
base::AutoLock lock(lock_);
SecurityStateMap::iterator state = security_state_.find(child_id);
if (state == security_state_.end())
return;
- state->second->GrantScheme(scheme);
+ state->second->GrantRequestOrigin(origin);
+}
+
+void ChildProcessSecurityPolicyImpl::GrantRequestScheme(
+ int child_id,
+ const std::string& scheme) {
+ base::AutoLock lock(lock_);
+
+ auto state = security_state_.find(child_id);
+ if (state == security_state_.end())
+ return;
+
+ state->second->GrantRequestScheme(scheme);
}
-void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id) {
+void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id,
+ int bindings) {
+ // Only WebUI bindings should come through here.
+ CHECK(bindings & kWebUIBindingsPolicyMask);
+ CHECK_EQ(0, bindings & ~kWebUIBindingsPolicyMask);
+
base::AutoLock lock(lock_);
SecurityStateMap::iterator state = security_state_.find(child_id);
if (state == security_state_.end())
return;
- state->second->GrantBindings(BINDINGS_POLICY_WEB_UI);
+ state->second->GrantBindings(bindings);
// Web UI bindings need the ability to request chrome: URLs.
- state->second->GrantScheme(kChromeUIScheme);
+ state->second->GrantRequestScheme(kChromeUIScheme);
// Web UI pages can contain links to file:// URLs.
- state->second->GrantScheme(url::kFileScheme);
+ state->second->GrantRequestScheme(url::kFileScheme);
}
void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id) {
@@ -630,35 +721,43 @@ bool ChildProcessSecurityPolicyImpl::CanRequestURL(
const std::string& scheme = url.scheme();
- if (IsPseudoScheme(scheme)) {
- // Every child process can request <about:blank>, <about:blank?foo>,
- // <about:blank/#foo> and <about:srcdoc>.
- if (url.IsAboutBlank() || url == kAboutSrcDocURL)
- return true;
- // URLs like <about:version>, <about:crash>, <view-source:...> shouldn't be
- // requestable by any child process. Also, this case covers
- // <javascript:...>, which should be handled internally by the process and
- // not kicked up to the browser.
- return false;
- }
+ // Every child process can request <about:blank>, <about:blank?foo>,
+ // <about:blank/#foo> and <about:srcdoc>.
+ //
+ // URLs like <about:version>, <about:crash>, <view-source:...> shouldn't be
+ // requestable by any child process. Also, this case covers
+ // <javascript:...>, which should be handled internally by the process and
+ // not kicked up to the browser.
+ // TODO(dcheng): Figure out why this check is different from CanCommitURL,
+ // which checks for direct equality with kAboutBlankURL.
+ if (IsPseudoScheme(scheme))
+ return url.IsAboutBlank() || url == kAboutSrcDocURL;
- // Blob and filesystem URLs require special treatment, since they embed an
- // inner origin.
+ // Blob and filesystem URLs require special treatment; validate the inner
+ // origin they embed.
if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) {
if (IsMalformedBlobUrl(url))
return false;
url::Origin origin = url::Origin::Create(url);
- return origin.unique() || IsWebSafeScheme(origin.scheme()) ||
- CanCommitURL(child_id, GURL(origin.Serialize()));
+ return origin.unique() || CanRequestURL(child_id, GURL(origin.Serialize()));
}
if (IsWebSafeScheme(scheme))
return true;
- // If the process can commit the URL, it can request it.
- if (CanCommitURL(child_id, url))
- return true;
+ {
+ base::AutoLock lock(lock_);
+
+ SecurityStateMap::iterator state = security_state_.find(child_id);
+ if (state == security_state_.end())
+ return false;
+
+ // Otherwise, we consult the child process's security state to see if it is
+ // allowed to request the URL.
+ if (state->second->CanRequestURL(url))
+ return true;
+ }
// Also allow URLs destined for ShellExecute and not the browser itself.
return !GetContentClient()->browser()->IsHandledURL(url) &&
@@ -1047,18 +1146,12 @@ bool ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin(int child_id,
return can_access;
}
-bool ChildProcessSecurityPolicyImpl::HasSpecificPermissionForOrigin(
- int child_id,
- const url::Origin& origin) {
- base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
- if (state == security_state_.end())
- return false;
- return state->second->CanCommitOrigin(origin);
-}
-
void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id,
const GURL& gurl) {
+ // LockToOrigin should only be called on the UI thread (OTOH, it is okay to
+ // call GetOriginLock or CheckOriginLock from any thread).
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
// "gurl" can be currently empty in some cases, such as file://blah.
DCHECK(SiteInstanceImpl::GetSiteForURL(nullptr, gurl) == gurl);
base::AutoLock lock(lock_);
diff --git a/chromium/content/browser/child_process_security_policy_impl.h b/chromium/content/browser/child_process_security_policy_impl.h
index 47eb3321976..a82411ecdce 100644
--- a/chromium/content/browser/child_process_security_policy_impl.h
+++ b/chromium/content/browser/child_process_security_policy_impl.h
@@ -75,8 +75,9 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
const std::string& filesystem_id) override;
void GrantDeleteFromFileSystem(int child_id,
const std::string& filesystem_id) override;
- void GrantOrigin(int child_id, const url::Origin& origin) override;
- void GrantScheme(int child_id, const std::string& scheme) override;
+ void GrantCommitOrigin(int child_id, const url::Origin& origin) override;
+ void GrantRequestOrigin(int child_id, const url::Origin& origin) override;
+ void GrantRequestScheme(int child_id, const std::string& scheme) override;
bool CanRequestURL(int child_id, const GURL& url) override;
bool CanCommitURL(int child_id, const GURL& url) override;
bool CanReadFile(int child_id, const base::FilePath& file) override;
@@ -93,8 +94,6 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
bool HasWebUIBindings(int child_id) override;
void GrantSendMidiSysExMessage(int child_id) override;
bool CanAccessDataForOrigin(int child_id, const GURL& url) override;
- bool HasSpecificPermissionForOrigin(int child_id,
- const url::Origin& origin) override;
bool GetMatchingIsolatedOrigin(const url::Origin& origin,
url::Origin* result) override;
@@ -137,11 +136,11 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// this method exactly once.
void Remove(int child_id);
- // Whenever the browser processes commands the child process to request a URL,
+ // Whenever the browser processes commands the child process to commit a URL,
// it should call this method to grant the child process the capability to
- // request the URL, along with permission to request all URLs of the same
- // scheme.
- void GrantRequestURL(int child_id, const GURL& url);
+ // commit anything from the URL's origin, along with permission to request all
+ // URLs of the same scheme.
+ void GrantCommitURL(int child_id, const GURL& url);
// Whenever the browser process drops a file icon on a tab, it should call
// this method to grant the child process the capability to request this one
@@ -151,8 +150,9 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// Revokes all permissions granted to the given file.
void RevokeAllPermissionsForFile(int child_id, const base::FilePath& file);
- // Grant the child process the ability to use Web UI Bindings.
- void GrantWebUIBindings(int child_id);
+ // Grant the child process the ability to use Web UI Bindings where |bindings|
+ // is either BINDINGS_POLICY_WEB_UI or BINDINGS_POLICY_MOJO_WEB_UI or both.
+ void GrantWebUIBindings(int child_id, int bindings);
// Grant the child process the ability to read raw cookies.
void GrantReadRawCookies(int child_id);
@@ -183,8 +183,9 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
bool CanReadRawCookies(int child_id);
// Sets the process as only permitted to use and see the cookies for the
- // given origin.
- void LockToOrigin(int child_id, const GURL& gurl);
+ // given origin. Most callers should use RenderProcessHostImpl::LockToOrigin
+ // instead of calling this directly.
+ void LockToOrigin(int child_id, const GURL& lock_url);
// Used to indicate the result of comparing a process's origin lock to
// another value:
diff --git a/chromium/content/browser/child_process_security_policy_unittest.cc b/chromium/content/browser/child_process_security_policy_unittest.cc
index 499cf3ac9eb..57bc04c9d8c 100644
--- a/chromium/content/browser/child_process_security_policy_unittest.cc
+++ b/chromium/content/browser/child_process_security_policy_unittest.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/test/mock_log.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/public/common/bindings_policy.h"
#include "content/public/common/url_constants.h"
#include "content/test/test_content_browser_client.h"
#include "storage/browser/fileapi/file_permission_policy.h"
@@ -342,20 +343,12 @@ TEST_F(ChildProcessSecurityPolicyTest, AboutTest) {
EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, GURL("aBoUt:version")));
// Requests for about: pages should be denied.
- p->GrantRequestURL(kRendererID, GURL("about:crash"));
+ p->GrantCommitURL(kRendererID, GURL("about:crash"));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:crash")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("about:crash")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:crash")));
EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, GURL("about:crash")));
- // These requests for chrome:// pages should be granted.
- GURL chrome_url("chrome://foo");
- p->GrantRequestURL(kRendererID, chrome_url);
- EXPECT_TRUE(p->CanRequestURL(kRendererID, chrome_url));
- EXPECT_TRUE(p->CanRedirectToURL(GURL(chrome_url)));
- EXPECT_TRUE(p->CanCommitURL(kRendererID, chrome_url));
- EXPECT_TRUE(p->CanSetAsOriginHeader(kRendererID, chrome_url));
-
p->Remove(kRendererID);
}
@@ -370,7 +363,7 @@ TEST_F(ChildProcessSecurityPolicyTest, JavaScriptTest) {
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("javascript:alert('xss')")));
EXPECT_FALSE(
p->CanSetAsOriginHeader(kRendererID, GURL("javascript:alert('xss')")));
- p->GrantRequestURL(kRendererID, GURL("javascript:alert('xss')"));
+ p->GrantCommitURL(kRendererID, GURL("javascript:alert('xss')"));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("javascript:alert('xss')")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("javascript:alert('xss')")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("javascript:alert('xss')")));
@@ -422,7 +415,7 @@ TEST_F(ChildProcessSecurityPolicyTest, CanServiceCommandsTest) {
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("file:///etc/passwd")));
EXPECT_FALSE(
p->CanSetAsOriginHeader(kRendererID, GURL("file:///etc/passwd")));
- p->GrantRequestURL(kRendererID, GURL("file:///etc/passwd"));
+ p->GrantCommitURL(kRendererID, GURL("file:///etc/passwd"));
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("file:///etc/passwd")));
EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("file:///etc/passwd")));
@@ -481,7 +474,7 @@ TEST_F(ChildProcessSecurityPolicyTest, ViewSource) {
EXPECT_FALSE(p->CanSetAsOriginHeader(
kRendererID, GURL("view-source:view-source:http://www.google.com/")));
- p->GrantRequestURL(kRendererID, GURL("view-source:file:///etc/passwd"));
+ p->GrantCommitURL(kRendererID, GURL("view-source:file:///etc/passwd"));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("file:///etc/passwd")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("file:///etc/passwd")));
@@ -497,6 +490,44 @@ TEST_F(ChildProcessSecurityPolicyTest, ViewSource) {
p->Remove(kRendererID);
}
+TEST_F(ChildProcessSecurityPolicyTest, GrantCommitURLToNonStandardScheme) {
+ ChildProcessSecurityPolicyImpl* p =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+
+ const GURL url("httpxml://awesome");
+ const GURL url2("httpxml://also-awesome");
+
+ ASSERT_TRUE(url::Origin::Create(url).unique());
+ ASSERT_TRUE(url::Origin::Create(url2).unique());
+ RegisterTestScheme("httpxml");
+
+ p->Add(kRendererID);
+
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, url2));
+ EXPECT_TRUE(p->CanRedirectToURL(url));
+ EXPECT_TRUE(p->CanRedirectToURL(url2));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url2));
+ EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, url));
+ EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, url2));
+
+ // GrantCommitURL with a non-standard scheme should grant commit access to the
+ // entire scheme.
+ p->GrantCommitURL(kRendererID, url);
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, url2));
+ EXPECT_TRUE(p->CanRedirectToURL(url));
+ EXPECT_TRUE(p->CanRedirectToURL(url2));
+ EXPECT_TRUE(p->CanCommitURL(kRendererID, url));
+ EXPECT_TRUE(p->CanCommitURL(kRendererID, url2));
+ EXPECT_TRUE(p->CanSetAsOriginHeader(kRendererID, url));
+ EXPECT_TRUE(p->CanSetAsOriginHeader(kRendererID, url2));
+
+ p->Remove(kRendererID);
+}
+
TEST_F(ChildProcessSecurityPolicyTest, SpecificFile) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -524,7 +555,7 @@ TEST_F(ChildProcessSecurityPolicyTest, SpecificFile) {
EXPECT_TRUE(p->CanSetAsOriginHeader(kRendererID, icon_url));
EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, sensitive_url));
- p->GrantRequestURL(kRendererID, icon_url);
+ p->GrantCommitURL(kRendererID, icon_url);
EXPECT_TRUE(p->CanRequestURL(kRendererID, icon_url));
EXPECT_TRUE(p->CanRequestURL(kRendererID, sensitive_url));
EXPECT_TRUE(p->CanRedirectToURL(icon_url));
@@ -833,19 +864,121 @@ TEST_F(ChildProcessSecurityPolicyTest, CanServiceWebUIBindings) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
- GURL url("chrome://thumb/http://www.google.com/");
+ const GURL url("chrome://thumb/http://www.google.com/");
+ const GURL other_url("chrome://not-thumb/");
+ const url::Origin origin = url::Origin::Create(url);
+ {
+ p->Add(kRendererID);
- p->Add(kRendererID);
+ EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
- EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
- EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
- EXPECT_TRUE(p->CanRedirectToURL(url));
- p->GrantWebUIBindings(kRendererID);
- EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
- EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
- EXPECT_TRUE(p->CanRedirectToURL(url));
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
+ EXPECT_TRUE(p->CanRedirectToURL(url));
- p->Remove(kRendererID);
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
+ EXPECT_TRUE(p->CanRedirectToURL(other_url));
+
+ p->GrantWebUIBindings(kRendererID, BINDINGS_POLICY_WEB_UI);
+
+ EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
+ EXPECT_TRUE(p->CanRedirectToURL(url));
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, other_url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
+ EXPECT_TRUE(p->CanRedirectToURL(other_url));
+
+ p->GrantCommitOrigin(kRendererID, origin);
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
+ EXPECT_TRUE(p->CanCommitURL(kRendererID, url));
+ EXPECT_TRUE(p->CanRedirectToURL(url));
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, other_url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
+ EXPECT_TRUE(p->CanRedirectToURL(other_url));
+
+ p->Remove(kRendererID);
+ }
+ {
+ p->Add(kRendererID);
+
+ EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
+
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
+ EXPECT_TRUE(p->CanRedirectToURL(url));
+
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
+ EXPECT_TRUE(p->CanRedirectToURL(other_url));
+
+ p->GrantWebUIBindings(kRendererID, BINDINGS_POLICY_MOJO_WEB_UI);
+
+ EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
+ EXPECT_TRUE(p->CanRedirectToURL(url));
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, other_url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
+ EXPECT_TRUE(p->CanRedirectToURL(other_url));
+
+ p->GrantCommitOrigin(kRendererID, origin);
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
+ EXPECT_TRUE(p->CanCommitURL(kRendererID, url));
+ EXPECT_TRUE(p->CanRedirectToURL(url));
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, other_url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
+ EXPECT_TRUE(p->CanRedirectToURL(other_url));
+
+ p->Remove(kRendererID);
+ }
+ {
+ p->Add(kRendererID);
+
+ EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
+
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
+ EXPECT_TRUE(p->CanRedirectToURL(url));
+
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
+ EXPECT_TRUE(p->CanRedirectToURL(other_url));
+
+ p->GrantWebUIBindings(kRendererID,
+ BINDINGS_POLICY_WEB_UI | BINDINGS_POLICY_MOJO_WEB_UI);
+
+ EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
+ EXPECT_TRUE(p->CanRedirectToURL(url));
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, other_url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
+ EXPECT_TRUE(p->CanRedirectToURL(other_url));
+
+ p->GrantCommitOrigin(kRendererID, origin);
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
+ EXPECT_TRUE(p->CanCommitURL(kRendererID, url));
+ EXPECT_TRUE(p->CanRedirectToURL(url));
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, other_url));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
+ EXPECT_TRUE(p->CanRedirectToURL(other_url));
+
+ p->Remove(kRendererID);
+ }
}
TEST_F(ChildProcessSecurityPolicyTest, RemoveRace) {
@@ -857,9 +990,10 @@ TEST_F(ChildProcessSecurityPolicyTest, RemoveRace) {
p->Add(kRendererID);
- p->GrantRequestURL(kRendererID, url);
+ p->GrantCommitURL(kRendererID, url);
p->GrantReadFile(kRendererID, file);
- p->GrantWebUIBindings(kRendererID);
+ p->GrantWebUIBindings(kRendererID,
+ BINDINGS_POLICY_WEB_UI | BINDINGS_POLICY_MOJO_WEB_UI);
EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
@@ -904,7 +1038,22 @@ TEST_F(ChildProcessSecurityPolicyTest, OriginGranting) {
EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, url_foo2));
EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, url_bar));
- p->GrantOrigin(kRendererID, url::Origin::Create(url_foo1));
+ p->GrantRequestOrigin(kRendererID, url::Origin::Create(url_foo1));
+
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo1));
+ EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo2));
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, url_bar));
+ EXPECT_TRUE(p->CanRedirectToURL(url_foo1));
+ EXPECT_TRUE(p->CanRedirectToURL(url_foo2));
+ EXPECT_TRUE(p->CanRedirectToURL(url_bar));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url_foo1));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url_foo2));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url_bar));
+ EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, url_foo1));
+ EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, url_foo2));
+ EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, url_bar));
+
+ p->GrantCommitOrigin(kRendererID, url::Origin::Create(url_foo1));
EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo1));
EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo2));
@@ -919,20 +1068,21 @@ TEST_F(ChildProcessSecurityPolicyTest, OriginGranting) {
EXPECT_TRUE(p->CanSetAsOriginHeader(kRendererID, url_foo2));
EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, url_bar));
- p->GrantScheme(kRendererID, kChromeUIScheme);
+ // Make sure this doesn't overwrite the earlier commit grants.
+ p->GrantRequestOrigin(kRendererID, url::Origin::Create(url_foo1));
EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo1));
EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo2));
- EXPECT_TRUE(p->CanRequestURL(kRendererID, url_bar));
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, url_bar));
EXPECT_TRUE(p->CanRedirectToURL(url_foo1));
EXPECT_TRUE(p->CanRedirectToURL(url_foo2));
EXPECT_TRUE(p->CanRedirectToURL(url_bar));
EXPECT_TRUE(p->CanCommitURL(kRendererID, url_foo1));
EXPECT_TRUE(p->CanCommitURL(kRendererID, url_foo2));
- EXPECT_TRUE(p->CanCommitURL(kRendererID, url_bar));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, url_bar));
EXPECT_TRUE(p->CanSetAsOriginHeader(kRendererID, url_foo1));
EXPECT_TRUE(p->CanSetAsOriginHeader(kRendererID, url_foo2));
- EXPECT_TRUE(p->CanSetAsOriginHeader(kRendererID, url_bar));
+ EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, url_bar));
p->Remove(kRendererID);
}
diff --git a/chromium/content/browser/code_cache/generated_code_cache.cc b/chromium/content/browser/code_cache/generated_code_cache.cc
new file mode 100644
index 00000000000..c74c9a32d40
--- /dev/null
+++ b/chromium/content/browser/code_cache/generated_code_cache.cc
@@ -0,0 +1,383 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/code_cache/generated_code_cache.h"
+#include "base/memory/ptr_util.h"
+#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
+#include "net/http/http_util.h"
+
+namespace content {
+
+namespace {
+// Checks if |requesting_origin| is allowed to cache code for |resource_url|.
+// |resource_url| is the url corresponding to the requested resource.
+// If this url is invalid we don't cache the code.
+// |requesting_origin| is the origin that has requested the resource.
+// If this is a unique origin, then we don't cache the code.
+// For example, if http://script.com/script1.js is requested by
+// http://example.com, then http://script.com/script.js is the resource_url
+// and example.com is the requesting_origin.
+bool IsAllowedToCache(const GURL& resource_url,
+ const url::Origin& requesting_origin) {
+ // Don't cache the code corresponding to unique origins. The same-origin
+ // checks should always fail for unique origins but the serialized value of
+ // unique origins does not ensure this.
+ if (requesting_origin.unique())
+ return false;
+
+ // If the resource url or requesting url is invalid don't cache the code.
+ if (!resource_url.is_valid())
+ return false;
+
+ return true;
+}
+
+// Generates the cache key for the given |resource_url| and the
+// |requesting_origin|. This returns the key by concatenating the
+// serialized url and origin with a separator in between.
+std::string GetCacheKey(const GURL& resource_url,
+ const url::Origin& requesting_origin) {
+ DCHECK(!requesting_origin.unique());
+ DCHECK(resource_url.is_valid());
+ // Add a prefix _ so it can't be parsed as a valid URL.
+ std::string key = "_key";
+ // Remove reference, username and password sections of the URL.
+ key.append(net::HttpUtil::SpecForRequest(resource_url));
+ // Add a separator between URL and origin to avoid any possibility of
+ // attacks by crafting the URL. URLs do not contain any control ASCII
+ // characters, and also space is encoded. So use ' \n' as a seperator.
+ key.append(" \n");
+ key.append(requesting_origin.Serialize());
+ return key;
+}
+} // namespace
+
+// Stores the information about a pending request while disk backend is
+// being initialized.
+class GeneratedCodeCache::PendingOperation {
+ public:
+ PendingOperation(Operation op,
+ std::string key,
+ scoped_refptr<net::IOBufferWithSize>);
+ PendingOperation(Operation op, std::string key, const ReadDataCallback&);
+ PendingOperation(Operation op, std::string key);
+
+ ~PendingOperation();
+
+ Operation operation() const { return op_; }
+ const std::string& key() const { return key_; }
+ const scoped_refptr<net::IOBufferWithSize> data() const { return data_; }
+ const ReadDataCallback& callback() const { return callback_; }
+
+ private:
+ const Operation op_;
+ const std::string key_;
+ const scoped_refptr<net::IOBufferWithSize> data_;
+ const ReadDataCallback callback_;
+};
+
+GeneratedCodeCache::PendingOperation::PendingOperation(
+ Operation op,
+ std::string key,
+ scoped_refptr<net::IOBufferWithSize> buffer)
+ : op_(op),
+ key_(std::move(key)),
+ data_(buffer),
+ callback_(ReadDataCallback()) {}
+
+GeneratedCodeCache::PendingOperation::PendingOperation(
+ Operation op,
+ std::string key,
+ const ReadDataCallback& callback)
+ : op_(op),
+ key_(std::move(key)),
+ data_(scoped_refptr<net::IOBufferWithSize>()),
+ callback_(callback) {}
+
+GeneratedCodeCache::PendingOperation::PendingOperation(Operation op,
+ std::string key)
+ : op_(op),
+ key_(std::move(key)),
+ data_(scoped_refptr<net::IOBufferWithSize>()),
+ callback_(ReadDataCallback()) {}
+
+GeneratedCodeCache::PendingOperation::~PendingOperation() = default;
+
+// Static factory method.
+std::unique_ptr<GeneratedCodeCache> GeneratedCodeCache::Create(
+ const base::FilePath& path,
+ int max_size_bytes) {
+ return base::WrapUnique(new GeneratedCodeCache(path, max_size_bytes));
+}
+
+GeneratedCodeCache::~GeneratedCodeCache() = default;
+
+void GeneratedCodeCache::WriteData(
+ const GURL& url,
+ const url::Origin& origin,
+ scoped_refptr<net::IOBufferWithSize> buffer) {
+ // Silently ignore the requests.
+ if (backend_state_ == kFailed)
+ return;
+
+ // If the url is invalid or if it is from a unique origin, we should not
+ // cache the code.
+ if (!IsAllowedToCache(url, origin))
+ return;
+
+ std::string key = GetCacheKey(url, origin);
+ if (backend_state_ != kInitialized) {
+ // Insert it into the list of pending operations while the backend is
+ // still being opened.
+ pending_ops_.push_back(std::make_unique<PendingOperation>(
+ Operation::kWrite, std::move(key), buffer));
+ return;
+ }
+
+ WriteDataImpl(key, buffer);
+}
+
+void GeneratedCodeCache::FetchEntry(const GURL& url,
+ const url::Origin& origin,
+ ReadDataCallback read_data_callback) {
+ if (backend_state_ == kFailed) {
+ // Silently ignore the requests.
+ std::move(read_data_callback).Run(scoped_refptr<net::IOBufferWithSize>());
+ return;
+ }
+
+ // If the url is invalid or if it is from a unique origin, we should not
+ // cache the code.
+ if (!IsAllowedToCache(url, origin)) {
+ std::move(read_data_callback).Run(scoped_refptr<net::IOBufferWithSize>());
+ return;
+ }
+
+ std::string key = GetCacheKey(url, origin);
+ if (backend_state_ != kInitialized) {
+ // Insert it into the list of pending operations while the backend is
+ // still being opened.
+ pending_ops_.push_back(std::make_unique<PendingOperation>(
+ Operation::kFetch, std::move(key), read_data_callback));
+ return;
+ }
+
+ FetchEntryImpl(key, read_data_callback);
+}
+
+void GeneratedCodeCache::DeleteEntry(const GURL& url,
+ const url::Origin& origin) {
+ // Silently ignore the requests.
+ if (backend_state_ == kFailed)
+ return;
+
+ // If the url is invalid or if it is from a unique origin, we should not
+ // cache the code.
+ if (!IsAllowedToCache(url, origin))
+ return;
+
+ std::string key = GetCacheKey(url, origin);
+ if (backend_state_ != kInitialized) {
+ // Insert it into the list of pending operations while the backend is
+ // still being opened.
+ pending_ops_.push_back(
+ std::make_unique<PendingOperation>(Operation::kDelete, std::move(key)));
+ return;
+ }
+
+ DeleteEntryImpl(key);
+}
+
+GeneratedCodeCache::GeneratedCodeCache(const base::FilePath& path,
+ int max_size_bytes)
+ : backend_state_(kUnInitialized),
+ path_(path),
+ max_size_bytes_(max_size_bytes),
+ weak_ptr_factory_(this) {
+ CreateBackend();
+}
+
+void GeneratedCodeCache::CreateBackend() {
+ // Create a new Backend pointer that cleans itself if the GeneratedCodeCache
+ // instance is not live when the CreateCacheBackend finishes.
+ scoped_refptr<base::RefCountedData<ScopedBackendPtr>> shared_backend_ptr =
+ new base::RefCountedData<ScopedBackendPtr>();
+
+ net::CompletionOnceCallback create_backend_complete =
+ base::BindOnce(&GeneratedCodeCache::DidCreateBackend,
+ weak_ptr_factory_.GetWeakPtr(), shared_backend_ptr);
+
+ // If the initialization of the existing cache fails, this call would delete
+ // all the contents and recreates a new one.
+ int rv = disk_cache::CreateCacheBackend(
+ net::GENERATED_CODE_CACHE, net::CACHE_BACKEND_SIMPLE, path_,
+ max_size_bytes_, true, nullptr, &shared_backend_ptr->data,
+ std::move(create_backend_complete));
+ if (rv != net::ERR_IO_PENDING) {
+ DidCreateBackend(shared_backend_ptr, rv);
+ }
+}
+
+void GeneratedCodeCache::DidCreateBackend(
+ scoped_refptr<base::RefCountedData<ScopedBackendPtr>> backend_ptr,
+ int rv) {
+ if (rv != net::OK) {
+ backend_state_ = kFailed;
+ // Process pending operations to process any required callbacks.
+ IssuePendingOperations();
+ return;
+ }
+
+ backend_ = std::move(backend_ptr->data);
+ backend_state_ = kInitialized;
+ IssuePendingOperations();
+}
+
+void GeneratedCodeCache::IssuePendingOperations() {
+ DCHECK_EQ(backend_state_, kInitialized);
+ // Issue all the pending operations that were received when creating
+ // the backend.
+ for (auto const& op : pending_ops_) {
+ switch (op->operation()) {
+ case kFetch:
+ FetchEntryImpl(op->key(), op->callback());
+ break;
+ case kWrite:
+ WriteDataImpl(op->key(), op->data());
+ break;
+ case kDelete:
+ DeleteEntryImpl(op->key());
+ break;
+ }
+ }
+ pending_ops_.clear();
+}
+
+void GeneratedCodeCache::WriteDataImpl(
+ const std::string& key,
+ scoped_refptr<net::IOBufferWithSize> buffer) {
+ if (backend_state_ != kInitialized)
+ return;
+
+ scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry_ptr =
+ new base::RefCountedData<disk_cache::Entry*>();
+ net::CompletionOnceCallback callback =
+ base::BindOnce(&GeneratedCodeCache::OpenCompleteForWriteData,
+ weak_ptr_factory_.GetWeakPtr(), buffer, key, entry_ptr);
+
+ int result =
+ backend_->OpenEntry(key, net::LOW, &entry_ptr->data, std::move(callback));
+ if (result != net::ERR_IO_PENDING) {
+ OpenCompleteForWriteData(buffer, key, entry_ptr, result);
+ }
+}
+
+void GeneratedCodeCache::OpenCompleteForWriteData(
+ scoped_refptr<net::IOBufferWithSize> buffer,
+ const std::string& key,
+ scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
+ int rv) {
+ if (rv != net::OK) {
+ net::CompletionOnceCallback callback =
+ base::BindOnce(&GeneratedCodeCache::CreateCompleteForWriteData,
+ weak_ptr_factory_.GetWeakPtr(), buffer, entry);
+
+ int result =
+ backend_->CreateEntry(key, net::LOW, &entry->data, std::move(callback));
+ if (result != net::ERR_IO_PENDING) {
+ CreateCompleteForWriteData(buffer, entry, result);
+ }
+ return;
+ }
+
+ DCHECK(entry->data);
+ disk_cache::ScopedEntryPtr disk_entry(entry->data);
+
+ // This call will truncate the data. This is safe to do since we read the
+ // entire data at the same time currently. If we want to read in parts we have
+ // to doom the entry first.
+ disk_entry->WriteData(kDataIndex, 0, buffer.get(), buffer->size(),
+ net::CompletionOnceCallback(), true);
+}
+
+void GeneratedCodeCache::CreateCompleteForWriteData(
+ scoped_refptr<net::IOBufferWithSize> buffer,
+ scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
+ int rv) {
+ if (rv != net::OK)
+ return;
+
+ DCHECK(entry->data);
+ disk_cache::ScopedEntryPtr disk_entry(entry->data);
+ disk_entry->WriteData(kDataIndex, 0, buffer.get(), buffer->size(),
+ net::CompletionOnceCallback(), true);
+}
+
+void GeneratedCodeCache::FetchEntryImpl(const std::string& key,
+ ReadDataCallback read_data_callback) {
+ if (backend_state_ != kInitialized) {
+ std::move(read_data_callback).Run(scoped_refptr<net::IOBufferWithSize>());
+ return;
+ }
+
+ scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry_ptr =
+ new base::RefCountedData<disk_cache::Entry*>();
+
+ net::CompletionOnceCallback callback = base::BindOnce(
+ &GeneratedCodeCache::OpenCompleteForReadData,
+ weak_ptr_factory_.GetWeakPtr(), read_data_callback, entry_ptr);
+
+ // This is a part of loading cycle and hence should run with a high priority.
+ int result = backend_->OpenEntry(key, net::HIGHEST, &entry_ptr->data,
+ std::move(callback));
+ if (result != net::ERR_IO_PENDING) {
+ OpenCompleteForReadData(read_data_callback, entry_ptr, result);
+ }
+}
+
+void GeneratedCodeCache::OpenCompleteForReadData(
+ ReadDataCallback read_data_callback,
+ scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
+ int rv) {
+ if (rv != net::OK) {
+ std::move(read_data_callback).Run(scoped_refptr<net::IOBufferWithSize>());
+ return;
+ }
+
+ // There should be a valid entry if the open was successful.
+ DCHECK(entry->data);
+
+ disk_cache::ScopedEntryPtr disk_entry(entry->data);
+ int size = disk_entry->GetDataSize(kDataIndex);
+ scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(size));
+ net::CompletionOnceCallback callback = base::BindOnce(
+ &GeneratedCodeCache::ReadDataComplete, weak_ptr_factory_.GetWeakPtr(),
+ read_data_callback, buffer);
+ int result = disk_entry->ReadData(kDataIndex, 0, buffer.get(), size,
+ std::move(callback));
+ if (result != net::ERR_IO_PENDING) {
+ ReadDataComplete(read_data_callback, buffer, result);
+ }
+}
+
+void GeneratedCodeCache::ReadDataComplete(
+ ReadDataCallback callback,
+ scoped_refptr<net::IOBufferWithSize> buffer,
+ int rv) {
+ if (rv != buffer->size()) {
+ std::move(callback).Run(scoped_refptr<net::IOBufferWithSize>());
+ } else {
+ std::move(callback).Run(buffer);
+ }
+}
+
+void GeneratedCodeCache::DeleteEntryImpl(const std::string& key) {
+ if (backend_state_ != kInitialized)
+ return;
+
+ backend_->DoomEntry(key, net::LOWEST, net::CompletionOnceCallback());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/code_cache/generated_code_cache.h b/chromium/content/browser/code_cache/generated_code_cache.h
new file mode 100644
index 00000000000..57e92b76946
--- /dev/null
+++ b/chromium/content/browser/code_cache/generated_code_cache.h
@@ -0,0 +1,125 @@
+// Copyright 2018 The Chromium Authors. All 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_CODE_CACHE_GENERATED_CODE_CACHE_H_
+#define CONTENT_BROWSER_CODE_CACHE_GENERATED_CODE_CACHE_H_
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "net/base/io_buffer.h"
+#include "net/disk_cache/disk_cache.h"
+#include "url/origin.h"
+
+namespace content {
+
+// Cache for storing generated code from the renderer on the disk.
+// This cache is keyed on two keys: |resource_url| and |requesting_origin|.
+// The |resource_url| is the url of the resource that was requested and the
+// |requesting_origin| is the origin that requested this resource. This origin
+// is used to enforce site isolation policy on stored code. We don't cache the
+// code corresponding to unique origins or invalid URLs.
+//
+// This uses a simple disk_cache backend. It just stores one data stream and
+// stores response_time + generated code as one data blob.
+// TODO(mythria): Update this comment if the design changes.
+//
+// There exists one cache per storage partition and is owned by the storage
+// partition. This cache is created, accessed and destroyed on the I/O thread.
+class CONTENT_EXPORT GeneratedCodeCache {
+ public:
+ using ReadDataCallback =
+ base::RepeatingCallback<void(scoped_refptr<net::IOBufferWithSize>)>;
+
+ // Creates a GeneratedCodeCache with the specified path and the maximum size.
+ static std::unique_ptr<GeneratedCodeCache> Create(const base::FilePath& path,
+ int max_size);
+
+ ~GeneratedCodeCache();
+
+ // Writes data to the cache. If there is an entry corresponding to
+ // <|url|, |origin|> this overwrites the existing data. If there is no entry
+ // it creates a new one.
+ void WriteData(const GURL& url,
+ const url::Origin& origin,
+ scoped_refptr<net::IOBufferWithSize>);
+
+ // Fetch entry corresponding to <url, origin> from the cache and pass
+ // it using the ReadDataCallback.
+ void FetchEntry(const GURL& url, const url::Origin& origin, ReadDataCallback);
+
+ // Delete the entry corresponding to <url, origin>
+ void DeleteEntry(const GURL& url, const url::Origin& origin);
+
+ const base::FilePath& path() const { return path_; }
+
+ private:
+ class PendingOperation;
+ using ScopedBackendPtr = std::unique_ptr<disk_cache::Backend>;
+
+ // State of the backend.
+ enum BackendState { kUnInitialized, kInitializing, kInitialized, kFailed };
+
+ // The operation requested.
+ enum Operation { kFetch, kWrite, kDelete };
+
+ // Data streams corresponding to each entry.
+ enum { kDataIndex = 1 };
+
+ GeneratedCodeCache(const base::FilePath& path, int max_size_bytes);
+
+ // Creates a simple_disk_cache backend.
+ void CreateBackend();
+ void DidCreateBackend(
+ scoped_refptr<base::RefCountedData<ScopedBackendPtr>> backend_ptr,
+ int rv);
+
+ // The requests that are received while tha backend is being initialized
+ // are recorded in pending operations list. This function issues all pending
+ // operations.
+ void IssuePendingOperations();
+
+ // Write entry to cache
+ void WriteDataImpl(const std::string& key,
+ scoped_refptr<net::IOBufferWithSize> buffer);
+ void OpenCompleteForWriteData(
+ scoped_refptr<net::IOBufferWithSize> buffer,
+ const std::string& key,
+ scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
+ int rv);
+ void CreateCompleteForWriteData(
+ scoped_refptr<net::IOBufferWithSize> buffer,
+ scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
+ int rv);
+
+ // Fetch entry from cache
+ void FetchEntryImpl(const std::string& key, ReadDataCallback);
+ void OpenCompleteForReadData(
+ ReadDataCallback callback,
+ scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
+ int rv);
+ void ReadDataComplete(ReadDataCallback callback,
+ scoped_refptr<net::IOBufferWithSize> buffer,
+ int rv);
+
+ // Delete entry from cache
+ void DeleteEntryImpl(const std::string& key);
+
+ std::unique_ptr<disk_cache::Backend> backend_;
+ BackendState backend_state_;
+
+ std::vector<std::unique_ptr<PendingOperation>> pending_ops_;
+
+ base::FilePath path_;
+ int max_size_bytes_;
+
+ base::WeakPtrFactory<GeneratedCodeCache> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeneratedCodeCache);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_CODE_CACHE_GENERATED_CODE_CACHE_H_
diff --git a/chromium/content/browser/code_cache/generated_code_cache_unittest.cc b/chromium/content/browser/code_cache/generated_code_cache_unittest.cc
new file mode 100644
index 00000000000..45ea2246f85
--- /dev/null
+++ b/chromium/content/browser/code_cache/generated_code_cache_unittest.cc
@@ -0,0 +1,293 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/code_cache/generated_code_cache.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/test/scoped_task_environment.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+
+class GeneratedCodeCacheTest : public testing::Test {
+ public:
+ static const int kMaxSizeInBytes = 1024 * 1024;
+ static constexpr char kInitialUrl[] = "http://example.com/script.js";
+ static constexpr char kInitialOrigin[] = "http://example.com";
+ static constexpr char kInitialData[] = "InitialData";
+
+ GeneratedCodeCacheTest() = default;
+
+ void SetUp() override {
+ ASSERT_TRUE(cache_dir_.CreateUniqueTempDir());
+ cache_path_ = cache_dir_.GetPath();
+ generated_code_cache_ =
+ GeneratedCodeCache::Create(cache_path_, kMaxSizeInBytes);
+ }
+
+ void TearDown() override {
+ disk_cache::FlushCacheThreadForTesting();
+ scoped_task_environment_.RunUntilIdle();
+ }
+
+ // This function initializes the cache and waits till the transaction is
+ // finished. When this function returns, the backend is already initialized.
+ void InitializeCache() {
+ GURL url(kInitialUrl);
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+ WriteToCache(url, origin, kInitialData);
+ scoped_task_environment_.RunUntilIdle();
+ }
+
+ // This function initializes the cache and reopens it. When this function
+ // returns, the backend initialization is not complete yet. This is used
+ // to test the pending operaions path.
+ void InitializeCacheAndReOpen() {
+ InitializeCache();
+ generated_code_cache_.reset();
+ generated_code_cache_ =
+ GeneratedCodeCache::Create(cache_path_, kMaxSizeInBytes);
+ }
+
+ void WriteToCache(const GURL& url,
+ const url::Origin& origin,
+ const std::string& data) {
+ scoped_refptr<net::IOBufferWithSize> buffer(
+ new net::IOBufferWithSize(data.length()));
+ memcpy(buffer->data(), data.c_str(), data.length());
+ generated_code_cache_->WriteData(url, origin, buffer);
+ }
+
+ void DeleteFromCache(const GURL& url, const url::Origin& origin) {
+ generated_code_cache_->DeleteEntry(url, origin);
+ }
+
+ void FetchFromCache(const GURL& url, const url::Origin& origin) {
+ received_ = false;
+ GeneratedCodeCache::ReadDataCallback callback = base::BindRepeating(
+ &GeneratedCodeCacheTest::FetchEntryCallback, base::Unretained(this));
+ generated_code_cache_->FetchEntry(url, origin, callback);
+ }
+
+ void FetchEntryCallback(scoped_refptr<net::IOBufferWithSize> buffer) {
+ if (!buffer || !buffer->data()) {
+ received_ = true;
+ received_null_ = true;
+ return;
+ }
+ std::string str(buffer->data(), buffer->size());
+ received_ = true;
+ received_null_ = false;
+ received_data_ = str;
+ }
+
+ protected:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ std::unique_ptr<GeneratedCodeCache> generated_code_cache_;
+ base::ScopedTempDir cache_dir_;
+ std::string received_data_;
+ bool received_;
+ bool received_null_;
+ base::FilePath cache_path_;
+};
+
+constexpr char GeneratedCodeCacheTest::kInitialUrl[];
+constexpr char GeneratedCodeCacheTest::kInitialOrigin[];
+constexpr char GeneratedCodeCacheTest::kInitialData[];
+
+TEST_F(GeneratedCodeCacheTest, FetchEntry) {
+ GURL url(kInitialUrl);
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+ InitializeCache();
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ EXPECT_EQ(kInitialData, received_data_);
+}
+
+TEST_F(GeneratedCodeCacheTest, WriteEntry) {
+ GURL new_url("http://example1.com/script.js");
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+ InitializeCache();
+ std::string data = "SerializedCodeForScript";
+ WriteToCache(new_url, origin, data);
+ FetchFromCache(new_url, origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ EXPECT_EQ(data, received_data_);
+}
+
+TEST_F(GeneratedCodeCacheTest, DeleteEntry) {
+ GURL url(kInitialUrl);
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+ InitializeCache();
+ DeleteFromCache(url, origin);
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ ASSERT_TRUE(received_null_);
+}
+
+TEST_F(GeneratedCodeCacheTest, FetchEntryPendingOp) {
+ GURL url(kInitialUrl);
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+ InitializeCacheAndReOpen();
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ EXPECT_EQ(kInitialData, received_data_);
+}
+
+TEST_F(GeneratedCodeCacheTest, WriteEntryPendingOp) {
+ GURL new_url("http://example1.com/script1.js");
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+ InitializeCache();
+ std::string data = "SerializedCodeForScript";
+ WriteToCache(new_url, origin, data);
+ scoped_task_environment_.RunUntilIdle();
+ FetchFromCache(new_url, origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ EXPECT_EQ(data, received_data_);
+}
+
+TEST_F(GeneratedCodeCacheTest, DeleteEntryPendingOp) {
+ GURL url(kInitialUrl);
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+ InitializeCacheAndReOpen();
+ DeleteFromCache(url, origin);
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ ASSERT_TRUE(received_null_);
+}
+
+TEST_F(GeneratedCodeCacheTest, UpdateDataOfExistingEntry) {
+ GURL url(kInitialUrl);
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+ InitializeCache();
+ std::string new_data = "SerializedCodeForScriptOverwrite";
+ WriteToCache(url, origin, new_data);
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ EXPECT_EQ(new_data, received_data_);
+}
+
+TEST_F(GeneratedCodeCacheTest, FetchFailsForNonexistingOrigin) {
+ InitializeCache();
+ url::Origin new_origin = url::Origin::Create(GURL("http://not-example.com"));
+ FetchFromCache(GURL(kInitialUrl), new_origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ ASSERT_TRUE(received_null_);
+}
+
+TEST_F(GeneratedCodeCacheTest, FetchEntriesFromSameOrigin) {
+ GURL url("http://example.com/script.js");
+ GURL second_url("http://script.com/one.js");
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+ std::string data_first_resource = "SerializedCodeForFirstResource";
+ WriteToCache(url, origin, data_first_resource);
+
+ std::string data_second_resource = "SerializedCodeForSecondResource";
+ WriteToCache(second_url, origin, data_second_resource);
+ scoped_task_environment_.RunUntilIdle();
+
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+ ASSERT_TRUE(received_);
+ EXPECT_EQ(data_first_resource, received_data_);
+
+ FetchFromCache(second_url, origin);
+ scoped_task_environment_.RunUntilIdle();
+ ASSERT_TRUE(received_);
+ EXPECT_EQ(data_second_resource, received_data_);
+}
+
+TEST_F(GeneratedCodeCacheTest, FetchSucceedsFromDifferentOrigins) {
+ GURL url("http://example.com/script.js");
+ url::Origin origin = url::Origin::Create(GURL("http://example.com"));
+ url::Origin origin1 = url::Origin::Create(GURL("http://example1.com"));
+
+ std::string data_origin = "SerializedCodeForFirstOrigin";
+ WriteToCache(url, origin, data_origin);
+
+ std::string data_origin1 = "SerializedCodeForSecondOrigin";
+ WriteToCache(url, origin1, data_origin1);
+ scoped_task_environment_.RunUntilIdle();
+
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+ ASSERT_TRUE(received_);
+ EXPECT_EQ(data_origin, received_data_);
+
+ FetchFromCache(url, origin1);
+ scoped_task_environment_.RunUntilIdle();
+ ASSERT_TRUE(received_);
+ EXPECT_EQ(data_origin1, received_data_);
+}
+
+TEST_F(GeneratedCodeCacheTest, FetchFailsForUniqueOrigin) {
+ GURL url("http://example.com/script.js");
+ url::Origin origin =
+ url::Origin::Create(GURL("data:text/html,<script></script>"));
+
+ std::string data = "SerializedCodeForUniqueOrigin";
+ WriteToCache(url, origin, data);
+ scoped_task_environment_.RunUntilIdle();
+
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+ ASSERT_TRUE(received_);
+ ASSERT_TRUE(received_null_);
+}
+
+TEST_F(GeneratedCodeCacheTest, FetchFailsForInvalidOrigin) {
+ GURL url("http://example.com/script.js");
+ url::Origin origin = url::Origin::Create(GURL("invalidURL"));
+
+ std::string data = "SerializedCodeForInvalidOrigin";
+ WriteToCache(url, origin, data);
+ scoped_task_environment_.RunUntilIdle();
+
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+ ASSERT_TRUE(received_);
+ ASSERT_TRUE(received_null_);
+}
+
+TEST_F(GeneratedCodeCacheTest, FetchFailsForInvalidURL) {
+ GURL url("InvalidURL");
+ url::Origin origin = url::Origin::Create(GURL("http://example.com"));
+
+ std::string data = "SerializedCodeForInvalidURL";
+ WriteToCache(url, origin, data);
+ scoped_task_environment_.RunUntilIdle();
+
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+ ASSERT_TRUE(received_);
+ ASSERT_TRUE(received_null_);
+}
+} // namespace content
diff --git a/chromium/content/browser/compositor/external_begin_frame_controller_client_impl.cc b/chromium/content/browser/compositor/external_begin_frame_controller_client_impl.cc
deleted file mode 100644
index 13583a06d26..00000000000
--- a/chromium/content/browser/compositor/external_begin_frame_controller_client_impl.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/compositor/external_begin_frame_controller_client_impl.h"
-
-#include "ui/compositor/compositor.h"
-
-namespace content {
-
-ExternalBeginFrameControllerClientImpl::ExternalBeginFrameControllerClientImpl(
- ui::Compositor* compositor)
- : compositor_(compositor), binding_(this) {}
-
-ExternalBeginFrameControllerClientImpl::
- ~ExternalBeginFrameControllerClientImpl() = default;
-
-viz::mojom::ExternalBeginFrameControllerClientPtr
-ExternalBeginFrameControllerClientImpl::GetBoundPtr() {
- viz::mojom::ExternalBeginFrameControllerClientPtr ptr;
- binding_.Bind(mojo::MakeRequest(&ptr));
- return ptr;
-}
-
-viz::mojom::ExternalBeginFrameControllerAssociatedRequest
-ExternalBeginFrameControllerClientImpl::GetControllerRequest() {
- return mojo::MakeRequest(&controller_);
-}
-
-viz::mojom::ExternalBeginFrameControllerAssociatedPtr&
-ExternalBeginFrameControllerClientImpl::GetController() {
- return controller_;
-}
-
-void ExternalBeginFrameControllerClientImpl::OnNeedsBeginFrames(
- bool needs_begin_frames) {
- compositor_->OnNeedsExternalBeginFrames(needs_begin_frames);
-}
-
-void ExternalBeginFrameControllerClientImpl::OnDisplayDidFinishFrame(
- const viz::BeginFrameAck& ack) {
- compositor_->OnDisplayDidFinishFrame(ack);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/compositor/external_begin_frame_controller_client_impl.h b/chromium/content/browser/compositor/external_begin_frame_controller_client_impl.h
deleted file mode 100644
index 9ecd0ae4882..00000000000
--- a/chromium/content/browser/compositor/external_begin_frame_controller_client_impl.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_COMPOSITOR_EXTERNAL_BEGIN_FRAME_CONTROLLER_CLIENT_IMPL_H_
-#define CONTENT_BROWSER_COMPOSITOR_EXTERNAL_BEGIN_FRAME_CONTROLLER_CLIENT_IMPL_H_
-
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/external_begin_frame_controller.mojom.h"
-
-namespace ui {
-class Compositor;
-} // namespace ui
-
-namespace content {
-
-// ExternalBeginFrameControllerClient implementation that notifies a
-// ui::Compositor about BeginFrame events.
-class ExternalBeginFrameControllerClientImpl
- : public viz::mojom::ExternalBeginFrameControllerClient {
- public:
- explicit ExternalBeginFrameControllerClientImpl(ui::Compositor* compositor);
- ~ExternalBeginFrameControllerClientImpl() override;
-
- viz::mojom::ExternalBeginFrameControllerClientPtr GetBoundPtr();
-
- viz::mojom::ExternalBeginFrameControllerAssociatedRequest
- GetControllerRequest();
-
- viz::mojom::ExternalBeginFrameControllerAssociatedPtr& GetController();
-
- private:
- // viz::ExternalBeginFrameControllerClient implementation.
- void OnNeedsBeginFrames(bool needs_begin_frames) override;
- void OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack) override;
-
- ui::Compositor* compositor_;
-
- mojo::Binding<viz::mojom::ExternalBeginFrameControllerClient> binding_;
- viz::mojom::ExternalBeginFrameControllerAssociatedPtr controller_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_COMPOSITOR_GPU_PROCESS_TRANSPORT_FACTORY_H_
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 34fbb3a9521..15226b0f4d7 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -38,19 +38,16 @@ GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
}
capabilities_.supports_stencil =
context_provider()->ContextCapabilities().num_stencil_bits > 0;
+ // Since one of the buffers is used by the surface for presentation, there can
+ // be at most |num_surface_buffers - 1| pending buffers that the compositor
+ // can use.
+ capabilities_.max_frames_pending =
+ context_provider()->ContextCapabilities().num_surface_buffers - 1;
}
GpuBrowserCompositorOutputSurface::~GpuBrowserCompositorOutputSurface() =
default;
-void GpuBrowserCompositorOutputSurface::SetNeedsVSync(bool needs_vsync) {
-#if defined(OS_WIN)
- GetCommandBufferProxy()->SetNeedsVSync(needs_vsync);
-#else
- NOTREACHED();
-#endif // defined(OS_WIN)
-}
-
void GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
std::vector<ui::LatencyInfo> latency_info,
const gpu::SwapBuffersCompleteParams& params) {
@@ -60,7 +57,6 @@ void GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
client_->DidReceiveTextureInUseResponses(params.texture_in_use_responses);
client_->DidReceiveSwapBuffersAck();
UpdateLatencyInfoOnSwap(params.swap_response, &latency_info);
- RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info);
latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
}
@@ -110,9 +106,6 @@ void GpuBrowserCompositorOutputSurface::Reshape(
void GpuBrowserCompositorOutputSurface::SwapBuffers(
viz::OutputSurfaceFrame frame) {
- if (LatencyInfoHasSnapshotRequest(frame.latency_info))
- GetCommandBufferProxy()->SetSnapshotRequested();
-
gfx::Size surface_size = frame.size;
if (reflector_) {
if (frame.sub_buffer_rect && reflector_texture_defined_) {
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 1ec2b3e3fdf..67ef5d40f1c 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
@@ -10,7 +10,6 @@
#include "base/macros.h"
#include "build/build_config.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
-#include "content/browser/compositor/gpu_vsync_begin_frame_source.h"
#include "gpu/vulkan/buildflags.h"
#include "ui/gfx/swap_result.h"
#include "ui/latency/latency_tracker.h"
@@ -38,8 +37,8 @@ class ReflectorTexture;
// Adapts a WebGraphicsContext3DCommandBufferImpl into a
// viz::OutputSurface that also handles vsync parameter updates
// arriving from the GPU process.
-class GpuBrowserCompositorOutputSurface : public BrowserCompositorOutputSurface,
- public GpuVSyncControl {
+class GpuBrowserCompositorOutputSurface
+ : public BrowserCompositorOutputSurface {
public:
GpuBrowserCompositorOutputSurface(
scoped_refptr<ui::ContextProviderCommandBuffer> context,
@@ -76,8 +75,6 @@ class GpuBrowserCompositorOutputSurface : public BrowserCompositorOutputSurface,
void SetDrawRectangle(const gfx::Rect& rect) override;
- // GpuVSyncControl implementation.
- void SetNeedsVSync(bool needs_vsync) override;
#if BUILDFLAG(ENABLE_VULKAN)
gpu::VulkanSurface* GetVulkanSurface() override;
#endif
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.cc b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
index e679dbb02a8..511d805187b 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
@@ -16,6 +16,7 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/simple_thread.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "cc/base/histograms.h"
@@ -27,22 +28,21 @@
#include "components/viz/common/frame_sinks/delay_based_time_source.h"
#include "components/viz/common/gl_helper.h"
#include "components/viz/common/switches.h"
+#include "components/viz/host/host_display_client.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/host/renderer_settings_creation.h"
#include "components/viz/service/display/display.h"
#include "components/viz/service/display/display_scheduler.h"
#include "components/viz/service/display_embedder/compositing_mode_reporter_impl.h"
#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
-#include "components/viz/service/display_embedder/external_begin_frame_controller_impl.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h"
+#include "components/viz/service/frame_sinks/external_begin_frame_source_mojo.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
-#include "content/browser/compositor/external_begin_frame_controller_client_impl.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/in_process_display_client.h"
#include "content/browser/compositor/offscreen_browser_compositor_output_surface.h"
#include "content/browser/compositor/reflector_impl.h"
#include "content/browser/compositor/software_browser_compositor_output_surface.h"
@@ -69,6 +69,7 @@
#include "ui/base/ui_base_switches_util.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_switches.h"
+#include "ui/compositor/host/external_begin_frame_controller_client_impl.h"
#include "ui/compositor/layer.h"
#include "ui/display/display_switches.h"
#include "ui/display/types/display_snapshot.h"
@@ -115,7 +116,7 @@
#if BUILDFLAG(ENABLE_VULKAN)
#include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
#include "content/browser/compositor/vulkan_browser_compositor_output_surface.h"
-#include "gpu/vulkan/init/vulkan_factory.cc"
+#include "gpu/vulkan/init/vulkan_factory.h"
#endif
using viz::ContextProvider;
@@ -127,17 +128,6 @@ namespace {
// from RenderWidgetHostImpl.
constexpr uint32_t kDefaultClientId = 0u;
-bool IsGpuVSyncSignalSupported() {
-#if defined(OS_WIN)
- // TODO(stanisc): http://crbug.com/467617 Limit to Windows 8.1+ for now
- // because of locking issue caused by waiting for VSync on Win7 and Win 8.0.
- return base::win::GetVersion() >= base::win::VERSION_WIN8_1 &&
- base::FeatureList::IsEnabled(features::kD3DVsync);
-#else
- return false;
-#endif // defined(OS_WIN)
-}
-
#if defined(OS_MACOSX)
bool IsCALayersDisabledFromCommandLine() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -160,14 +150,12 @@ namespace content {
struct GpuProcessTransportFactory::PerCompositorData {
gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
BrowserCompositorOutputSurface* display_output_surface = nullptr;
- // Exactly one of |synthetic_begin_frame_source|,
- // |gpu_vsync_begin_frame_source|, and |external_begin_frame_source| is valid
- // at the same time.
+ // Exactly one of |synthetic_begin_frame_source| and
+ // |external_begin_frame_source| is valid at the same time.
std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_begin_frame_source;
- std::unique_ptr<GpuVSyncBeginFrameSource> gpu_vsync_begin_frame_source;
- std::unique_ptr<viz::ExternalBeginFrameControllerImpl>
- external_begin_frame_controller;
- std::unique_ptr<ExternalBeginFrameControllerClientImpl>
+ std::unique_ptr<viz::ExternalBeginFrameSourceMojo>
+ external_begin_frame_source_mojo;
+ std::unique_ptr<ui::ExternalBeginFrameControllerClientImpl>
external_begin_frame_controller_client;
ReflectorImpl* reflector = nullptr;
std::unique_ptr<viz::Display> display;
@@ -178,6 +166,7 @@ struct GpuProcessTransportFactory::PerCompositorData {
GpuProcessTransportFactory::GpuProcessTransportFactory(
gpu::GpuChannelEstablishFactory* gpu_channel_factory,
viz::CompositingModeReporterImpl* compositing_mode_reporter,
+ viz::ServerSharedBitmapManager* server_shared_bitmap_manager,
scoped_refptr<base::SingleThreadTaskRunner> resize_task_runner)
: frame_sink_id_allocator_(kDefaultClientId),
renderer_settings_(viz::CreateRendererSettings()),
@@ -185,9 +174,9 @@ GpuProcessTransportFactory::GpuProcessTransportFactory(
task_graph_runner_(new cc::SingleThreadTaskGraphRunner),
gpu_channel_factory_(gpu_channel_factory),
compositing_mode_reporter_(compositing_mode_reporter),
+ server_shared_bitmap_manager_(server_shared_bitmap_manager),
callback_factory_(this) {
DCHECK(gpu_channel_factory_);
- cc::SetClientNameForMetrics("Browser");
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kDisableFrameRateLimit))
@@ -229,7 +218,7 @@ GpuProcessTransportFactory::CreateSoftwareOutputDevice(
return base::WrapUnique(new viz::SoftwareOutputDevice);
#if defined(USE_AURA)
- if (base::FeatureList::IsEnabled(features::kMash)) {
+ if (!features::IsAshInBrowserProcess()) {
NOTREACHED();
return nullptr;
}
@@ -412,7 +401,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
gpu_channel_host, gpu::kNullSurfaceHandle, need_alpha_channel,
false /* support_stencil */, support_locking, support_gles2_interface,
support_raster_interface, support_grcontext,
- ui::command_buffer_metrics::BROWSER_WORKER_CONTEXT);
+ ui::command_buffer_metrics::ContextType::BROWSER_WORKER);
auto result = shared_worker_context_provider_->BindToCurrentThread();
if (result != gpu::ContextResult::kSuccess) {
shared_worker_context_provider_ = nullptr;
@@ -439,7 +428,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
std::move(gpu_channel_host), surface_handle, need_alpha_channel,
support_stencil, support_locking, support_gles2_interface,
support_raster_interface, support_grcontext,
- ui::command_buffer_metrics::DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT);
+ ui::command_buffer_metrics::ContextType::BROWSER_COMPOSITOR);
// On Mac, GpuCommandBufferMsg_SwapBuffersCompleted must be handled in
// a nested run loop during resize.
context_provider->SetDefaultTaskRunner(resize_task_runner_);
@@ -479,8 +468,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
BrowserCompositorOutputSurface::UpdateVSyncParametersCallback vsync_callback =
base::Bind(&ui::Compositor::SetDisplayVSyncParameters, compositor);
- GpuVSyncControl* gpu_vsync_control = nullptr;
-
std::unique_ptr<BrowserCompositorOutputSurface> display_output_surface;
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<VulkanBrowserCompositorOutputSurface> vulkan_surface;
@@ -540,7 +527,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
GL_TEXTURE_2D, GL_BGRA_EXT,
display::DisplaySnapshot::PrimaryFormat(),
GetGpuMemoryBufferManager());
- gpu_vsync_control = gpu_output_surface.get();
display_output_surface = std::move(gpu_output_surface);
#endif
} else {
@@ -556,7 +542,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
std::make_unique<GpuBrowserCompositorOutputSurface>(
context_provider, std::move(vsync_callback),
std::move(validator));
- gpu_vsync_control = gpu_output_surface.get();
display_output_surface = std::move(gpu_output_surface);
}
}
@@ -567,26 +552,25 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
data->reflector->OnSourceSurfaceReady(data->display_output_surface);
std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_begin_frame_source;
- std::unique_ptr<GpuVSyncBeginFrameSource> gpu_vsync_begin_frame_source;
- std::unique_ptr<viz::ExternalBeginFrameControllerImpl>
- external_begin_frame_controller;
- std::unique_ptr<ExternalBeginFrameControllerClientImpl>
+ std::unique_ptr<viz::ExternalBeginFrameSourceMojo>
+ external_begin_frame_source_mojo;
+ std::unique_ptr<ui::ExternalBeginFrameControllerClientImpl>
external_begin_frame_controller_client;
viz::BeginFrameSource* begin_frame_source = nullptr;
if (compositor->external_begin_frames_enabled()) {
external_begin_frame_controller_client =
- std::make_unique<ExternalBeginFrameControllerClientImpl>(
+ std::make_unique<ui::ExternalBeginFrameControllerClientImpl>(
compositor.get());
// We don't bind the controller mojo interface, since we only use the
- // ExternalBeginFrameControllerImpl directly and not via mojo (plus, as it
+ // ExternalBeginFrameSourceMojo directly and not via mojo (plus, as it
// is an associated interface, binding it would require a separate pipe).
viz::mojom::ExternalBeginFrameControllerAssociatedRequest request = nullptr;
- external_begin_frame_controller =
- std::make_unique<viz::ExternalBeginFrameControllerImpl>(
+ external_begin_frame_source_mojo =
+ std::make_unique<viz::ExternalBeginFrameSourceMojo>(
std::move(request),
external_begin_frame_controller_client->GetBoundPtr());
- begin_frame_source = external_begin_frame_controller->begin_frame_source();
+ begin_frame_source = external_begin_frame_source_mojo.get();
} else if (disable_frame_rate_limit_) {
synthetic_begin_frame_source =
std::make_unique<viz::BackToBackBeginFrameSource>(
@@ -594,18 +578,12 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
compositor->task_runner().get()));
begin_frame_source = synthetic_begin_frame_source.get();
} else {
- if (gpu_vsync_control && IsGpuVSyncSignalSupported()) {
- gpu_vsync_begin_frame_source =
- std::make_unique<GpuVSyncBeginFrameSource>(gpu_vsync_control);
- begin_frame_source = gpu_vsync_begin_frame_source.get();
- } else {
synthetic_begin_frame_source =
std::make_unique<viz::DelayBasedBeginFrameSource>(
std::make_unique<viz::DelayBasedTimeSource>(
compositor->task_runner().get()),
viz::BeginFrameSource::kNotRestartableId);
begin_frame_source = synthetic_begin_frame_source.get();
- }
}
#if defined(OS_WIN)
@@ -615,13 +593,10 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
if (data->synthetic_begin_frame_source) {
GetFrameSinkManager()->UnregisterBeginFrameSource(
data->synthetic_begin_frame_source.get());
- } else if (data->gpu_vsync_begin_frame_source) {
- GetFrameSinkManager()->UnregisterBeginFrameSource(
- data->gpu_vsync_begin_frame_source.get());
- } else if (data->external_begin_frame_controller) {
+ } else if (data->external_begin_frame_source_mojo) {
GetFrameSinkManager()->UnregisterBeginFrameSource(
- data->external_begin_frame_controller->begin_frame_source());
- data->external_begin_frame_controller->SetDisplay(nullptr);
+ data->external_begin_frame_source_mojo.get());
+ data->external_begin_frame_source_mojo->SetDisplay(nullptr);
}
auto scheduler = std::make_unique<viz::DisplayScheduler>(
@@ -631,23 +606,22 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
// The Display owns and uses the |display_output_surface| created above.
data->display = std::make_unique<viz::Display>(
- viz::ServerSharedBitmapManager::current(), renderer_settings_,
+ server_shared_bitmap_manager_, renderer_settings_,
compositor->frame_sink_id(), std::move(display_output_surface),
std::move(scheduler), compositor->task_runner());
data->display_client =
- std::make_unique<InProcessDisplayClient>(compositor->widget());
+ std::make_unique<viz::HostDisplayClient>(compositor->widget());
GetFrameSinkManager()->RegisterBeginFrameSource(begin_frame_source,
compositor->frame_sink_id());
// Note that we are careful not to destroy prior BeginFrameSource objects
// until we have reset |data->display|.
data->synthetic_begin_frame_source = std::move(synthetic_begin_frame_source);
- data->gpu_vsync_begin_frame_source = std::move(gpu_vsync_begin_frame_source);
- data->external_begin_frame_controller =
- std::move(external_begin_frame_controller);
+ data->external_begin_frame_source_mojo =
+ std::move(external_begin_frame_source_mojo);
data->external_begin_frame_controller_client =
std::move(external_begin_frame_controller_client);
- if (data->external_begin_frame_controller)
- data->external_begin_frame_controller->SetDisplay(data->display.get());
+ if (data->external_begin_frame_source_mojo)
+ data->external_begin_frame_source_mojo->SetDisplay(data->display.get());
// The |delegated_output_surface| is given back to the compositor, it
// delegates to the Display as its root surface. Importantly, it shares the
@@ -750,13 +724,10 @@ void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
if (data->synthetic_begin_frame_source) {
GetFrameSinkManager()->UnregisterBeginFrameSource(
data->synthetic_begin_frame_source.get());
- } else if (data->gpu_vsync_begin_frame_source) {
- GetFrameSinkManager()->UnregisterBeginFrameSource(
- data->gpu_vsync_begin_frame_source.get());
- } else if (data->external_begin_frame_controller) {
+ } else if (data->external_begin_frame_source_mojo) {
GetFrameSinkManager()->UnregisterBeginFrameSource(
- data->external_begin_frame_controller->begin_frame_source());
- data->external_begin_frame_controller->SetDisplay(nullptr);
+ data->external_begin_frame_source_mojo.get());
+ data->external_begin_frame_source_mojo->SetDisplay(nullptr);
}
per_compositor_data_.erase(it);
if (per_compositor_data_.empty()) {
@@ -770,7 +741,7 @@ void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
// If there are any observer left at this point, make sure they clean up
// before we destroy the GLHelper.
for (auto& observer : observer_list_)
- observer.OnLostResources();
+ observer.OnLostSharedContext();
helper.reset();
DCHECK(!gl_helper_) << "Destroying the GLHelper should not cause a new "
@@ -795,6 +766,11 @@ cc::TaskGraphRunner* GpuProcessTransportFactory::GetTaskGraphRunner() {
return task_graph_runner_.get();
}
+void GpuProcessTransportFactory::DisableGpuCompositing() {
+ if (!is_gpu_compositing_disabled_)
+ DisableGpuCompositing(nullptr);
+}
+
bool GpuProcessTransportFactory::IsGpuCompositingDisabled() {
return is_gpu_compositing_disabled_;
}
@@ -841,6 +817,17 @@ void GpuProcessTransportFactory::ResizeDisplay(ui::Compositor* compositor,
data->display->Resize(size);
}
+void GpuProcessTransportFactory::DisableSwapUntilResize(
+ ui::Compositor* compositor) {
+ PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ if (it == per_compositor_data_.end())
+ return;
+ PerCompositorData* data = it->second.get();
+ DCHECK(data);
+ if (data->display)
+ data->display->Resize(gfx::Size());
+}
+
void GpuProcessTransportFactory::SetDisplayColorMatrix(
ui::Compositor* compositor,
const SkMatrix44& matrix) {
@@ -893,8 +880,6 @@ void GpuProcessTransportFactory::SetDisplayVSyncParameters(
if (data->synthetic_begin_frame_source) {
data->synthetic_begin_frame_source->OnUpdateVSyncParameters(timebase,
interval);
- } else if (data->gpu_vsync_begin_frame_source) {
- data->gpu_vsync_begin_frame_source->OnVSync(timebase, interval);
}
}
@@ -906,8 +891,8 @@ void GpuProcessTransportFactory::IssueExternalBeginFrame(
return;
PerCompositorData* data = it->second.get();
DCHECK(data);
- DCHECK(data->external_begin_frame_controller);
- data->external_begin_frame_controller->IssueExternalBeginFrame(args);
+ DCHECK(data->external_begin_frame_source_mojo);
+ data->external_begin_frame_source_mojo->IssueExternalBeginFrame(args);
}
void GpuProcessTransportFactory::SetOutputIsSecure(ui::Compositor* compositor,
@@ -932,6 +917,12 @@ void GpuProcessTransportFactory::RemoveObserver(
observer_list_.RemoveObserver(observer);
}
+bool GpuProcessTransportFactory::SyncTokensRequiredForDisplayCompositor() {
+ // Display and DirectLayerTreeFrameSink share a GL context, so sync
+ // points aren't needed when passing resources between them.
+ return false;
+}
+
viz::FrameSinkManagerImpl* GpuProcessTransportFactory::GetFrameSinkManager() {
return BrowserMainLoop::GetInstance()->GetFrameSinkManager();
}
@@ -977,7 +968,7 @@ GpuProcessTransportFactory::SharedMainThreadContextProvider() {
std::move(gpu_channel_host), gpu::kNullSurfaceHandle, need_alpha_channel,
false, support_locking, support_gles2_interface, support_raster_interface,
support_grcontext,
- ui::command_buffer_metrics::BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
+ ui::command_buffer_metrics::ContextType::BROWSER_MAIN_THREAD);
shared_main_thread_contexts_->AddObserver(this);
auto result = shared_main_thread_contexts_->BindToCurrentThread();
if (result != gpu::ContextResult::kSuccess) {
@@ -1028,7 +1019,7 @@ void GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
std::unique_ptr<viz::GLHelper> lost_gl_helper = std::move(gl_helper_);
for (auto& observer : observer_list_)
- observer.OnLostResources();
+ observer.OnLostSharedContext();
// Kill things that use the shared context before killing the shared context.
lost_gl_helper.reset();
@@ -1041,6 +1032,7 @@ GpuProcessTransportFactory::SharedVulkanContextProvider() {
if (!shared_vulkan_context_provider_initialized_) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableVulkan)) {
+ base::ScopedAllowBlocking allow_blocking;
vulkan_implementation_ = gpu::CreateVulkanImplementation();
if (vulkan_implementation_ &&
vulkan_implementation_->InitializeVulkanInstance()) {
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.h b/chromium/content/browser/compositor/gpu_process_transport_factory.h
index 02c1ec0d59b..6704fa4bb4c 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.h
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.h
@@ -47,6 +47,7 @@ class ContextProviderCommandBuffer;
namespace viz {
class CompositingModeReporterImpl;
class OutputDeviceBacking;
+class ServerSharedBitmapManager;
class SoftwareOutputDevice;
class VulkanInProcessContextProvider;
class RasterContextProvider;
@@ -62,6 +63,7 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
GpuProcessTransportFactory(
gpu::GpuChannelEstablishFactory* gpu_channel_factory,
viz::CompositingModeReporterImpl* compositing_mode_reporter,
+ viz::ServerSharedBitmapManager* server_shared_bitmap_manager,
scoped_refptr<base::SingleThreadTaskRunner> resize_task_runner);
~GpuProcessTransportFactory() override;
@@ -76,6 +78,7 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
cc::TaskGraphRunner* GetTaskGraphRunner() override;
void AddObserver(ui::ContextFactoryObserver* observer) override;
void RemoveObserver(ui::ContextFactoryObserver* observer) override;
+ bool SyncTokensRequiredForDisplayCompositor() override;
// ui::ContextFactoryPrivate implementation.
std::unique_ptr<ui::Reflector> CreateReflector(ui::Compositor* source,
@@ -87,6 +90,7 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
void SetDisplayVisible(ui::Compositor* compositor, bool visible) override;
void ResizeDisplay(ui::Compositor* compositor,
const gfx::Size& size) override;
+ void DisableSwapUntilResize(ui::Compositor* compositor) override;
void SetDisplayColorMatrix(ui::Compositor* compositor,
const SkMatrix44& matrix) override;
void SetDisplayColorSpace(ui::Compositor* compositor,
@@ -102,6 +106,7 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override;
// ImageTransportFactory implementation.
+ void DisableGpuCompositing() override;
bool IsGpuCompositingDisabled() override;
ui::ContextFactory* GetContextFactory() override;
ui::ContextFactoryPrivate* GetContextFactoryPrivate() override;
@@ -180,6 +185,8 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
// Service-side impl that controls the compositing mode based on what mode the
// display compositors are using.
viz::CompositingModeReporterImpl* const compositing_mode_reporter_;
+ // Manages a mapping of SharedBitmapId to shared memory objects.
+ viz::ServerSharedBitmapManager* const server_shared_bitmap_manager_;
base::WeakPtrFactory<GpuProcessTransportFactory> callback_factory_;
diff --git a/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.cc b/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.cc
deleted file mode 100644
index d46b8337f35..00000000000
--- a/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.cc
+++ /dev/null
@@ -1,87 +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/compositor/gpu_vsync_begin_frame_source.h"
-
-namespace content {
-
-GpuVSyncBeginFrameSource::GpuVSyncBeginFrameSource(
- GpuVSyncControl* vsync_control)
- : viz::ExternalBeginFrameSource(this),
- vsync_control_(vsync_control),
- needs_begin_frames_(false),
- next_sequence_number_(viz::BeginFrameArgs::kStartingFrameNumber) {
- DCHECK(vsync_control);
-}
-
-GpuVSyncBeginFrameSource::~GpuVSyncBeginFrameSource() = default;
-
-void GpuVSyncBeginFrameSource::OnVSync(base::TimeTicks timestamp,
- base::TimeDelta interval) {
- if (!needs_begin_frames_)
- return;
-
- base::TimeTicks now = Now();
- base::TimeTicks deadline = now.SnappedToNextTick(timestamp, interval);
-
- TRACE_EVENT1("cc", "GpuVSyncBeginFrameSource::OnVSync", "latency",
- (now - timestamp).ToInternalValue());
-
- // Fast forward timestamp to avoid generating BeginFrame with a timestamp
- // that is too far behind. Most of the time it would remain the same.
- timestamp = deadline - interval;
-
- next_sequence_number_++;
-
- // OnBeginFrame can still skip this notification if it is behind
- // last_begin_frame_args_.
- OnBeginFrame(viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, source_id(), next_sequence_number_, timestamp,
- deadline, interval, viz::BeginFrameArgs::NORMAL));
-}
-
-void GpuVSyncBeginFrameSource::OnNeedsBeginFrames(bool needs_begin_frames) {
- needs_begin_frames_ = needs_begin_frames;
- vsync_control_->SetNeedsVSync(needs_begin_frames);
-}
-
-base::TimeTicks GpuVSyncBeginFrameSource::Now() const {
- return base::TimeTicks::Now();
-}
-
-viz::BeginFrameArgs GpuVSyncBeginFrameSource::GetMissedBeginFrameArgs(
- viz::BeginFrameObserver* obs) {
- if (!last_begin_frame_args_.IsValid())
- return viz::BeginFrameArgs();
-
- base::TimeTicks now = Now();
- base::TimeTicks estimated_next_timestamp = now.SnappedToNextTick(
- last_begin_frame_args_.frame_time, last_begin_frame_args_.interval);
- base::TimeTicks missed_timestamp =
- estimated_next_timestamp - last_begin_frame_args_.interval;
-
- if (missed_timestamp > last_begin_frame_args_.frame_time) {
- // The projected missed timestamp is newer than the last known timestamp.
- // In this case create BeginFrameArgs with a new sequence number.
- next_sequence_number_++;
- last_begin_frame_args_ = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, source_id(), next_sequence_number_,
- missed_timestamp, estimated_next_timestamp,
- last_begin_frame_args_.interval, viz::BeginFrameArgs::NORMAL);
- }
-
- // The last known args object is up-to-date. Skip sending notification
- // if the observer has already seen it.
- const viz::BeginFrameArgs& last_observer_args = obs->LastUsedBeginFrameArgs();
- if (last_observer_args.IsValid() &&
- last_begin_frame_args_.frame_time <= last_observer_args.frame_time) {
- return viz::BeginFrameArgs();
- }
-
- viz::BeginFrameArgs missed_args = last_begin_frame_args_;
- missed_args.type = viz::BeginFrameArgs::MISSED;
- return missed_args;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.h b/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.h
deleted file mode 100644
index 251b69263a6..00000000000
--- a/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.h
+++ /dev/null
@@ -1,52 +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_COMPOSITOR_GPU_VSYNC_BEGIN_FRAME_SOURCE_H_
-#define CONTENT_BROWSER_COMPOSITOR_GPU_VSYNC_BEGIN_FRAME_SOURCE_H_
-
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "components/viz/common/frame_sinks/begin_frame_source.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// This class is used to control VSync production on GPU side.
-class CONTENT_EXPORT GpuVSyncControl {
- public:
- virtual void SetNeedsVSync(bool needs_vsync) = 0;
-};
-
-// This is a type of ExternalBeginFrameSource where VSync signals are
-// generated externally on GPU side.
-class CONTENT_EXPORT GpuVSyncBeginFrameSource
- : public viz::ExternalBeginFrameSource,
- public viz::ExternalBeginFrameSourceClient {
- public:
- explicit GpuVSyncBeginFrameSource(GpuVSyncControl* vsync_control);
- ~GpuVSyncBeginFrameSource() override;
-
- // viz::ExternalBeginFrameSourceClient implementation.
- void OnNeedsBeginFrames(bool needs_begin_frames) override;
-
- void OnVSync(base::TimeTicks timestamp, base::TimeDelta interval);
-
- protected:
- // Virtual for testing.
- virtual base::TimeTicks Now() const;
-
- private:
- viz::BeginFrameArgs GetMissedBeginFrameArgs(
- viz::BeginFrameObserver* obs) override;
-
- GpuVSyncControl* const vsync_control_;
- bool needs_begin_frames_;
- uint64_t next_sequence_number_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuVSyncBeginFrameSource);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_COMPOSITOR_GPU_VSYNC_BEGIN_FRAME_SOURCE_H_
diff --git a/chromium/content/browser/compositor/gpu_vsync_begin_frame_source_unittest.cc b/chromium/content/browser/compositor/gpu_vsync_begin_frame_source_unittest.cc
deleted file mode 100644
index 7b091fe0b98..00000000000
--- a/chromium/content/browser/compositor/gpu_vsync_begin_frame_source_unittest.cc
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/compositor/gpu_vsync_begin_frame_source.h"
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-namespace {
-
-class TestBeginFrameObserver : public viz::BeginFrameObserverBase {
- public:
- TestBeginFrameObserver() = default;
-
- int begin_frame_count() { return begin_frame_count_; }
-
- private:
- bool OnBeginFrameDerivedImpl(const viz::BeginFrameArgs& args) override {
- begin_frame_count_++;
- return true;
- }
-
- void OnBeginFrameSourcePausedChanged(bool paused) override {}
-
- int begin_frame_count_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(TestBeginFrameObserver);
-};
-
-class TestGpuVSyncBeginFrameSource : public GpuVSyncBeginFrameSource {
- public:
- explicit TestGpuVSyncBeginFrameSource(GpuVSyncControl* vsync_control)
- : GpuVSyncBeginFrameSource(vsync_control) {}
-
- void SetNow(base::TimeTicks now) { now_ = now; }
-
- private:
- base::TimeTicks Now() const override { return now_; }
-
- base::TimeTicks now_;
-
- DISALLOW_COPY_AND_ASSIGN(TestGpuVSyncBeginFrameSource);
-};
-
-class GpuVSyncBeginFrameSourceTest : public testing::Test,
- public GpuVSyncControl {
- public:
- GpuVSyncBeginFrameSourceTest() = default;
- ~GpuVSyncBeginFrameSourceTest() override = default;
-
- protected:
- void SetNeedsVSync(bool needs_vsync) override { needs_vsync_ = needs_vsync; }
-
- bool needs_vsync_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(GpuVSyncBeginFrameSourceTest);
-};
-
-// Test that an observer can be added to BFS and that it receives OnBeginFrame
-// notification.
-TEST_F(GpuVSyncBeginFrameSourceTest, BasicTest) {
- TestBeginFrameObserver observer;
- TestGpuVSyncBeginFrameSource begin_frame_source(this);
-
- base::TimeTicks now = base::TimeTicks() + base::TimeDelta::FromHours(2);
- begin_frame_source.SetNow(now);
-
- EXPECT_FALSE(needs_vsync_);
-
- begin_frame_source.AddObserver(&observer);
-
- EXPECT_TRUE(needs_vsync_);
- EXPECT_FALSE(observer.LastUsedBeginFrameArgs().IsValid());
-
- base::TimeTicks timestamp = now - base::TimeDelta::FromSeconds(1);
- base::TimeDelta interval = base::TimeDelta::FromSeconds(2);
-
- begin_frame_source.OnVSync(timestamp, interval);
-
- EXPECT_EQ(1, observer.begin_frame_count());
-
- viz::BeginFrameArgs args = observer.LastUsedBeginFrameArgs();
- EXPECT_TRUE(args.IsValid());
- EXPECT_EQ(timestamp, args.frame_time);
- EXPECT_EQ(interval, args.interval);
- EXPECT_EQ(timestamp + interval, args.deadline);
- EXPECT_EQ(viz::BeginFrameArgs::kStartingFrameNumber + 1,
- args.sequence_number);
- EXPECT_EQ(viz::BeginFrameArgs::NORMAL, args.type);
- EXPECT_EQ(begin_frame_source.source_id(), args.source_id);
-
- // Make sure that the deadline time is correctly advanced forward to be after
- // 'now' when frame time is way behind.
- now += base::TimeDelta::FromSeconds(10);
- begin_frame_source.SetNow(now);
- // v-sync timestamp is 5 seconds behind but frame time should be projected
- // forward to be 1 second before 'now' and the the deadline should be 1 second
- // after 'now' considering the 2 second interval.
- timestamp = now - base::TimeDelta::FromSeconds(5);
-
- begin_frame_source.OnVSync(timestamp, interval);
-
- EXPECT_EQ(2, observer.begin_frame_count());
-
- args = observer.LastUsedBeginFrameArgs();
- EXPECT_TRUE(args.IsValid());
- EXPECT_EQ(now - base::TimeDelta::FromSeconds(1), args.frame_time);
- EXPECT_EQ(interval, args.interval);
- EXPECT_EQ(now + base::TimeDelta::FromSeconds(1), args.deadline);
- EXPECT_EQ(viz::BeginFrameArgs::kStartingFrameNumber + 2,
- args.sequence_number);
- EXPECT_EQ(viz::BeginFrameArgs::NORMAL, args.type);
- EXPECT_EQ(begin_frame_source.source_id(), args.source_id);
-
- begin_frame_source.RemoveObserver(&observer);
-
- EXPECT_EQ(2, observer.begin_frame_count());
- EXPECT_FALSE(needs_vsync_);
-}
-
-// Test that MISSED OnBeginFrame is produced as expected.
-TEST_F(GpuVSyncBeginFrameSourceTest, MissedBeginFrameArgs) {
- TestBeginFrameObserver observer1;
- TestBeginFrameObserver observer2;
- TestGpuVSyncBeginFrameSource begin_frame_source(this);
-
- base::TimeTicks now = base::TimeTicks() + base::TimeDelta::FromHours(2);
- begin_frame_source.SetNow(now);
-
- begin_frame_source.AddObserver(&observer1);
-
- // The observer shouldn't be getting any BeginFrame at this point.
- EXPECT_EQ(0, observer1.begin_frame_count());
-
- base::TimeDelta interval = base::TimeDelta::FromSeconds(2);
-
- // Trigger first OnBeginFrame.
- begin_frame_source.OnVSync(now, interval);
-
- // The observer should get a NORMAL BeginFrame notification which is covered
- // by BasicTest above.
- EXPECT_EQ(1, observer1.begin_frame_count());
- EXPECT_EQ(viz::BeginFrameArgs::NORMAL,
- observer1.LastUsedBeginFrameArgs().type);
-
- // Remove the first observer and add it back after advancing the 'now' time.
- // It should get a more recent missed notification calculated from the
- // projection of the previous notification.
- begin_frame_source.RemoveObserver(&observer1);
- now = now + base::TimeDelta::FromSeconds(5);
- begin_frame_source.SetNow(now);
- begin_frame_source.AddObserver(&observer1);
-
- EXPECT_EQ(2, observer1.begin_frame_count());
-
- // The projected MISSED frame_time should be 1 second behind 'now'.
- base::TimeTicks timestamp1 = now - base::TimeDelta::FromSeconds(1);
- viz::BeginFrameArgs args1 = observer1.LastUsedBeginFrameArgs();
- EXPECT_TRUE(args1.IsValid());
- EXPECT_EQ(timestamp1, args1.frame_time);
- EXPECT_EQ(timestamp1 + interval, args1.deadline);
- EXPECT_EQ(viz::BeginFrameArgs::kStartingFrameNumber + 2,
- args1.sequence_number);
- EXPECT_EQ(viz::BeginFrameArgs::MISSED, args1.type);
-
- // Add second observer which should receive the same notification.
- begin_frame_source.AddObserver(&observer2);
-
- EXPECT_EQ(1, observer2.begin_frame_count());
-
- viz::BeginFrameArgs args2 = observer2.LastUsedBeginFrameArgs();
- EXPECT_TRUE(args2.IsValid());
- EXPECT_EQ(timestamp1, args2.frame_time);
- EXPECT_EQ(timestamp1 + interval, args2.deadline);
- EXPECT_EQ(viz::BeginFrameArgs::kStartingFrameNumber + 2,
- args2.sequence_number);
- EXPECT_EQ(viz::BeginFrameArgs::MISSED, args2.type);
-
- // Adding and removing the second observer shouldn't produce any
- // new notifications.
- begin_frame_source.RemoveObserver(&observer2);
- begin_frame_source.AddObserver(&observer2);
-
- EXPECT_EQ(1, observer2.begin_frame_count());
-}
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/browser/compositor/image_transport_factory.h b/chromium/content/browser/compositor/image_transport_factory.h
index 0ccaf358643..9dba97fe029 100644
--- a/chromium/content/browser/compositor/image_transport_factory.h
+++ b/chromium/content/browser/compositor/image_transport_factory.h
@@ -38,6 +38,10 @@ class CONTENT_EXPORT ImageTransportFactory {
// Gets the factory instance.
static ImageTransportFactory* GetInstance();
+ // Disable GPU compositing. Will do nothing if GPU compositing is already
+ // disabled.
+ virtual void DisableGpuCompositing() = 0;
+
// Whether gpu compositing is being used or is disabled for software
// compositing. Clients of the compositor should give resources that match
// the appropriate mode.
diff --git a/chromium/content/browser/compositor/image_transport_factory_browsertest.cc b/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
index 8a918a746a9..659533c687d 100644
--- a/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
+++ b/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
@@ -6,58 +6,50 @@
#include "base/run_loop.h"
#include "build/build_config.h"
+#include "components/viz/common/features.h"
#include "components/viz/common/gpu/context_provider.h"
#include "content/browser/compositor/owned_mailbox.h"
#include "content/public/test/content_browser_test.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
-#include "gpu/config/gpu_feature_info.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/compositor/compositor.h"
namespace content {
namespace {
-typedef ContentBrowserTest ImageTransportFactoryBrowserTest;
+using ImageTransportFactoryBrowserTest = ContentBrowserTest;
class MockContextFactoryObserver : public ui::ContextFactoryObserver {
public:
- MOCK_METHOD0(OnLostResources, void());
+ MOCK_METHOD0(OnLostSharedContext, void());
+ MOCK_METHOD0(OnLostVizProcess, void());
};
-// This crashes on Mac ASAN: http://crbug.com/335083
// Flaky on ChromeOS: crbug.com/394083
-#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS)
#define MAYBE_TestLostContext DISABLED_TestLostContext
#else
#define MAYBE_TestLostContext TestLostContext
#endif
-// Checks that upon context loss, the observer is called and the created
-// resources are reset.
+// Checks that upon context loss the observer is notified.
IN_PROC_BROWSER_TEST_F(ImageTransportFactoryBrowserTest,
MAYBE_TestLostContext) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
// This test doesn't make sense in software compositing mode.
- scoped_refptr<viz::ContextProvider> context_provider =
- factory->GetContextFactory()->SharedMainThreadContextProvider();
- if (context_provider->GetGpuFeatureInfo()
- .status_values[gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING] !=
- gpu::kGpuFeatureStatusEnabled) {
+ if (factory->IsGpuCompositingDisabled())
return;
- }
-
- scoped_refptr<OwnedMailbox> mailbox =
- new OwnedMailbox(factory->GetGLHelper());
- EXPECT_FALSE(mailbox->mailbox().IsZero());
MockContextFactoryObserver observer;
factory->GetContextFactory()->AddObserver(&observer);
base::RunLoop run_loop;
- EXPECT_CALL(observer, OnLostResources())
- .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+ EXPECT_CALL(observer, OnLostSharedContext())
+ .WillOnce(testing::Invoke(&run_loop, &base::RunLoop::Quit));
+ scoped_refptr<viz::ContextProvider> context_provider =
+ factory->GetContextFactory()->SharedMainThreadContextProvider();
gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
gl->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
GL_INNOCENT_CONTEXT_RESET_ARB);
@@ -67,16 +59,14 @@ IN_PROC_BROWSER_TEST_F(ImageTransportFactoryBrowserTest,
gl->Flush();
run_loop.Run();
- EXPECT_TRUE(mailbox->mailbox().IsZero());
factory->GetContextFactory()->RemoveObserver(&observer);
}
class ImageTransportFactoryTearDownBrowserTest : public ContentBrowserTest {
public:
- ImageTransportFactoryTearDownBrowserTest() {}
-
void TearDown() override {
+ // Mailbox is null if the test exited early.
if (mailbox_.get())
EXPECT_TRUE(mailbox_->mailbox().IsZero());
ContentBrowserTest::TearDown();
@@ -86,34 +76,27 @@ class ImageTransportFactoryTearDownBrowserTest : public ContentBrowserTest {
scoped_refptr<OwnedMailbox> mailbox_;
};
-// This crashes on Mac. ImageTransportFactory is NULL unless
-// --enable-delegated-renderer is passed, and after that, we'd need to spawn a
-// renderer and get a frame before we create a browser compositor, necessary for
-// the GLHelper to not be NULL.
-// http://crbug.com/335083
-#if defined(OS_MACOSX)
-#define MAYBE_LoseOnTearDown DISABLED_LoseOnTearDown
-#else
-#define MAYBE_LoseOnTearDown LoseOnTearDown
-#endif
// Checks that upon destruction of the ImageTransportFactory, the observer is
// called and the created resources are reset.
IN_PROC_BROWSER_TEST_F(ImageTransportFactoryTearDownBrowserTest,
- MAYBE_LoseOnTearDown) {
+ LoseOnTearDown) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+
+ // TODO(crbug.com/844469): Delete after OOP-D is launched because GLHelper
+ // and OwnedMailbox aren't used.
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor))
+ return;
+
// This test doesn't make sense in software compositing mode.
- scoped_refptr<viz::ContextProvider> context_provider =
- factory->GetContextFactory()->SharedMainThreadContextProvider();
- if (context_provider->GetGpuFeatureInfo()
- .status_values[gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING] !=
- gpu::kGpuFeatureStatusEnabled) {
+ if (factory->IsGpuCompositingDisabled())
return;
- }
viz::GLHelper* helper = factory->GetGLHelper();
ASSERT_TRUE(helper);
- mailbox_ = new OwnedMailbox(helper);
+ mailbox_ = base::MakeRefCounted<OwnedMailbox>(helper);
EXPECT_FALSE(mailbox_->mailbox().IsZero());
+
+ // See TearDown() for the test expectation that |mailbox_| has been reset.
}
} // anonymous namespace
diff --git a/chromium/content/browser/compositor/in_process_display_client.cc b/chromium/content/browser/compositor/in_process_display_client.cc
deleted file mode 100644
index 3190c0d90ff..00000000000
--- a/chromium/content/browser/compositor/in_process_display_client.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/compositor/in_process_display_client.h"
-
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-
-#if defined(OS_MACOSX)
-#include "ui/accelerated_widget_mac/ca_layer_frame_sink.h"
-#endif
-
-#if defined(OS_WIN)
-#include <windows.h>
-
-#include "components/viz/common/display/use_layered_window.h"
-#include "components/viz/host/layered_window_updater_impl.h"
-#include "ui/base/win/internal_constants.h"
-#endif
-
-namespace content {
-
-InProcessDisplayClient::InProcessDisplayClient(gfx::AcceleratedWidget widget)
- : binding_(this) {
-#if defined(OS_MACOSX) || defined(OS_WIN)
- widget_ = widget;
-#endif
-}
-
-InProcessDisplayClient::~InProcessDisplayClient() {}
-
-viz::mojom::DisplayClientPtr InProcessDisplayClient::GetBoundPtr(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- viz::mojom::DisplayClientPtr ptr;
- binding_.Bind(mojo::MakeRequest(&ptr), task_runner);
- return ptr;
-}
-
-void InProcessDisplayClient::OnDisplayReceivedCALayerParams(
- const gfx::CALayerParams& ca_layer_params) {
-#if defined(OS_MACOSX)
- ui::CALayerFrameSink* ca_layer_frame_sink =
- ui::CALayerFrameSink::FromAcceleratedWidget(widget_);
- if (ca_layer_frame_sink)
- ca_layer_frame_sink->UpdateCALayerTree(ca_layer_params);
- else
- DLOG(WARNING) << "Received frame for non-existent widget.";
-#else
- DLOG(ERROR) << "Should not receive CALayer params on non-macOS platforms.";
-#endif
-}
-
-void InProcessDisplayClient::DidSwapAfterSnapshotRequestReceived(
- const std::vector<ui::LatencyInfo>& latency_info) {
- RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info);
-}
-
-void InProcessDisplayClient::CreateLayeredWindowUpdater(
- viz::mojom::LayeredWindowUpdaterRequest request) {
-#if defined(OS_WIN)
- if (!viz::NeedsToUseLayerWindow(widget_)) {
- DLOG(ERROR) << "HWND shouldn't be using a layered window";
- return;
- }
-
- layered_window_updater_ = std::make_unique<viz::LayeredWindowUpdaterImpl>(
- widget_, std::move(request));
-#else
-// This should never happen on non-Windows platforms.
-#endif
-}
-
-} // namespace content
diff --git a/chromium/content/browser/compositor/in_process_display_client.h b/chromium/content/browser/compositor/in_process_display_client.h
deleted file mode 100644
index baa83594ed5..00000000000
--- a/chromium/content/browser/compositor/in_process_display_client.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_COMPOSITOR_IN_PROCESS_DISPLAY_CLIENT_H_
-#define CONTENT_BROWSER_COMPOSITOR_IN_PROCESS_DISPLAY_CLIENT_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/single_thread_task_runner.h"
-#include "build/build_config.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace viz {
-class LayeredWindowUpdaterImpl;
-}
-
-namespace content {
-
-// A DisplayClient that can be used to display received
-// gfx::CALayerParams in a CALayer tree in this process.
-class InProcessDisplayClient : public viz::mojom::DisplayClient {
- public:
- explicit InProcessDisplayClient(gfx::AcceleratedWidget widget);
- ~InProcessDisplayClient() override;
-
- viz::mojom::DisplayClientPtr GetBoundPtr(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
-
- private:
- // viz::mojom::DisplayClient implementation:
- void OnDisplayReceivedCALayerParams(
- const gfx::CALayerParams& ca_layer_params) override;
- void DidSwapAfterSnapshotRequestReceived(
- const std::vector<ui::LatencyInfo>& latency_info) override;
- void CreateLayeredWindowUpdater(
- viz::mojom::LayeredWindowUpdaterRequest request) override;
-
- mojo::Binding<viz::mojom::DisplayClient> binding_;
-#if defined(OS_MACOSX) || defined(OS_WIN)
- gfx::AcceleratedWidget widget_;
-#endif
-
-#if defined(OS_WIN)
- std::unique_ptr<viz::LayeredWindowUpdaterImpl> layered_window_updater_;
-#endif
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_COMPOSITOR_IN_PROCESS_DISPLAY_CLIENT_H_
diff --git a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
index 2792d4646f5..3b3dc6943a6 100644
--- a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
@@ -193,7 +193,6 @@ void OffscreenBrowserCompositorOutputSurface::OnReflectorChanged() {
void OffscreenBrowserCompositorOutputSurface::OnSwapBuffersComplete(
const std::vector<ui::LatencyInfo>& latency_info,
bool need_presentation_feedback) {
- RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info);
latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
client_->DidReceiveSwapBuffersAck();
if (need_presentation_feedback)
diff --git a/chromium/content/browser/compositor/owned_mailbox.cc b/chromium/content/browser/compositor/owned_mailbox.cc
index 69e1687c9d0..f1eddad0fbc 100644
--- a/chromium/content/browser/compositor/owned_mailbox.cc
+++ b/chromium/content/browser/compositor/owned_mailbox.cc
@@ -41,9 +41,11 @@ void OwnedMailbox::Destroy() {
gl_helper_ = nullptr;
}
-void OwnedMailbox::OnLostResources() {
+void OwnedMailbox::OnLostSharedContext() {
if (gl_helper_)
Destroy();
}
+void OwnedMailbox::OnLostVizProcess() {}
+
} // namespace content
diff --git a/chromium/content/browser/compositor/owned_mailbox.h b/chromium/content/browser/compositor/owned_mailbox.h
index d703dfa5b99..9880759f4c6 100644
--- a/chromium/content/browser/compositor/owned_mailbox.h
+++ b/chromium/content/browser/compositor/owned_mailbox.h
@@ -41,7 +41,8 @@ class CONTENT_EXPORT OwnedMailbox : public base::RefCounted<OwnedMailbox>,
~OwnedMailbox() override;
// ImageTransportFactoryObserver implementation.
- void OnLostResources() override;
+ void OnLostSharedContext() override;
+ void OnLostVizProcess() override;
private:
friend class base::RefCounted<OwnedMailbox>;
diff --git a/chromium/content/browser/compositor/reflector_impl_unittest.cc b/chromium/content/browser/compositor/reflector_impl_unittest.cc
index feb02e87cfb..fd673e054bd 100644
--- a/chromium/content/browser/compositor/reflector_impl_unittest.cc
+++ b/chromium/content/browser/compositor/reflector_impl_unittest.cc
@@ -14,7 +14,6 @@
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
#include "components/viz/test/test_context_provider.h"
-#include "components/viz/test/test_web_graphics_context_3d.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/browser/compositor/reflector_texture.h"
#include "content/browser/compositor/test/test_image_transport_factory.h"
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
index b5b49363709..ff4f125cdd1 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
@@ -71,10 +71,9 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
base::TimeTicks swap_time = base::TimeTicks::Now();
for (auto& latency : frame.latency_info) {
latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, swap_time, 1);
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, swap_time, 1);
latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, swap_time,
- 1);
+ ui::INPUT_EVENT_LATENCY_FRAME_SWAP_COMPONENT, swap_time, 1);
}
gfx::VSyncProvider* vsync_provider = software_device()->GetVSyncProvider();
@@ -93,7 +92,6 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
void SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback(
const std::vector<ui::LatencyInfo>& latency_info,
bool need_presentation_feedback) {
- RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info);
latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
client_->DidReceiveSwapBuffersAck();
if (need_presentation_feedback) {
diff --git a/chromium/content/browser/compositor/viz_process_transport_factory.cc b/chromium/content/browser/compositor/viz_process_transport_factory.cc
index 7f02b82c3a4..af692aeb080 100644
--- a/chromium/content/browser/compositor/viz_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/viz_process_transport_factory.cc
@@ -10,18 +10,17 @@
#include "base/command_line.h"
#include "base/debug/dump_without_crashing.h"
#include "base/single_thread_task_runner.h"
+#include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
#include "cc/raster/single_thread_task_graph_runner.h"
-#include "components/viz/client/client_layer_tree_frame_sink.h"
#include "components/viz/client/hit_test_data_provider_draw_quad.h"
#include "components/viz/client/local_surface_id_provider.h"
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/gpu/raster_context_provider.h"
+#include "components/viz/common/switches.h"
#include "components/viz/host/host_frame_sink_manager.h"
-#include "components/viz/host/renderer_settings_creation.h"
#include "components/viz/service/display_embedder/compositing_mode_reporter_impl.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "content/browser/browser_main_loop.h"
-#include "content/browser/compositor/external_begin_frame_controller_client_impl.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
@@ -110,12 +109,13 @@ VizProcessTransportFactory::VizProcessTransportFactory(
gpu::GpuChannelEstablishFactory* gpu_channel_establish_factory,
scoped_refptr<base::SingleThreadTaskRunner> resize_task_runner,
viz::CompositingModeReporterImpl* compositing_mode_reporter)
- : gpu_channel_establish_factory_(gpu_channel_establish_factory),
- resize_task_runner_(std::move(resize_task_runner)),
+ : ui::HostContextFactoryPrivate(
+ kBrowserClientId,
+ BrowserMainLoop::GetInstance()->host_frame_sink_manager(),
+ resize_task_runner),
+ gpu_channel_establish_factory_(gpu_channel_establish_factory),
compositing_mode_reporter_(compositing_mode_reporter),
- frame_sink_id_allocator_(kBrowserClientId),
task_graph_runner_(std::make_unique<cc::SingleThreadTaskGraphRunner>()),
- renderer_settings_(viz::CreateRendererSettings()),
weak_ptr_factory_(this) {
DCHECK(gpu_channel_establish_factory_);
task_graph_runner_->Start("CompositorTileWorker1",
@@ -150,28 +150,50 @@ void VizProcessTransportFactory::ConnectHostFrameSinkManager() {
// Setup HostFrameSinkManager with interface endpoints.
GetHostFrameSinkManager()->BindAndSetManager(
- std::move(frame_sink_manager_client_request), resize_task_runner_,
+ std::move(frame_sink_manager_client_request), resize_task_runner(),
std::move(frame_sink_manager));
- // Hop to the IO thread, then send the other side of interface to viz process.
- auto connect_on_io_thread =
- [](viz::mojom::FrameSinkManagerRequest request,
- viz::mojom::FrameSinkManagerClientPtrInfo client) {
- // There should always be a GpuProcessHost instance, and GPU process,
- // for running the compositor thread. The exception is during shutdown
- // the GPU process won't be restarted and GpuProcessHost::Get() can
- // return null.
- auto* gpu_process_host = GpuProcessHost::Get();
- if (gpu_process_host) {
- gpu_process_host->ConnectFrameSinkManager(std::move(request),
- std::move(client));
- }
- };
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(connect_on_io_thread,
- std::move(frame_sink_manager_request),
- frame_sink_manager_client.PassInterface()));
+ if (GpuDataManagerImpl::GetInstance()->GpuProcessStartAllowed()) {
+ // Hop to the IO thread, then send the other side of interface to viz
+ // process.
+ auto connect_on_io_thread =
+ [](viz::mojom::FrameSinkManagerRequest request,
+ viz::mojom::FrameSinkManagerClientPtrInfo client) {
+ // There should always be a GpuProcessHost instance, and GPU process,
+ // for running the compositor thread. The exception is during shutdown
+ // the GPU process won't be restarted and GpuProcessHost::Get() can
+ // return null.
+ auto* gpu_process_host = GpuProcessHost::Get();
+ if (gpu_process_host) {
+ gpu_process_host->ConnectFrameSinkManager(std::move(request),
+ std::move(client));
+ }
+ };
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(connect_on_io_thread,
+ std::move(frame_sink_manager_request),
+ frame_sink_manager_client.PassInterface()));
+ } else {
+ DCHECK(!viz_compositor_thread_);
+
+ // GPU process access is disabled. Start a new thread to run the display
+ // compositor in-process and connect HostFrameSinkManager to it.
+ viz_compositor_thread_ = std::make_unique<viz::VizCompositorThreadRunner>();
+
+ viz::mojom::FrameSinkManagerParamsPtr params =
+ viz::mojom::FrameSinkManagerParams::New();
+ params->restart_id = viz::BeginFrameSource::kNotRestartableId;
+ base::Optional<uint32_t> activation_deadline_in_frames =
+ switches::GetDeadlineToSynchronizeSurfaces();
+ params->use_activation_deadline = activation_deadline_in_frames.has_value();
+ params->activation_deadline_in_frames =
+ activation_deadline_in_frames.value_or(0u);
+ params->frame_sink_manager = std::move(frame_sink_manager_request);
+ params->frame_sink_manager_client =
+ frame_sink_manager_client.PassInterface();
+ viz_compositor_thread_->CreateFrameSinkManager(std::move(params));
+ }
}
void VizProcessTransportFactory::CreateLayerTreeFrameSink(
@@ -181,7 +203,8 @@ void VizProcessTransportFactory::CreateLayerTreeFrameSink(
compositor->widget());
#endif
- if (is_gpu_compositing_disabled_ || compositor->force_software_compositor()) {
+ if (is_gpu_compositing_disabled() ||
+ compositor->force_software_compositor()) {
OnEstablishedGpuChannel(compositor, nullptr);
return;
}
@@ -192,7 +215,7 @@ void VizProcessTransportFactory::CreateLayerTreeFrameSink(
scoped_refptr<viz::ContextProvider>
VizProcessTransportFactory::SharedMainThreadContextProvider() {
- if (is_gpu_compositing_disabled_)
+ if (is_gpu_compositing_disabled())
return nullptr;
if (!main_context_provider_) {
@@ -211,14 +234,7 @@ VizProcessTransportFactory::SharedMainThreadContextProvider() {
}
void VizProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
-#if defined(OS_WIN)
- // TODO(crbug.com/791660): Make sure that GpuProcessHost::SetChildSurface()
- // doesn't crash the GPU process after parent is unregistered.
- gfx::RenderingWindowManager::GetInstance()->UnregisterParent(
- compositor->widget());
-#endif
-
- compositor_data_map_.erase(compositor);
+ UnconfigureCompositor(compositor);
}
double VizProcessTransportFactory::GetRefreshRate() const {
@@ -245,112 +261,19 @@ void VizProcessTransportFactory::RemoveObserver(
observer_list_.RemoveObserver(observer);
}
-std::unique_ptr<ui::Reflector> VizProcessTransportFactory::CreateReflector(
- ui::Compositor* source,
- ui::Layer* target) {
- // TODO(crbug.com/601869): Reflector needs to be rewritten for viz.
- NOTIMPLEMENTED();
- return nullptr;
-}
-
-void VizProcessTransportFactory::RemoveReflector(ui::Reflector* reflector) {
- // TODO(crbug.com/601869): Reflector needs to be rewritten for viz.
- NOTIMPLEMENTED();
-}
-
-viz::FrameSinkId VizProcessTransportFactory::AllocateFrameSinkId() {
- return frame_sink_id_allocator_.NextFrameSinkId();
-}
-
-viz::HostFrameSinkManager*
-VizProcessTransportFactory::GetHostFrameSinkManager() {
- return BrowserMainLoop::GetInstance()->host_frame_sink_manager();
-}
-
-void VizProcessTransportFactory::SetDisplayVisible(ui::Compositor* compositor,
- bool visible) {
- auto iter = compositor_data_map_.find(compositor);
- if (iter == compositor_data_map_.end() || !iter->second.display_private)
- return;
- iter->second.display_private->SetDisplayVisible(visible);
-}
-
-void VizProcessTransportFactory::ResizeDisplay(ui::Compositor* compositor,
- const gfx::Size& size) {
- // Do nothing and resize when a CompositorFrame with a new size arrives.
-}
-
-void VizProcessTransportFactory::SetDisplayColorMatrix(
- ui::Compositor* compositor,
- const SkMatrix44& matrix) {
- auto iter = compositor_data_map_.find(compositor);
- if (iter == compositor_data_map_.end() || !iter->second.display_private)
- return;
- iter->second.display_private->SetDisplayColorMatrix(gfx::Transform(matrix));
-}
-
-void VizProcessTransportFactory::SetDisplayColorSpace(
- ui::Compositor* compositor,
- const gfx::ColorSpace& blending_color_space,
- const gfx::ColorSpace& output_color_space) {
- auto iter = compositor_data_map_.find(compositor);
- if (iter == compositor_data_map_.end() || !iter->second.display_private)
- return;
- iter->second.display_private->SetDisplayColorSpace(blending_color_space,
- output_color_space);
-}
-
-void VizProcessTransportFactory::SetAuthoritativeVSyncInterval(
- ui::Compositor* compositor,
- base::TimeDelta interval) {
- auto iter = compositor_data_map_.find(compositor);
- if (iter == compositor_data_map_.end() || !iter->second.display_private)
- return;
- iter->second.display_private->SetAuthoritativeVSyncInterval(interval);
-}
-
-void VizProcessTransportFactory::SetDisplayVSyncParameters(
- ui::Compositor* compositor,
- base::TimeTicks timebase,
- base::TimeDelta interval) {
- auto iter = compositor_data_map_.find(compositor);
- if (iter == compositor_data_map_.end() || !iter->second.display_private)
- return;
- iter->second.display_private->SetDisplayVSyncParameters(timebase, interval);
-}
-
-void VizProcessTransportFactory::IssueExternalBeginFrame(
- ui::Compositor* compositor,
- const viz::BeginFrameArgs& args) {
- auto iter = compositor_data_map_.find(compositor);
- if (iter == compositor_data_map_.end() || !iter->second.display_private)
- return;
-
- DCHECK(iter->second.external_begin_frame_controller_client);
- iter->second.external_begin_frame_controller_client->GetController()
- ->IssueExternalBeginFrame(args);
-}
-
-void VizProcessTransportFactory::SetOutputIsSecure(ui::Compositor* compositor,
- bool secure) {
- auto iter = compositor_data_map_.find(compositor);
- if (iter == compositor_data_map_.end() || !iter->second.display_private)
- return;
- iter->second.display_private->SetOutputIsSecure(secure);
+bool VizProcessTransportFactory::SyncTokensRequiredForDisplayCompositor() {
+ // The display compositor is out-of-process, so must be using a different
+ // context from the UI compositor, and requires synchronization between them.
+ return true;
}
-viz::FrameSinkManagerImpl* VizProcessTransportFactory::GetFrameSinkManager() {
- // When running with viz there is no FrameSinkManagerImpl in the browser
- // process. FrameSinkManagerImpl runs in the GPU process instead. Anything in
- // the browser process that relies FrameSinkManagerImpl or SurfaceManager
- // internal state needs to change. See https://crbug.com/787097 and
- // https://crbug.com/760181 for more context.
- NOTREACHED();
- return nullptr;
+void VizProcessTransportFactory::DisableGpuCompositing() {
+ if (!is_gpu_compositing_disabled())
+ DisableGpuCompositing(nullptr);
}
bool VizProcessTransportFactory::IsGpuCompositingDisabled() {
- return is_gpu_compositing_disabled_;
+ return is_gpu_compositing_disabled();
}
ui::ContextFactory* VizProcessTransportFactory::GetContextFactory() {
@@ -379,7 +302,7 @@ void VizProcessTransportFactory::DisableGpuCompositing(
DLOG(ERROR) << "Switching to software compositing.";
// Change the result of IsGpuCompositingDisabled() before notifying anything.
- is_gpu_compositing_disabled_ = true;
+ set_is_gpu_compositing_disabled(true);
compositing_mode_reporter_->SetUsingSoftwareCompositing();
@@ -396,27 +319,18 @@ void VizProcessTransportFactory::DisableGpuCompositing(
main_context_provider_ = nullptr;
}
- // Here we remove the FrameSink from every compositor that needs to fall back
- // to software compositing.
- //
- // Releasing the FrameSink from the compositor will remove it from
- // |compositor_data_map_|, so we can't do that while iterating though the
- // collection.
- std::vector<ui::Compositor*> to_release;
- to_release.reserve(compositor_data_map_.size());
- for (auto& pair : compositor_data_map_) {
- ui::Compositor* compositor = pair.first;
+ // Reemove the FrameSink from every compositor that needs to fall back to
+ // software compositing.
+ for (ui::Compositor* compositor : GetAllCompositors()) {
// The |guilty_compositor| is in the process of setting up its FrameSink
// so removing it from |compositor_data_map_| would be both pointless and
// the cause of a crash.
// Compositors with force_software_compositor() do not follow the global
// compositing mode, so they do not need to changed.
- if (compositor != guilty_compositor &&
- !compositor->force_software_compositor()) {
- to_release.push_back(compositor);
- }
- }
- for (ui::Compositor* compositor : to_release) {
+ if (compositor == guilty_compositor ||
+ compositor->force_software_compositor())
+ continue;
+
// Compositor expects to be not visible when releasing its FrameSink.
bool visible = compositor->IsVisible();
compositor->SetVisible(false);
@@ -432,6 +346,9 @@ void VizProcessTransportFactory::DisableGpuCompositing(
void VizProcessTransportFactory::OnGpuProcessLost() {
// Reconnect HostFrameSinkManager to new GPU process.
ConnectHostFrameSinkManager();
+
+ for (auto& observer : observer_list_)
+ observer.OnLostVizProcess();
}
void VizProcessTransportFactory::OnEstablishedGpuChannel(
@@ -441,8 +358,8 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
if (!compositor)
return;
- bool gpu_compositing =
- !is_gpu_compositing_disabled_ && !compositor->force_software_compositor();
+ bool gpu_compositing = !is_gpu_compositing_disabled() &&
+ !compositor->force_software_compositor();
if (gpu_compositing) {
auto context_result =
@@ -459,72 +376,6 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
}
}
-#if defined(OS_WIN)
- gfx::RenderingWindowManager::GetInstance()->RegisterParent(
- compositor->widget());
-#endif
-
- auto& compositor_data = compositor_data_map_[compositor];
-
- auto root_params = viz::mojom::RootCompositorFrameSinkParams::New();
-
- // Create interfaces for a root CompositorFrameSink.
- viz::mojom::CompositorFrameSinkAssociatedPtrInfo sink_info;
- root_params->compositor_frame_sink = mojo::MakeRequest(&sink_info);
- viz::mojom::CompositorFrameSinkClientRequest client_request =
- mojo::MakeRequest(&root_params->compositor_frame_sink_client);
- root_params->display_private =
- mojo::MakeRequest(&compositor_data.display_private);
- compositor_data.display_client =
- std::make_unique<InProcessDisplayClient>(compositor->widget());
- root_params->display_client =
- compositor_data.display_client->GetBoundPtr(resize_task_runner_)
- .PassInterface();
-
-#if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW)
- gpu::SurfaceHandle surface_handle = compositor->widget();
-#else
- // TODO(kylechar): Fix this when we support macOS.
- gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
-#endif
-
- // Initialize ExternalBeginFrameController client if enabled.
- compositor_data.external_begin_frame_controller_client.reset();
- if (compositor->external_begin_frames_enabled()) {
- compositor_data.external_begin_frame_controller_client =
- std::make_unique<ExternalBeginFrameControllerClientImpl>(compositor);
- root_params->external_begin_frame_controller =
- compositor_data.external_begin_frame_controller_client
- ->GetControllerRequest();
- root_params->external_begin_frame_controller_client =
- compositor_data.external_begin_frame_controller_client->GetBoundPtr()
- .PassInterface();
- }
-
- root_params->frame_sink_id = compositor->frame_sink_id();
- root_params->widget = surface_handle;
- root_params->gpu_compositing = gpu_compositing;
- root_params->renderer_settings = renderer_settings_;
-
- // Connects the viz process end of CompositorFrameSink message pipes. The
- // browser compositor may request a new CompositorFrameSink on context loss,
- // which will destroy the existing CompositorFrameSink.
- GetHostFrameSinkManager()->CreateRootCompositorFrameSink(
- std::move(root_params));
-
- // Create LayerTreeFrameSink with the browser end of CompositorFrameSink.
- viz::ClientLayerTreeFrameSink::InitParams params;
- params.compositor_task_runner = compositor->task_runner();
- params.gpu_memory_buffer_manager = GetGpuMemoryBufferManager();
- params.pipes.compositor_frame_sink_associated_info = std::move(sink_info);
- params.pipes.client_request = std::move(client_request);
- params.local_surface_id_provider =
- std::make_unique<viz::DefaultLocalSurfaceIdProvider>();
- params.enable_surface_synchronization = true;
- params.hit_test_data_provider =
- std::make_unique<viz::HitTestDataProviderDrawQuad>(
- /*should_ask_for_child_region=*/false);
-
scoped_refptr<viz::ContextProvider> compositor_context;
scoped_refptr<viz::RasterContextProvider> worker_context;
if (gpu_compositing) {
@@ -532,20 +383,14 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
compositor_context = main_context_provider_;
worker_context = worker_context_provider_;
}
- compositor->SetLayerTreeFrameSink(
- std::make_unique<viz::ClientLayerTreeFrameSink>(
- std::move(compositor_context), std::move(worker_context), &params));
-
-#if defined(OS_WIN)
- gfx::RenderingWindowManager::GetInstance()->DoSetParentOnChild(
- compositor->widget());
-#endif
+ ConfigureCompositor(compositor_weak_ptr, std::move(compositor_context),
+ std::move(worker_context));
}
gpu::ContextResult
VizProcessTransportFactory::TryCreateContextsForGpuCompositing(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
- DCHECK(!is_gpu_compositing_disabled_);
+ DCHECK(!is_gpu_compositing_disabled());
// Fallback to software compositing if there is no IPC channel.
if (!gpu_channel_host)
@@ -575,7 +420,7 @@ VizProcessTransportFactory::TryCreateContextsForGpuCompositing(
kSharedWorkerContextSupportsLocking, kSharedWorkerContextSupportsGLES2,
kSharedWorkerContextSupportsRaster,
kSharedWorkerContextSupportsGrContext,
- ui::command_buffer_metrics::BROWSER_WORKER_CONTEXT);
+ ui::command_buffer_metrics::ContextType::BROWSER_WORKER);
// Don't observer context loss on |worker_context_provider_| here, that is
// already observered by LayerTreeFrameSink. The lost context will be caught
@@ -602,8 +447,8 @@ VizProcessTransportFactory::TryCreateContextsForGpuCompositing(
std::move(gpu_channel_host), GetGpuMemoryBufferManager(),
kCompositorContextSupportsLocking, kCompositorContextSupportsGLES2,
kCompositorContextSupportsRaster, kCompositorContextSupportsGrContext,
- ui::command_buffer_metrics::UI_COMPOSITOR_CONTEXT);
- main_context_provider_->SetDefaultTaskRunner(resize_task_runner_);
+ ui::command_buffer_metrics::ContextType::BROWSER_MAIN_THREAD);
+ main_context_provider_->SetDefaultTaskRunner(resize_task_runner());
auto context_result = main_context_provider_->BindToCurrentThread();
if (context_result != gpu::ContextResult::kSuccess) {
@@ -627,15 +472,7 @@ void VizProcessTransportFactory::OnLostMainThreadSharedContext() {
}
for (auto& observer : observer_list_)
- observer.OnLostResources();
+ observer.OnLostSharedContext();
}
-VizProcessTransportFactory::CompositorData::CompositorData() = default;
-VizProcessTransportFactory::CompositorData::CompositorData(
- CompositorData&& other) = default;
-VizProcessTransportFactory::CompositorData::~CompositorData() = default;
-VizProcessTransportFactory::CompositorData&
-VizProcessTransportFactory::CompositorData::operator=(CompositorData&& other) =
- default;
-
} // namespace content
diff --git a/chromium/content/browser/compositor/viz_process_transport_factory.h b/chromium/content/browser/compositor/viz_process_transport_factory.h
index 229b760eb08..731a309d53a 100644
--- a/chromium/content/browser/compositor/viz_process_transport_factory.h
+++ b/chromium/content/browser/compositor/viz_process_transport_factory.h
@@ -7,19 +7,17 @@
#include <memory>
-#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "build/build_config.h"
-#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/gpu/context_lost_observer.h"
-#include "components/viz/common/surfaces/frame_sink_id_allocator.h"
+#include "components/viz/service/main/viz_compositor_thread_runner.h"
#include "content/browser/compositor/image_transport_factory.h"
-#include "content/browser/compositor/in_process_display_client.h"
#include "gpu/command_buffer/common/context_result.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "ui/compositor/compositor.h"
+#include "ui/compositor/host/host_context_factory_private.h"
namespace base {
class SingleThreadTaskRunner;
@@ -44,14 +42,12 @@ class RasterContextProvider;
namespace content {
-class ExternalBeginFrameControllerClientImpl;
-
// A replacement for GpuProcessTransportFactory to be used when running viz. In
// this configuration the display compositor is located in the viz process
// instead of in the browser process. Any interaction with the display
// compositor must happen over IPC.
class VizProcessTransportFactory : public ui::ContextFactory,
- public ui::ContextFactoryPrivate,
+ public ui::HostContextFactoryPrivate,
public ImageTransportFactory,
public viz::ContextLostObserver {
public:
@@ -75,32 +71,10 @@ class VizProcessTransportFactory : public ui::ContextFactory,
cc::TaskGraphRunner* GetTaskGraphRunner() override;
void AddObserver(ui::ContextFactoryObserver* observer) override;
void RemoveObserver(ui::ContextFactoryObserver* observer) override;
-
- // ui::ContextFactoryPrivate implementation.
- std::unique_ptr<ui::Reflector> CreateReflector(ui::Compositor* source,
- ui::Layer* target) override;
- void RemoveReflector(ui::Reflector* reflector) override;
- viz::FrameSinkId AllocateFrameSinkId() override;
- viz::HostFrameSinkManager* GetHostFrameSinkManager() override;
- void SetDisplayVisible(ui::Compositor* compositor, bool visible) override;
- void ResizeDisplay(ui::Compositor* compositor,
- const gfx::Size& size) override;
- void SetDisplayColorMatrix(ui::Compositor* compositor,
- const SkMatrix44& matrix) override;
- void SetDisplayColorSpace(ui::Compositor* compositor,
- const gfx::ColorSpace& blending_color_space,
- const gfx::ColorSpace& output_color_space) override;
- void SetAuthoritativeVSyncInterval(ui::Compositor* compositor,
- base::TimeDelta interval) override;
- void SetDisplayVSyncParameters(ui::Compositor* compositor,
- base::TimeTicks timebase,
- base::TimeDelta interval) override;
- void IssueExternalBeginFrame(ui::Compositor* compositor,
- const viz::BeginFrameArgs& args) override;
- void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override;
- viz::FrameSinkManagerImpl* GetFrameSinkManager() override;
+ bool SyncTokensRequiredForDisplayCompositor() override;
// ImageTransportFactory implementation.
+ void DisableGpuCompositing() override;
bool IsGpuCompositingDisabled() override;
ui::ContextFactory* GetContextFactory() override;
ui::ContextFactoryPrivate* GetContextFactoryPrivate() override;
@@ -110,26 +84,6 @@ class VizProcessTransportFactory : public ui::ContextFactory,
void OnContextLost() override;
private:
- struct CompositorData {
- CompositorData();
- CompositorData(CompositorData&& other);
- ~CompositorData();
- CompositorData& operator=(CompositorData&& other);
-
- // Privileged interface that controls the display for a root
- // CompositorFrameSink.
- viz::mojom::DisplayPrivateAssociatedPtr display_private;
- std::unique_ptr<InProcessDisplayClient> display_client;
-
- // Controls external BeginFrames for the display. Only set if external
- // BeginFrames are enabled for the compositor.
- std::unique_ptr<ExternalBeginFrameControllerClientImpl>
- external_begin_frame_controller_client;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CompositorData);
- };
-
// Disables GPU compositing. This notifies UI and renderer compositors to drop
// LayerTreeFrameSinks and request new ones. If fallback happens while
// creating a new LayerTreeFrameSink for UI compositor it should be passed in
@@ -159,15 +113,11 @@ class VizProcessTransportFactory : public ui::ContextFactory,
void OnLostMainThreadSharedContext();
gpu::GpuChannelEstablishFactory* const gpu_channel_establish_factory_;
- scoped_refptr<base::SingleThreadTaskRunner> const resize_task_runner_;
// Controls the compositing mode based on what mode the display compositors
// are using.
viz::CompositingModeReporterImpl* const compositing_mode_reporter_;
- base::flat_map<ui::Compositor*, CompositorData> compositor_data_map_;
- bool is_gpu_compositing_disabled_ = false;
-
base::ObserverList<ui::ContextFactoryObserver> observer_list_;
// ContextProvider used on worker threads for rasterization.
@@ -177,9 +127,11 @@ class VizProcessTransportFactory : public ui::ContextFactory,
// returned from GetSharedMainThreadContextProvider().
scoped_refptr<ui::ContextProviderCommandBuffer> main_context_provider_;
- viz::FrameSinkIdAllocator frame_sink_id_allocator_;
std::unique_ptr<cc::SingleThreadTaskGraphRunner> task_graph_runner_;
- const viz::RendererSettings renderer_settings_;
+
+ // Will start and run the VizCompositorThread for using an in-process display
+ // compositor.
+ std::unique_ptr<viz::VizCompositorThreadRunner> viz_compositor_thread_;
base::WeakPtrFactory<VizProcessTransportFactory> weak_ptr_factory_;
diff --git a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
index 50ea53d2cec..8637358c8e2 100644
--- a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
@@ -94,6 +94,10 @@ void VulkanBrowserCompositorOutputSurface::SetDrawRectangle(
NOTREACHED();
}
+unsigned VulkanBrowserCompositorOutputSurface::UpdateGpuFence() {
+ return 0;
+}
+
uint32_t
VulkanBrowserCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
NOTIMPLEMENTED();
diff --git a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h
index 7de13ae0e6a..870afb75ceb 100644
--- a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h
@@ -47,6 +47,7 @@ class VulkanBrowserCompositorOutputSurface
uint32_t GetFramebufferCopyTextureFormat() override;
void SwapBuffers(viz::OutputSurfaceFrame frame) override;
void SetDrawRectangle(const gfx::Rect& rect) override;
+ unsigned UpdateGpuFence() override;
gpu::VulkanSurface* GetVulkanSurface() override;
diff --git a/chromium/content/browser/content_service_browsertest.cc b/chromium/content/browser/content_service_browsertest.cc
new file mode 100644
index 00000000000..633ff83f863
--- /dev/null
+++ b/chromium/content/browser/content_service_browsertest.cc
@@ -0,0 +1,59 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/shell/browser/shell.h"
+#include "services/content/public/cpp/navigable_contents.h"
+#include "services/content/public/mojom/constants.mojom.h"
+#include "services/content/public/mojom/navigable_contents_factory.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace content {
+namespace {
+
+class ContentServiceBrowserTest : public ContentBrowserTest {
+ public:
+ ContentServiceBrowserTest() = default;
+ ~ContentServiceBrowserTest() override = default;
+
+ void SetUpOnMainThread() override {
+ ContentBrowserTest::SetUpOnMainThread();
+
+ base::FilePath test_data_path;
+ CHECK(base::PathService::Get(DIR_TEST_DATA, &test_data_path));
+ embedded_test_server()->ServeFilesFromDirectory(test_data_path);
+ CHECK(embedded_test_server()->Start());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ContentServiceBrowserTest);
+};
+
+// Verifies that the embedded Content Service is reachable. Does a basic
+// end-to-end sanity check to also verify that a NavigableContents is backed by
+// a WebContents instance in the browser.
+IN_PROC_BROWSER_TEST_F(ContentServiceBrowserTest, EmbeddedContentService) {
+ auto* browser_context = shell()->web_contents()->GetBrowserContext();
+ auto* connector = BrowserContext::GetConnectorFor(browser_context);
+
+ content::mojom::NavigableContentsFactoryPtr factory;
+ connector->BindInterface(content::mojom::kServiceName, &factory);
+ auto contents = std::make_unique<content::NavigableContents>(factory.get());
+
+ base::RunLoop loop;
+ contents->set_did_stop_loading_callback_for_testing(loop.QuitClosure());
+ contents->Navigate(embedded_test_server()->GetURL("/hello.html"));
+ loop.Run();
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/content_service_delegate_impl.cc b/chromium/content/browser/content_service_delegate_impl.cc
new file mode 100644
index 00000000000..40eb806f117
--- /dev/null
+++ b/chromium/content/browser/content_service_delegate_impl.cc
@@ -0,0 +1,90 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/content_service_delegate_impl.h"
+
+#include "base/macros.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "services/content/navigable_contents_delegate.h"
+#include "services/content/service.h"
+
+namespace content {
+
+namespace {
+
+// Bridge between Content Service navigable contents delegation API and a
+// WebContentsImpl.
+class NavigableContentsDelegateImpl : public content::NavigableContentsDelegate,
+ public WebContentsObserver {
+ public:
+ explicit NavigableContentsDelegateImpl(BrowserContext* browser_context,
+ mojom::NavigableContentsClient* client)
+ : client_(client) {
+ WebContents::CreateParams params(browser_context);
+ web_contents_ = WebContents::Create(params);
+ WebContentsObserver::Observe(web_contents_.get());
+ }
+
+ ~NavigableContentsDelegateImpl() override {
+ WebContentsObserver::Observe(nullptr);
+ }
+
+ private:
+ // content::NavigableContentsDelegate:
+ gfx::NativeView GetNativeView() override {
+ return web_contents_->GetNativeView();
+ }
+
+ void Navigate(const GURL& url) override {
+ NavigationController::LoadURLParams params(url);
+ params.transition_type = ui::PAGE_TRANSITION_AUTO_TOPLEVEL;
+ web_contents_->GetController().LoadURLWithParams(params);
+ }
+
+ // WebContentsObserver:
+ void DidStopLoading() override { client_->DidStopLoading(); }
+
+ std::unique_ptr<WebContents> web_contents_;
+ mojom::NavigableContentsClient* const client_;
+
+ DISALLOW_COPY_AND_ASSIGN(NavigableContentsDelegateImpl);
+};
+
+} // namespace
+
+ContentServiceDelegateImpl::ContentServiceDelegateImpl(
+ BrowserContext* browser_context)
+ : browser_context_(browser_context) {}
+
+ContentServiceDelegateImpl::~ContentServiceDelegateImpl() {
+ // This delegate is destroyed immediately before |browser_context_| is
+ // destroyed. We force-kill any Content Service instances which depend on
+ // |this|, since they will no longer be functional anyway.
+ std::set<content::Service*> instances;
+ std::swap(instances, service_instances_);
+ for (content::Service* service : instances) {
+ // Eventually destroys |service|. Ensures that no more calls into |this|
+ // will occur.
+ service->ForceQuit();
+ }
+}
+
+void ContentServiceDelegateImpl::AddService(content::Service* service) {
+ service_instances_.insert(service);
+}
+
+void ContentServiceDelegateImpl::WillDestroyServiceInstance(
+ content::Service* service) {
+ service_instances_.erase(service);
+}
+
+std::unique_ptr<content::NavigableContentsDelegate>
+ContentServiceDelegateImpl::CreateNavigableContentsDelegate(
+ mojom::NavigableContentsClient* client) {
+ return std::make_unique<NavigableContentsDelegateImpl>(browser_context_,
+ client);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/content_service_delegate_impl.h b/chromium/content/browser/content_service_delegate_impl.h
new file mode 100644
index 00000000000..70b2295f950
--- /dev/null
+++ b/chromium/content/browser/content_service_delegate_impl.h
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All 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_CONTENT_SERVICE_DELEGATE_IMPL_H_
+#define CONTENT_BROWSER_CONTENT_SERVICE_DELEGATE_IMPL_H_
+
+#include <memory>
+#include <set>
+
+#include "base/macros.h"
+#include "services/content/service_delegate.h"
+
+namespace content {
+
+class BrowserContext;
+
+// Implementation of the main delegate interface for the Content Service. This
+// is used to support the Content Service implementation with content/browser
+// details, without the Content Service having any build dependencies on
+// src/content. There is one instance of this delegate per BrowserContext,
+// shared by any ContentService instance instantiated on behalf of that
+// BrowserContext.
+class ContentServiceDelegateImpl : public content::ServiceDelegate {
+ public:
+ // Constructs a new ContentServiceDelegateImpl for |browser_context|.
+ // |browser_context| must outlive |this|.
+ explicit ContentServiceDelegateImpl(BrowserContext* browser_context);
+ ~ContentServiceDelegateImpl() override;
+
+ // Registers |service| with this delegate. Must be called for any |service|
+ // using |this| as its ContentServiceDelegate. Automatically balanced by
+ // |WillDestroyServiceInstance()|.
+ void AddService(content::Service* service);
+
+ private:
+ // content::ContentServiceDelegate:
+ void WillDestroyServiceInstance(content::Service* service) override;
+ std::unique_ptr<NavigableContentsDelegate> CreateNavigableContentsDelegate(
+ mojom::NavigableContentsClient* client) override;
+
+ BrowserContext* const browser_context_;
+
+ // Tracks ContentService instances currently using this delegate. Necessary
+ // because the lifetime of |this| is tied to the lifetime of
+ // |browser_context_|; on destruction of |this|, we need to force all of these
+ // ContentService instances to terminate, since they cannot operate without
+ // their delegate.
+ std::set<content::Service*> service_instances_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentServiceDelegateImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_CONTENT_SERVICE_DELEGATE_IMPL_H_
diff --git a/chromium/content/browser/cookie_store/cookie_store_manager.cc b/chromium/content/browser/cookie_store/cookie_store_manager.cc
index 8e08a32ed55..717c5d04a3c 100644
--- a/chromium/content/browser/cookie_store/cookie_store_manager.cc
+++ b/chromium/content/browser/cookie_store/cookie_store_manager.cc
@@ -13,9 +13,9 @@
#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_version.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/browser/browser_context.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "url/gurl.h"
@@ -27,13 +27,14 @@ namespace {
const char kSubscriptionsUserKey[] = "cookie_store_subscriptions";
// Handles the result of ServiceWorkerContextWrapper::StoreRegistrationUserData.
-void HandleStoreRegistrationUserDataStatus(ServiceWorkerStatusCode status) {
+void HandleStoreRegistrationUserDataStatus(
+ blink::ServiceWorkerStatusCode status) {
// The current implementation does not have a good way to handle errors in
// StoreRegistrationUserData. Cookie change subscriptions have been added to
// the registration during the install event, so it's too late to surface the
// error to the renderer. The registration has already been persisted, and the
// Service Worker is likely active by now.
- DLOG_IF(ERROR, status != SERVICE_WORKER_OK)
+ DLOG_IF(ERROR, status != blink::ServiceWorkerStatusCode::kOk)
<< "StoreRegistrationUserData failed";
}
@@ -94,13 +95,13 @@ void CookieStoreManager::ListenToCookieChanges(
void CookieStoreManager::ProcessOnDiskSubscriptions(
base::OnceCallback<void(bool)> load_callback,
const std::vector<std::pair<int64_t, std::string>>& user_data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!done_loading_subscriptions_) << __func__ << " already called";
done_loading_subscriptions_ = true;
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
DidLoadAllSubscriptions(false, std::move(load_callback));
return;
}
@@ -480,9 +481,9 @@ void CookieStoreManager::OnCookieChange(
[](base::WeakPtr<CookieStoreManager> manager,
const net::CanonicalCookie& cookie,
::network::mojom::CookieChangeCause cause,
- ServiceWorkerStatusCode find_status,
+ blink::ServiceWorkerStatusCode find_status,
scoped_refptr<ServiceWorkerRegistration> registration) {
- if (find_status != SERVICE_WORKER_OK)
+ if (find_status != blink::ServiceWorkerStatusCode::kOk)
return;
DCHECK(registration);
@@ -513,7 +514,7 @@ void CookieStoreManager::DispatchChangeEvent(
int request_id = active_version->StartRequest(
ServiceWorkerMetrics::EventType::COOKIE_CHANGE, base::DoNothing());
- active_version->event_dispatcher()->DispatchCookieChangeEvent(
+ active_version->endpoint()->DispatchCookieChangeEvent(
cookie, cause, active_version->CreateSimpleEventCallback(request_id));
}
@@ -521,8 +522,8 @@ void CookieStoreManager::DidStartWorkerForChangeEvent(
scoped_refptr<ServiceWorkerRegistration> registration,
const net::CanonicalCookie& cookie,
::network::mojom::CookieChangeCause cause,
- ServiceWorkerStatusCode start_worker_status) {
- if (start_worker_status != SERVICE_WORKER_OK)
+ blink::ServiceWorkerStatusCode start_worker_status) {
+ if (start_worker_status != blink::ServiceWorkerStatusCode::kOk)
return;
DispatchChangeEvent(std::move(registration), cookie, cause);
}
diff --git a/chromium/content/browser/cookie_store/cookie_store_manager.h b/chromium/content/browser/cookie_store/cookie_store_manager.h
index 19ccf7333b1..ce506e744f9 100644
--- a/chromium/content/browser/cookie_store/cookie_store_manager.h
+++ b/chromium/content/browser/cookie_store/cookie_store_manager.h
@@ -105,7 +105,7 @@ class CookieStoreManager : public ServiceWorkerContextCoreObserver,
void ProcessOnDiskSubscriptions(
base::OnceCallback<void(bool)> load_callback,
const std::vector<std::pair<int64_t, std::string>>& user_data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// Runs all the callbacks waiting for on-disk subscription data.
//
@@ -145,7 +145,7 @@ class CookieStoreManager : public ServiceWorkerContextCoreObserver,
scoped_refptr<ServiceWorkerRegistration> registration,
const net::CanonicalCookie& cookie,
::network::mojom::CookieChangeCause cause,
- ServiceWorkerStatusCode start_worker_status);
+ blink::ServiceWorkerStatusCode start_worker_status);
// Used to efficiently implement OnRegistrationDeleted().
//
diff --git a/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc b/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc
index 68c926cab07..b74748e9a2a 100644
--- a/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc
+++ b/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc
@@ -13,7 +13,7 @@
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/storage_partition_impl.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -116,7 +116,7 @@ class CookieStoreWorkerTestHelper : public EmbeddedWorkerTestHelper {
const GURL& scope,
const GURL& script_url,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -129,15 +129,14 @@ class CookieStoreWorkerTestHelper : public EmbeddedWorkerTestHelper {
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id, service_worker_version_id, scope, script_url,
- pause_after_download, std::move(dispatcher_request),
+ pause_after_download, std::move(service_worker_request),
std::move(controller_request), std::move(instance_host),
std::move(provider_info), std::move(installed_scripts_info));
}
// Cookie change subscriptions can only be created in this event handler.
void OnInstallEvent(
- mojom::ServiceWorkerEventDispatcher::DispatchInstallEventCallback
- callback) override {
+ mojom::ServiceWorker::DispatchInstallEventCallback callback) override {
for (auto& subscriptions : install_subscription_batches_) {
cookie_store_service_->AppendSubscriptions(
service_worker_registration_id_, std::move(subscriptions),
@@ -152,8 +151,7 @@ class CookieStoreWorkerTestHelper : public EmbeddedWorkerTestHelper {
// Used to implement WaitForActivateEvent().
void OnActivateEvent(
- mojom::ServiceWorkerEventDispatcher::DispatchActivateEventCallback
- callback) override {
+ mojom::ServiceWorker::DispatchActivateEventCallback callback) override {
if (quit_on_activate_) {
quit_on_activate_->Quit();
quit_on_activate_ = nullptr;
@@ -165,8 +163,8 @@ class CookieStoreWorkerTestHelper : public EmbeddedWorkerTestHelper {
void OnCookieChangeEvent(
const net::CanonicalCookie& cookie,
::network::mojom::CookieChangeCause cause,
- mojom::ServiceWorkerEventDispatcher::DispatchCookieChangeEventCallback
- callback) override {
+ mojom::ServiceWorker::DispatchCookieChangeEventCallback callback)
+ override {
changes_.emplace_back(cookie, cause);
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -270,13 +268,13 @@ class CookieStoreManagerTest
GURL(script_url), options,
base::BindOnce(
[](base::RunLoop* run_loop, bool* success, int64_t* registration_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t service_worker_registration_id) {
- *success = (status == SERVICE_WORKER_OK);
+ *success = (status == blink::ServiceWorkerStatusCode::kOk);
*registration_id = service_worker_registration_id;
- EXPECT_EQ(SERVICE_WORKER_OK, status)
- << ServiceWorkerStatusToString(status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
run_loop->Quit();
},
&run_loop, &success, &registration_id));
@@ -288,19 +286,8 @@ class CookieStoreManagerTest
return registration_id;
}
- // Simplified helper for SetCanonicalCookie.
- //
- // Creates a CanonicalCookie that is not secure, not http-only,
- // and not restricted to first parties. Returns false if creation fails.
- bool SetSessionCookie(const char* name,
- const char* value,
- const char* domain,
- const char* path) {
- net::CanonicalCookie cookie(
- name, value, domain, path, base::Time(), base::Time(), base::Time(),
- /* secure = */ false,
- /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION,
- net::COOKIE_PRIORITY_DEFAULT);
+ // Synchronous helper for CookieManager::SetCanonicalCookie.
+ bool SetCanonicalCookie(const net::CanonicalCookie& cookie) {
base::RunLoop run_loop;
bool success = false;
cookie_manager_->SetCanonicalCookie(
@@ -315,6 +302,21 @@ class CookieStoreManagerTest
return success;
}
+ // Simplified helper for SetCanonicalCookie.
+ //
+ // Creates a CanonicalCookie that is not secure, not http-only,
+ // and not restricted to first parties. Returns false if creation fails.
+ bool SetSessionCookie(const char* name,
+ const char* value,
+ const char* domain,
+ const char* path) {
+ return SetCanonicalCookie(net::CanonicalCookie(
+ name, value, domain, path, base::Time(), base::Time(), base::Time(),
+ /* secure = */ false,
+ /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_DEFAULT));
+ }
+
bool reset_context_during_test() const { return GetParam(); }
static constexpr const int64_t kInvalidRegistrationId = -1;
@@ -824,6 +826,58 @@ TEST_P(CookieStoreManagerTest, CookieChangeUrl) {
worker_test_helper_->changes()[0].second);
}
+TEST_P(CookieStoreManagerTest, HttpOnlyCookieChange) {
+ std::vector<CookieStoreSync::Subscriptions> batches;
+ batches.emplace_back();
+
+ CookieStoreSync::Subscriptions& subscriptions = batches.back();
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+ example_service_ptr_.get());
+ int64_t registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ ASSERT_EQ(1u, all_subscriptions_opt.value().size());
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ ASSERT_TRUE(SetCanonicalCookie(net::CanonicalCookie(
+ "cookie-name-1", "cookie-value-1", "example.com", "/", base::Time(),
+ base::Time(), base::Time(),
+ /* secure = */ false,
+ /* httponly = */ true, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_DEFAULT)));
+ thread_bundle_.RunUntilIdle();
+ EXPECT_EQ(0u, worker_test_helper_->changes().size());
+
+ worker_test_helper_->changes().clear();
+ ASSERT_TRUE(SetCanonicalCookie(net::CanonicalCookie(
+ "cookie-name-2", "cookie-value-2", "example.com", "/", base::Time(),
+ base::Time(), base::Time(),
+ /* secure = */ false,
+ /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_DEFAULT)));
+ thread_bundle_.RunUntilIdle();
+
+ ASSERT_EQ(1u, worker_test_helper_->changes().size());
+ EXPECT_EQ("cookie-name-2", worker_test_helper_->changes()[0].first.Name());
+ EXPECT_EQ("cookie-value-2", worker_test_helper_->changes()[0].first.Value());
+ EXPECT_EQ("example.com", worker_test_helper_->changes()[0].first.Domain());
+ EXPECT_EQ("/", worker_test_helper_->changes()[0].first.Path());
+ EXPECT_EQ(::network::mojom::CookieChangeCause::INSERTED,
+ worker_test_helper_->changes()[0].second);
+}
+
TEST_P(CookieStoreManagerTest, GetSubscriptionsFromWrongOrigin) {
std::vector<CookieStoreSync::Subscriptions> batches;
batches.emplace_back();
diff --git a/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc b/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc
index 86b2b534245..7eccbe6db70 100644
--- a/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc
+++ b/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc
@@ -11,6 +11,7 @@
#include "content/browser/interface_provider_filtering.h"
#include "content/browser/renderer_interface_binders.h"
#include "content/browser/websockets/websocket_manager.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/message_pipe.h"
@@ -27,10 +28,10 @@ namespace {
class DedicatedWorkerHost : public service_manager::mojom::InterfaceProvider {
public:
DedicatedWorkerHost(int process_id,
- int parent_render_frame_id,
+ int ancestor_render_frame_id,
const url::Origin& origin)
: process_id_(process_id),
- parent_render_frame_id_(parent_render_frame_id),
+ ancestor_render_frame_id_(ancestor_render_frame_id),
origin_(origin) {
RegisterMojoInterfaces();
}
@@ -53,22 +54,52 @@ class DedicatedWorkerHost : public service_manager::mojom::InterfaceProvider {
private:
void RegisterMojoInterfaces() {
- registry_.AddInterface(
- base::BindRepeating(&WebSocketManager::CreateWebSocket, process_id_,
- parent_render_frame_id_, origin_));
+ registry_.AddInterface(base::BindRepeating(
+ &DedicatedWorkerHost::CreateWebSocket, base::Unretained(this)));
registry_.AddInterface(base::BindRepeating(
&DedicatedWorkerHost::CreateUsbDeviceManager, base::Unretained(this)));
+ registry_.AddInterface(base::BindRepeating(
+ &DedicatedWorkerHost::CreateDedicatedWorker, base::Unretained(this)));
}
void CreateUsbDeviceManager(device::mojom::UsbDeviceManagerRequest request) {
auto* host =
- RenderFrameHostImpl::FromID(process_id_, parent_render_frame_id_);
+ RenderFrameHostImpl::FromID(process_id_, ancestor_render_frame_id_);
GetContentClient()->browser()->CreateUsbDeviceManager(host,
std::move(request));
}
+ void CreateWebSocket(network::mojom::WebSocketRequest request) {
+ network::mojom::AuthenticationHandlerPtr auth_handler;
+ auto* frame =
+ RenderFrameHost::FromID(process_id_, ancestor_render_frame_id_);
+ if (!frame) {
+ // In some cases |frame| can be null. In such cases the worker will
+ // soon be terminated too, so let's abort the connection.
+ request.ResetWithReason(network::mojom::WebSocket::kInsufficientResources,
+ "The parent frame has already been gone.");
+ return;
+ }
+
+ GetContentClient()->browser()->WillCreateWebSocket(frame, &request,
+ &auth_handler);
+
+ WebSocketManager::CreateWebSocket(process_id_, ancestor_render_frame_id_,
+ origin_, std::move(auth_handler),
+ std::move(request));
+ }
+
+ void CreateDedicatedWorker(
+ blink::mojom::DedicatedWorkerFactoryRequest request) {
+ CreateDedicatedWorkerHostFactory(process_id_, ancestor_render_frame_id_,
+ origin_, std::move(request));
+ }
+
const int process_id_;
- const int parent_render_frame_id_;
+ // ancestor_render_frame_id_ is the id of the frame that owns this worker,
+ // either directly, or (in the case of nested workers) indirectly via a tree
+ // of dedicated workers.
+ const int ancestor_render_frame_id_;
const url::Origin origin_;
service_manager::BinderRegistry registry_;
@@ -81,10 +112,10 @@ class DedicatedWorkerHost : public service_manager::mojom::InterfaceProvider {
class DedicatedWorkerFactoryImpl : public blink::mojom::DedicatedWorkerFactory {
public:
DedicatedWorkerFactoryImpl(int process_id,
- int parent_render_frame_id,
+ int ancestor_render_frame_id,
const url::Origin& parent_context_origin)
: process_id_(process_id),
- parent_render_frame_id_(parent_render_frame_id),
+ ancestor_render_frame_id_(ancestor_render_frame_id),
parent_context_origin_(parent_context_origin) {}
// blink::mojom::DedicatedWorkerFactory:
@@ -95,7 +126,7 @@ class DedicatedWorkerFactoryImpl : public blink::mojom::DedicatedWorkerFactory {
// with the request for |DedicatedWorkerFactory|, enforce that the worker's
// origin either matches the creating document's origin, or is unique.
mojo::MakeStrongBinding(std::make_unique<DedicatedWorkerHost>(
- process_id_, parent_render_frame_id_, origin),
+ process_id_, ancestor_render_frame_id_, origin),
FilterRendererExposedInterfaces(
blink::mojom::kNavigation_DedicatedWorkerSpec,
process_id_, std::move(request)));
@@ -103,7 +134,7 @@ class DedicatedWorkerFactoryImpl : public blink::mojom::DedicatedWorkerFactory {
private:
const int process_id_;
- const int parent_render_frame_id_;
+ const int ancestor_render_frame_id_;
const url::Origin parent_context_origin_;
DISALLOW_COPY_AND_ASSIGN(DedicatedWorkerFactoryImpl);
@@ -113,11 +144,11 @@ class DedicatedWorkerFactoryImpl : public blink::mojom::DedicatedWorkerFactory {
void CreateDedicatedWorkerHostFactory(
int process_id,
- int parent_render_frame_id,
+ int ancestor_render_frame_id,
const url::Origin& origin,
blink::mojom::DedicatedWorkerFactoryRequest request) {
mojo::MakeStrongBinding(std::make_unique<DedicatedWorkerFactoryImpl>(
- process_id, parent_render_frame_id, origin),
+ process_id, ancestor_render_frame_id, origin),
std::move(request));
}
diff --git a/chromium/content/browser/device_sensors/device_sensor_browsertest.cc b/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
index 494c1c7acc1..2829fe11923 100644
--- a/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
+++ b/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
@@ -9,7 +9,6 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "components/network_session_configurator/common/network_switches.h"
@@ -44,10 +43,20 @@ using device::FakeSensorProvider;
class DeviceSensorBrowserTest : public ContentBrowserTest {
public:
- DeviceSensorBrowserTest()
- : io_loop_finished_event_(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED) {}
+ DeviceSensorBrowserTest() {
+ // Because Device Service also runs in this process (browser process), here
+ // we can directly set our binder to intercept interface requests against
+ // it.
+ service_manager::ServiceContext::SetGlobalBinderForTesting(
+ device::mojom::kServiceName, device::mojom::SensorProvider::Name_,
+ base::BindRepeating(&DeviceSensorBrowserTest::Bind,
+ base::Unretained(this)));
+ }
+
+ ~DeviceSensorBrowserTest() override {
+ service_manager::ServiceContext::ClearGlobalBindersForTesting(
+ device::mojom::kServiceName);
+ }
void SetUpOnMainThread() override {
https_embedded_test_server_.reset(
@@ -66,11 +75,6 @@ class DeviceSensorBrowserTest : public ContentBrowserTest {
sensor_provider_->SetGyroscopeData(7, 8, 9);
sensor_provider_->SetRelativeOrientationSensorData(1, 2, 3);
sensor_provider_->SetAbsoluteOrientationSensorData(4, 5, 6);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&DeviceSensorBrowserTest::SetUpOnIOThread,
- base::Unretained(this)));
- io_loop_finished_event_.Wait();
}
void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -79,17 +83,6 @@ class DeviceSensorBrowserTest : public ContentBrowserTest {
command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
}
- void SetUpOnIOThread() {
- // Because Device Service also runs in this process(browser process), here
- // we can directly set our binder to intercept interface requests against
- // it.
- service_manager::ServiceContext::SetGlobalBinderForTesting(
- device::mojom::kServiceName, device::mojom::SensorProvider::Name_,
- base::Bind(&DeviceSensorBrowserTest::Bind, base::Unretained(this)));
-
- io_loop_finished_event_.Signal();
- }
-
void DelayAndQuit(base::TimeDelta delay) {
base::PlatformThread::Sleep(delay);
base::RunLoop::QuitCurrentWhenIdleDeprecated();
@@ -117,8 +110,6 @@ class DeviceSensorBrowserTest : public ContentBrowserTest {
sensor_provider_->Bind(
device::mojom::SensorProviderRequest(std::move(handle)));
}
-
- base::WaitableEvent io_loop_finished_event_;
};
IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, OrientationTest) {
@@ -364,7 +355,7 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest,
"The deviceorientationabsolute events are blocked by "
"feature policy. See "
"https://github.com/WICG/feature-policy/blob/"
- "gh-pages/features.md#sensor-features";
+ "master/features.md#sensor-features";
auto console_delegate = std::make_unique<ConsoleObserverDelegate>(
shell()->web_contents(), kWarningMessage);
diff --git a/chromium/content/browser/devtools/README.md b/chromium/content/browser/devtools/README.md
new file mode 100644
index 00000000000..e0315182b14
--- /dev/null
+++ b/chromium/content/browser/devtools/README.md
@@ -0,0 +1,3 @@
+# Chrome DevTools Protocol
+
+Contributing to Chrome DevTools Protocol: [docs.google.com](https://docs.google.com/document/d/1c-COD2kaK__5iMM5SEx-PzNA7HFmgttcYfOHHX0HaOM/edit?usp=sharing).
diff --git a/chromium/content/browser/devtools/browser_devtools_agent_host.cc b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
index bd0c4705380..5bdec4f820f 100644
--- a/chromium/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/guid.h"
+#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "content/browser/devtools/devtools_session.h"
@@ -18,6 +19,7 @@
#include "content/browser/devtools/protocol/target_handler.h"
#include "content/browser/devtools/protocol/tethering_handler.h"
#include "content/browser/devtools/protocol/tracing_handler.h"
+#include "content/browser/devtools/target_registry.h"
#include "content/browser/frame_host/frame_tree_node.h"
namespace content {
@@ -48,30 +50,40 @@ BrowserDevToolsAgentHost::BrowserDevToolsAgentHost(
BrowserDevToolsAgentHost::~BrowserDevToolsAgentHost() {
}
-bool BrowserDevToolsAgentHost::AttachSession(DevToolsSession* session) {
+bool BrowserDevToolsAgentHost::AttachSession(DevToolsSession* session,
+ TargetRegistry* parent_registry) {
if (session->restricted())
return false;
+ TargetRegistry* registry = parent_registry;
+ if (!registry) {
+ auto new_registry = std::make_unique<TargetRegistry>(session);
+ registry = new_registry.get();
+ target_registries_[session->client()] = std::move(new_registry);
+ }
session->SetBrowserOnly(true);
- session->AddHandler(
- base::WrapUnique(new protocol::TargetHandler(true /* browser_only */)));
+ session->AddHandler(std::make_unique<protocol::TargetHandler>(
+ true /* browser_only */, GetId(), registry));
if (only_discovery_)
return true;
- session->AddHandler(base::WrapUnique(new protocol::BrowserHandler()));
- session->AddHandler(base::WrapUnique(new protocol::IOHandler(
- GetIOContext())));
- session->AddHandler(base::WrapUnique(new protocol::MemoryHandler()));
- session->AddHandler(base::WrapUnique(new protocol::SecurityHandler()));
- session->AddHandler(base::WrapUnique(new protocol::SystemInfoHandler()));
- session->AddHandler(base::WrapUnique(new protocol::TetheringHandler(
- socket_callback_, tethering_task_runner_)));
+ session->AddHandler(std::make_unique<protocol::BrowserHandler>());
+ session->AddHandler(std::make_unique<protocol::IOHandler>(GetIOContext()));
+ session->AddHandler(std::make_unique<protocol::MemoryHandler>());
+ session->AddHandler(std::make_unique<protocol::SecurityHandler>());
+ session->AddHandler(std::make_unique<protocol::SystemInfoHandler>());
+ if (tethering_task_runner_) {
+ session->AddHandler(std::make_unique<protocol::TetheringHandler>(
+ socket_callback_, tethering_task_runner_));
+ }
session->AddHandler(
- base::WrapUnique(new protocol::TracingHandler(nullptr, GetIOContext())));
+ std::make_unique<protocol::TracingHandler>(nullptr, GetIOContext()));
return true;
}
-void BrowserDevToolsAgentHost::DetachSession(DevToolsSession* session) {}
+void BrowserDevToolsAgentHost::DetachSession(DevToolsSession* session) {
+ target_registries_.erase(session->client());
+}
std::string BrowserDevToolsAgentHost::GetType() {
return kTypeBrowser;
@@ -96,10 +108,17 @@ bool BrowserDevToolsAgentHost::Close() {
void BrowserDevToolsAgentHost::Reload() {
}
-void BrowserDevToolsAgentHost::DispatchProtocolMessage(
- DevToolsSession* session,
- const std::string& message) {
- session->DispatchProtocolMessage(message);
+bool BrowserDevToolsAgentHost::DispatchProtocolMessage(
+ DevToolsAgentHostClient* client,
+ const std::string& message,
+ base::DictionaryValue* parsed_message) {
+ auto it = target_registries_.find(client);
+ if (it != target_registries_.end() &&
+ it->second->DispatchMessageOnAgentHost(message, parsed_message)) {
+ return true;
+ }
+ return DevToolsAgentHostImpl::DispatchProtocolMessage(client, message,
+ parsed_message);
}
} // content
diff --git a/chromium/content/browser/devtools/browser_devtools_agent_host.h b/chromium/content/browser/devtools/browser_devtools_agent_host.h
index 7022e2d167c..29963484035 100644
--- a/chromium/content/browser/devtools/browser_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/browser_devtools_agent_host.h
@@ -5,10 +5,13 @@
#ifndef CONTENT_BROWSER_DEVTOOLS_BROWSER_DEVTOOLS_AGENT_HOST_H_
#define CONTENT_BROWSER_DEVTOOLS_BROWSER_DEVTOOLS_AGENT_HOST_H_
+#include "base/containers/flat_map.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
namespace content {
+class TargetRegistry;
+
class BrowserDevToolsAgentHost : public DevToolsAgentHostImpl {
private:
friend class DevToolsAgentHost;
@@ -18,11 +21,13 @@ class BrowserDevToolsAgentHost : public DevToolsAgentHostImpl {
bool only_discovery);
~BrowserDevToolsAgentHost() override;
- // DevToolsAgentHostImpl implementation.
- bool AttachSession(DevToolsSession* session) override;
+ // DevToolsAgentHostImpl overrides.
+ bool AttachSession(DevToolsSession* session,
+ TargetRegistry* registry) override;
void DetachSession(DevToolsSession* session) override;
- void DispatchProtocolMessage(DevToolsSession* session,
- const std::string& message) override;
+ bool DispatchProtocolMessage(DevToolsAgentHostClient* client,
+ const std::string& message,
+ base::DictionaryValue* parsed_message) override;
// DevToolsAgentHost implementation.
std::string GetType() override;
@@ -35,6 +40,8 @@ class BrowserDevToolsAgentHost : public DevToolsAgentHostImpl {
scoped_refptr<base::SingleThreadTaskRunner> tethering_task_runner_;
CreateServerSocketCallback socket_callback_;
bool only_discovery_;
+ base::flat_map<DevToolsAgentHostClient*, std::unique_ptr<TargetRegistry>>
+ target_registries_;
};
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.cc b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
index a67148429f1..273ca40034c 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
#include "base/observer_list.h"
@@ -176,12 +177,13 @@ DevToolsSession* DevToolsAgentHostImpl::SessionByClient(
}
bool DevToolsAgentHostImpl::InnerAttachClient(DevToolsAgentHostClient* client,
+ TargetRegistry* registry,
bool restricted) {
scoped_refptr<DevToolsAgentHostImpl> protect(this);
DevToolsSession* session = new DevToolsSession(this, client, restricted);
sessions_.insert(session);
session_by_client_[client].reset(session);
- if (!AttachSession(session)) {
+ if (!AttachSession(session, registry)) {
sessions_.erase(session);
session_by_client_.erase(client);
return false;
@@ -198,14 +200,22 @@ bool DevToolsAgentHostImpl::InnerAttachClient(DevToolsAgentHostClient* client,
void DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) {
if (SessionByClient(client))
return;
- InnerAttachClient(client, false /* restricted */);
+ InnerAttachClient(client, nullptr, false /* restricted */);
+}
+
+void DevToolsAgentHostImpl::AttachSubtargetClient(
+ DevToolsAgentHostClient* client,
+ TargetRegistry* registry) {
+ if (SessionByClient(client))
+ return;
+ InnerAttachClient(client, registry, false /* restricted */);
}
bool DevToolsAgentHostImpl::AttachRestrictedClient(
DevToolsAgentHostClient* client) {
if (SessionByClient(client))
return false;
- return InnerAttachClient(client, true /* restricted */);
+ return InnerAttachClient(client, nullptr, true /* restricted */);
}
bool DevToolsAgentHostImpl::DetachClient(DevToolsAgentHostClient* client) {
@@ -220,16 +230,29 @@ bool DevToolsAgentHostImpl::DetachClient(DevToolsAgentHostClient* client) {
bool DevToolsAgentHostImpl::DispatchProtocolMessage(
DevToolsAgentHostClient* client,
const std::string& message) {
+ std::unique_ptr<base::Value> value = base::JSONReader::Read(message);
+ if (value && !value->is_dict())
+ value.reset();
+ return DispatchProtocolMessage(
+ client, message, static_cast<base::DictionaryValue*>(value.get()));
+}
+
+bool DevToolsAgentHostImpl::DispatchProtocolMessage(
+ DevToolsAgentHostClient* client,
+ const std::string& message,
+ base::DictionaryValue* parsed_message) {
DevToolsSession* session = SessionByClient(client);
if (!session)
return false;
- DispatchProtocolMessage(session, message);
+ session->DispatchProtocolMessage(message, parsed_message);
return true;
}
void DevToolsAgentHostImpl::InnerDetachClient(DevToolsAgentHostClient* client) {
std::unique_ptr<DevToolsSession> session =
std::move(session_by_client_[client]);
+ // Make sure we dispose session prior to reporting it to the host.
+ session->Dispose();
sessions_.erase(session.get());
session_by_client_.erase(client);
DetachSession(session.get());
@@ -310,32 +333,24 @@ void DevToolsAgentHostImpl::ForceDetachAllSessions() {
}
}
-void DevToolsAgentHostImpl::ForceDetachRestrictedSessions() {
- if (sessions_.empty())
- return;
+void DevToolsAgentHostImpl::ForceDetachRestrictedSessions(
+ const std::vector<DevToolsSession*>& restricted_sessions) {
scoped_refptr<DevToolsAgentHostImpl> protect(this);
- std::vector<DevToolsSession*> restricted;
- for (DevToolsSession* session : sessions_) {
- if (session->restricted())
- restricted.push_back(session);
- }
- for (DevToolsSession* session : restricted) {
+
+ for (DevToolsSession* session : restricted_sessions) {
DevToolsAgentHostClient* client = session->client();
DetachClient(client);
client->AgentHostClosed(this);
}
}
-bool DevToolsAgentHostImpl::AttachSession(DevToolsSession* session) {
+bool DevToolsAgentHostImpl::AttachSession(DevToolsSession* session,
+ TargetRegistry* registry) {
return false;
}
void DevToolsAgentHostImpl::DetachSession(DevToolsSession* session) {}
-void DevToolsAgentHostImpl::DispatchProtocolMessage(
- DevToolsSession* session,
- const std::string& message) {}
-
// static
void DevToolsAgentHost::DetachAllClients() {
if (!g_devtools_instances.IsCreated())
@@ -343,11 +358,14 @@ void DevToolsAgentHost::DetachAllClients() {
// Make a copy, since detaching may lead to agent destruction, which
// removes it from the instances.
- DevToolsMap copy = g_devtools_instances.Get();
- for (DevToolsMap::iterator it(copy.begin()); it != copy.end(); ++it) {
- DevToolsAgentHostImpl* agent_host = it->second;
- agent_host->ForceDetachAllSessions();
- }
+ std::vector<scoped_refptr<DevToolsAgentHostImpl>> copy;
+ for (DevToolsMap::iterator it(g_devtools_instances.Get().begin());
+ it != g_devtools_instances.Get().end(); ++it)
+ copy.push_back(it->second);
+ for (std::vector<scoped_refptr<DevToolsAgentHostImpl>>::iterator it(
+ copy.begin());
+ it != copy.end(); ++it)
+ it->get()->ForceDetachAllSessions();
}
// static
@@ -400,6 +418,11 @@ void DevToolsAgentHostImpl::NotifyDetached() {
observer.DevToolsAgentHostDetached(this);
}
+void DevToolsAgentHostImpl::NotifyCrashed(base::TerminationStatus status) {
+ for (auto& observer : g_devtools_observers.Get())
+ observer.DevToolsAgentHostCrashed(this, status);
+}
+
void DevToolsAgentHostImpl::NotifyDestroyed() {
DCHECK(g_devtools_instances.Get().find(id_) !=
g_devtools_instances.Get().end());
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.h b/chromium/content/browser/devtools/devtools_agent_host_impl.h
index 6831704222e..b258f840c9b 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.h
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.h
@@ -12,6 +12,7 @@
#include "base/compiler_specific.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
+#include "base/process/kill.h"
#include "content/browser/devtools/devtools_io_context.h"
#include "content/common/content_export.h"
#include "content/public/browser/certificate_request_result_type.h"
@@ -22,6 +23,7 @@ namespace content {
class BrowserContext;
class DevToolsSession;
+class TargetRegistry;
// Describes interface for managing devtools agents from the browser process.
class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
@@ -64,29 +66,42 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
static bool ShouldForceCreation();
// Returning |false| will block the attach.
- virtual bool AttachSession(DevToolsSession* session);
+ virtual bool AttachSession(DevToolsSession* session,
+ TargetRegistry* registry);
virtual void DetachSession(DevToolsSession* session);
- virtual void DispatchProtocolMessage(DevToolsSession* session,
- const std::string& message);
+
+ virtual bool DispatchProtocolMessage(DevToolsAgentHostClient* client,
+ const std::string& message,
+ base::DictionaryValue* parsed_message);
void NotifyCreated();
void NotifyNavigated();
+ void NotifyCrashed(base::TerminationStatus status);
void ForceDetachAllSessions();
- void ForceDetachRestrictedSessions();
+ void ForceDetachRestrictedSessions(
+ const std::vector<DevToolsSession*>& restricted_sessions);
DevToolsIOContext* GetIOContext() { return &io_context_; }
base::flat_set<DevToolsSession*>& sessions() { return sessions_; }
private:
- friend class DevToolsAgentHost; // for static methods
+ friend class DevToolsAgentHost; // for static methods
friend class DevToolsSession;
- bool InnerAttachClient(DevToolsAgentHostClient* client, bool restricted);
+ friend class TargetRegistry; // for subtarget management
+
+ bool InnerAttachClient(DevToolsAgentHostClient* client,
+ TargetRegistry* registry,
+ bool restricted);
void InnerDetachClient(DevToolsAgentHostClient* client);
void NotifyAttached();
void NotifyDetached();
void NotifyDestroyed();
DevToolsSession* SessionByClient(DevToolsAgentHostClient* client);
+ // TargetRegistry API for subtarget management.
+ void AttachSubtargetClient(DevToolsAgentHostClient* client,
+ TargetRegistry* registry);
+
const std::string id_;
base::flat_set<DevToolsSession*> sessions_;
base::flat_map<DevToolsAgentHostClient*, std::unique_ptr<DevToolsSession>>
diff --git a/chromium/content/browser/devtools/devtools_http_handler.cc b/chromium/content/browser/devtools/devtools_http_handler.cc
index c9187e77495..eaf44246e9e 100644
--- a/chromium/content/browser/devtools/devtools_http_handler.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler.cc
@@ -289,7 +289,10 @@ void StartServerOnHandlerThread(
}
}
} else {
- LOG(ERROR) << "Cannot start http server for devtools. Stop devtools.";
+#if !defined(OS_ANDROID)
+ // Android uses UNIX domain sockets which don't have an IP address.
+ LOG(ERROR) << "Cannot start http server for devtools.";
+#endif
}
BrowserThread::PostTask(
diff --git a/chromium/content/browser/devtools/devtools_manager_unittest.cc b/chromium/content/browser/devtools/devtools_manager_unittest.cc
index b945b03f214..affaef82158 100644
--- a/chromium/content/browser/devtools/devtools_manager_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_manager_unittest.cc
@@ -4,7 +4,10 @@
#include "content/browser/devtools/devtools_manager.h"
+#include <map>
#include <memory>
+#include <string>
+#include <utility>
#include "base/guid.h"
#include "base/location.h"
@@ -84,8 +87,10 @@ class TestWebContentsDelegate : public WebContentsDelegate {
TestWebContentsDelegate() : renderer_unresponsive_received_(false) {}
// Notification that the contents is hung.
- void RendererUnresponsive(WebContents* source,
- RenderWidgetHost* render_widget_host) override {
+ void RendererUnresponsive(
+ WebContents* source,
+ RenderWidgetHost* render_widget_host,
+ base::RepeatingClosure hang_monitor_restarter) override {
renderer_unresponsive_received_ = true;
}
@@ -141,25 +146,32 @@ TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) {
client_host.InspectAgentHost(agent_host.get());
// Start with a short timeout.
- inspected_rvh->GetWidget()->StartHangMonitorTimeout(
+ inspected_rvh->GetWidget()->StartInputEventAckTimeout(
TimeDelta::FromMilliseconds(10));
- // Wait long enough for first timeout and see if it fired.
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMilliseconds(10));
- base::RunLoop().Run();
+ {
+ base::RunLoop run_loop;
+ // Wait long enough for first timeout and see if it fired. We use quit-when-
+ // idle so that all tasks due after the timeout get a chance to run.
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitWhenIdleClosure(),
+ TimeDelta::FromMilliseconds(10));
+ run_loop.Run();
+ }
EXPECT_FALSE(delegate.renderer_unresponsive_received());
// Now close devtools and check that the notification is delivered.
client_host.Close();
// Start with a short timeout.
- inspected_rvh->GetWidget()->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(10));
- // Wait long enough for first timeout and see if it fired.
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
+ inspected_rvh->GetWidget()->StartInputEventAckTimeout(
TimeDelta::FromMilliseconds(10));
- base::RunLoop().Run();
+ {
+ base::RunLoop run_loop;
+ // Wait long enough for first timeout and see if it fired.
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitWhenIdleClosure(),
+ TimeDelta::FromMilliseconds(10));
+ run_loop.Run();
+ }
EXPECT_TRUE(delegate.renderer_unresponsive_received());
contents()->SetDelegate(nullptr);
@@ -178,7 +190,7 @@ class TestExternalAgentDelegate: public DevToolsExternalAgentProxyDelegate {
}
private:
- std::map<std::string,int> event_counter_;
+ std::map<std::string, int> event_counter_;
void recordEvent(const std::string& name) {
if (event_counter_.find(name) == event_counter_.end())
@@ -213,7 +225,6 @@ class TestExternalAgentDelegate: public DevToolsExternalAgentProxyDelegate {
const std::string& message) override {
recordEvent(std::string("SendMessageToBackend.") + message);
};
-
};
TEST_F(DevToolsManagerTest, TestExternalProxy) {
diff --git a/chromium/content/browser/devtools/devtools_pipe_handler.cc b/chromium/content/browser/devtools/devtools_pipe_handler.cc
index 4fbea246102..dcdce1fe0ef 100644
--- a/chromium/content/browser/devtools/devtools_pipe_handler.cc
+++ b/chromium/content/browser/devtools/devtools_pipe_handler.cc
@@ -66,9 +66,9 @@ void WriteIntoPipe(int write_fd, const std::string& message) {
}
#if defined(OS_WIN)
DWORD result = 0;
- WriteFile(handle, "\n", 1, &result, nullptr);
+ WriteFile(handle, "\0", 1, &result, nullptr);
#else
- int result = write(write_fd, "\n", 1);
+ int result = write(write_fd, "\0", 1);
#endif
if (!result) {
LOG(ERROR) << "Could not write into pipe";
@@ -145,11 +145,11 @@ bool PipeReader::HandleReadResult(int result) {
read_buffer_->DidRead(result);
- // Go over the last read chunk, look for \n, extract messages.
+ // Go over the last read chunk, look for \0, extract messages.
int offset = 0;
for (int i = read_buffer_->GetSize() - result; i < read_buffer_->GetSize();
++i) {
- if (read_buffer_->StartOfBuffer()[i] == '\n') {
+ if (read_buffer_->StartOfBuffer()[i] == '\0') {
std::string str(read_buffer_->StartOfBuffer() + offset, i - offset);
BrowserThread::PostTask(
@@ -190,7 +190,8 @@ DevToolsPipeHandler::DevToolsPipeHandler()
return;
}
- browser_target_ = DevToolsAgentHost::CreateForDiscovery();
+ browser_target_ = DevToolsAgentHost::CreateForBrowser(
+ nullptr, DevToolsAgentHost::CreateServerSocketCallback());
browser_target_->AttachClient(this);
pipe_reader_.reset(new PipeReader(weak_factory_.GetWeakPtr(), read_fd_));
diff --git a/chromium/content/browser/devtools/devtools_session.cc b/chromium/content/browser/devtools/devtools_session.cc
index 10a84a5ef0a..a82213afc24 100644
--- a/chromium/content/browser/devtools/devtools_session.cc
+++ b/chromium/content/browser/devtools/devtools_session.cc
@@ -46,6 +46,13 @@ DevToolsSession::DevToolsSession(DevToolsAgentHostImpl* agent_host,
}
DevToolsSession::~DevToolsSession() {
+ // It is Ok for session to be deleted without the dispose -
+ // it can be kicked out by an extension connect / disconnect.
+ if (dispatcher_)
+ Dispose();
+}
+
+void DevToolsSession::Dispose() {
dispatcher_.reset();
for (auto& pair : handlers_)
pair.second->Disable();
@@ -116,22 +123,19 @@ void DevToolsSession::MojoConnectionDestroyed() {
io_session_ptr_.reset();
}
-void DevToolsSession::DispatchProtocolMessage(const std::string& message) {
- std::unique_ptr<base::Value> value = base::JSONReader::Read(message);
-
+void DevToolsSession::DispatchProtocolMessage(
+ const std::string& message,
+ base::DictionaryValue* parsed_message) {
DevToolsManagerDelegate* delegate =
DevToolsManager::GetInstance()->delegate();
- if (value && value->is_dict() && delegate) {
- base::DictionaryValue* dict_value =
- static_cast<base::DictionaryValue*>(value.get());
-
- if (delegate->HandleCommand(agent_host_, client_, dict_value))
- return;
+ if (delegate && parsed_message &&
+ delegate->HandleCommand(agent_host_, client_, parsed_message)) {
+ return;
}
int call_id;
std::string method;
- if (dispatcher_->dispatch(protocol::toProtocolValue(value.get(), 1000),
+ if (dispatcher_->dispatch(protocol::toProtocolValue(parsed_message, 1000),
&call_id,
&method) != protocol::Response::kFallThrough) {
return;
diff --git a/chromium/content/browser/devtools/devtools_session.h b/chromium/content/browser/devtools/devtools_session.h
index 9ae28ad0097..2b2bccf785b 100644
--- a/chromium/content/browser/devtools/devtools_session.h
+++ b/chromium/content/browser/devtools/devtools_session.h
@@ -28,8 +28,10 @@ class DevToolsSession : public protocol::FrontendChannel,
DevToolsAgentHostClient* client,
bool restricted);
~DevToolsSession() override;
+ void Dispose();
bool restricted() { return restricted_; }
+ DevToolsAgentHost* agent_host() { return agent_host_; };
DevToolsAgentHostClient* client() { return client_; };
// Browser-only sessions do not talk to mojom::DevToolsAgent, but instead
@@ -41,7 +43,8 @@ class DevToolsSession : public protocol::FrontendChannel,
void SetRenderer(int process_host_id, RenderFrameHostImpl* frame_host);
void AttachToAgent(const blink::mojom::DevToolsAgentAssociatedPtr& agent);
- void DispatchProtocolMessage(const std::string& message);
+ void DispatchProtocolMessage(const std::string& message,
+ base::DictionaryValue* parsed_message);
void SuspendSendingMessagesToAgent();
void ResumeSendingMessagesToAgent();
diff --git a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
index abfa5795a0c..65329798837 100644
--- a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
+++ b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
@@ -9,7 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/devtools/protocol/network_handler.h"
#include "content/browser/devtools/protocol/page.h"
-#include "content/browser/loader/navigation_loader_util.h"
+#include "content/browser/loader/download_utils_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "ipc/ipc_channel.h"
#include "net/base/completion_once_callback.h"
@@ -18,12 +18,13 @@
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_element_reader.h"
#include "net/cert/cert_status_flags.h"
+#include "net/cookies/cookie_options.h"
+#include "net/cookies/cookie_store.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request_context.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
-
namespace {
static const int kInitialBufferSize = 4096;
static const int kMaxBufferSize = IPC::Channel::kMaximumMessageSize / 4;
@@ -105,8 +106,8 @@ DevToolsURLInterceptorRequestJob::SubRequest::SubRequest(
"This feature cannot be disabled in settings, however it happens "
"only when user is debugging a page."
chrome_policy {
- DeveloperToolsDisabled {
- DeveloperToolsDisabled: true
+ DeveloperToolsAvailability {
+ DeveloperToolsAvailability: 2
}
}
})");
@@ -551,8 +552,8 @@ bool IsDownload(net::URLRequest* orig_request, net::URLRequest* subrequest) {
std::string mime_type;
subrequest->GetMimeType(&mime_type);
return req_info->allow_download() &&
- navigation_loader_util::IsDownload(
- orig_request->url(), subrequest->response_headers(), mime_type);
+ download_utils::IsDownload(orig_request->url(),
+ subrequest->response_headers(), mime_type);
}
} // namespace
@@ -605,6 +606,30 @@ void DevToolsURLInterceptorRequestJob::SetExtraRequestHeaders(
void DevToolsURLInterceptorRequestJob::Start() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ auto* store = request_details_.url_request_context->cookie_store();
+ if (!store || (request()->load_flags() & net::LOAD_DO_NOT_SEND_COOKIES)) {
+ StartWithCookies(net::CookieList());
+ return;
+ }
+
+ net::CookieOptions options;
+ options.set_include_httponly();
+ if (request()->attach_same_site_cookies()) {
+ options.set_same_site_cookie_mode(
+ net::CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ }
+ store->GetCookieListWithOptionsAsync(
+ request_details_.url, options,
+ base::BindOnce(&DevToolsURLInterceptorRequestJob::StartWithCookies,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void DevToolsURLInterceptorRequestJob::StartWithCookies(
+ const net::CookieList& cookie_list) {
+ request_details_.cookie_line =
+ net::CanonicalCookie::BuildCookieLine(cookie_list);
+
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (stage_to_intercept_ == InterceptionStage::DONT_INTERCEPT) {
sub_request_.reset(new SubRequest(request_details_, this, interceptor_));
return;
@@ -1057,7 +1082,8 @@ DevToolsURLInterceptorRequestJob::BuildRequestInfo() {
auto result = std::make_unique<InterceptedRequestInfo>();
result->interception_id = interception_id_;
result->network_request =
- protocol::NetworkHandler::CreateRequestFromURLRequest(request());
+ protocol::NetworkHandler::CreateRequestFromURLRequest(
+ request(), request_details_.cookie_line);
result->frame_id = devtools_token_;
result->resource_type = resource_type_;
result->is_navigation =
@@ -1086,7 +1112,7 @@ void DevToolsURLInterceptorRequestJob::ProcessInterceptionResponse(
// far, to minimize risk of breaking other usages.
ResourceRequestInfoImpl* resource_request_info =
ResourceRequestInfoImpl::ForRequest(request());
- resource_request_info->set_resource_request_blocked_reason(
+ resource_request_info->SetResourceRequestBlockedReason(
blink::ResourceRequestBlockedReason::kInspector);
}
NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
@@ -1103,6 +1129,33 @@ void DevToolsURLInterceptorRequestJob::ProcessInterceptionResponse(
interceptor_->ExpectRequestAfterRedirect(request(), interception_id_);
}
+ // Set cookies in the network stack.
+ net::CookieOptions options;
+ options.set_include_httponly();
+ base::Time response_date;
+ if (!mock_response_details_->response_headers()->GetDateValue(
+ &response_date)) {
+ response_date = base::Time();
+ }
+ options.set_server_time(response_date);
+
+ const base::StringPiece name("Set-Cookie");
+ std::string cookie_line;
+ size_t iter = 0;
+ while (mock_response_details_->response_headers()->EnumerateHeader(
+ &iter, name, &cookie_line)) {
+ std::unique_ptr<net::CanonicalCookie> cookie =
+ net::CanonicalCookie::Create(request_details_.url, cookie_line,
+ base::Time::Now(), options);
+ if (!cookie)
+ continue;
+
+ auto* store = request_details_.url_request_context->cookie_store();
+ store->SetCanonicalCookieAsync(
+ std::move(cookie), request_details_.url.SchemeIsCryptographic(),
+ !options.exclude_httponly(), net::CookieStore::SetCookiesCallback());
+ }
+
if (sub_request_) {
sub_request_->Cancel();
sub_request_.reset();
diff --git a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
index 48e7a7bde39..e7531a1d79d 100644
--- a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
+++ b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
@@ -12,6 +12,7 @@
#include "content/browser/devtools/protocol/network.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/resource_type.h"
+#include "net/cookies/canonical_cookie.h"
#include "net/http/http_raw_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
@@ -104,6 +105,7 @@ class DevToolsURLInterceptorRequestJob : public net::URLRequestJob {
GURL url;
std::string method;
std::unique_ptr<net::UploadDataStream> post_data;
+ std::string cookie_line;
net::HttpRequestHeaders extra_request_headers;
std::string referrer;
net::URLRequest::ReferrerPolicy referrer_policy;
@@ -111,6 +113,8 @@ class DevToolsURLInterceptorRequestJob : public net::URLRequestJob {
const net::URLRequestContext* url_request_context;
};
+ void StartWithCookies(const net::CookieList& cookies);
+
// Callbacks from SubRequest.
void OnSubRequestAuthRequired(net::AuthChallengeInfo* auth_info);
void OnSubRequestRedirectReceived(const net::URLRequest& request,
diff --git a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
index bc91e2d6d59..6d4201baf6d 100644
--- a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
+++ b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -10,7 +10,7 @@
#include "base/unguessable_token.h"
#include "content/browser/devtools/protocol/network_handler.h"
#include "content/browser/frame_host/frame_tree_node.h"
-#include "content/browser/loader/navigation_loader_util.h"
+#include "content/browser/loader/download_utils_impl.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
@@ -151,7 +151,6 @@ struct ResponseMetadata {
network::ResourceResponseHead head;
std::unique_ptr<net::RedirectInfo> redirect_info;
- network::mojom::DownloadedTempFilePtr downloaded_file;
std::vector<uint8_t> cached_metadata;
size_t encoded_length = 0;
size_t transfer_size = 0;
@@ -229,7 +228,9 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
}
// network::mojom::URLLoader methods
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
@@ -238,12 +239,9 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
void ResumeReadingBodyFromNet() override;
// network::mojom::URLLoaderClient methods
- void OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override;
+ void OnReceiveResponse(const network::ResourceResponseHead& head) override;
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) override;
- void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override;
@@ -336,7 +334,9 @@ class DevToolsURLLoaderInterceptor::Impl
InterceptionStage GetInterceptionStage(const GURL& url,
ResourceType resource_type) const {
InterceptionStage stage = InterceptionStage::DONT_INTERCEPT;
- std::string url_str = protocol::NetworkHandler::ClearUrlRef(url).spec();
+ std::string unused;
+ std::string url_str =
+ protocol::NetworkHandler::ExtractFragment(url, &unused);
for (const auto& pattern : patterns_) {
if (pattern.Matches(url_str, resource_type))
stage |= pattern.interception_stage;
@@ -818,8 +818,7 @@ Response InterceptionJob::InnerContinueRequest(
// TODO(caseq): report error if other modifications are present.
DCHECK_EQ(State::kResponseReceived, state_);
DCHECK(!body_reader_);
- client_->OnReceiveResponse(response_metadata_->head,
- std::move(response_metadata_->downloaded_file));
+ client_->OnReceiveResponse(response_metadata_->head);
response_metadata_.reset();
loader_->ResumeReadingBodyFromNet();
client_binding_.ResumeIncomingMethodCallProcessing();
@@ -962,7 +961,7 @@ Response InterceptionJob::ProcessRedirectByClient(const std::string& location) {
first_party_url_policy, request.referrer_policy,
request.referrer.spec(), &headers, headers.response_code(),
redirect_url, false /* token_binding_negotiated */,
- false /* copy_fragment */));
+ false /* insecure_scheme_was_upgraded */, false /* copy_fragment */));
client_->OnReceiveRedirect(*response_metadata_->redirect_info,
response_metadata_->head);
@@ -970,8 +969,7 @@ Response InterceptionJob::ProcessRedirectByClient(const std::string& location) {
}
void InterceptionJob::SendResponse(const base::StringPiece& body) {
- client_->OnReceiveResponse(response_metadata_->head,
- std::move(response_metadata_->downloaded_file));
+ client_->OnReceiveResponse(response_metadata_->head);
// We shouldn't be able to transfer a string that big over the protocol,
// but just in case...
@@ -1086,6 +1084,8 @@ void InterceptionJob::Shutdown() {
// URLLoader methods
void InterceptionJob::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
"headers was not supported "
@@ -1106,7 +1106,7 @@ void InterceptionJob::FollowRedirect(
}
if (state_ == State::kRedirectReceived) {
state_ = State::kRequestSent;
- loader_->FollowRedirect(base::nullopt);
+ loader_->FollowRedirect(base::nullopt, base::nullopt);
return;
}
@@ -1138,25 +1138,23 @@ void InterceptionJob::ResumeReadingBodyFromNet() {
// URLLoaderClient methods
void InterceptionJob::OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
+ const network::ResourceResponseHead& head) {
state_ = State::kResponseReceived;
DCHECK(!response_metadata_);
if (!(stage_ & InterceptionStage::RESPONSE)) {
- client_->OnReceiveResponse(head, std::move(downloaded_file));
+ client_->OnReceiveResponse(head);
return;
}
loader_->PauseReadingBodyFromNet();
client_binding_.PauseIncomingMethodCallProcessing();
response_metadata_ = std::make_unique<ResponseMetadata>(head);
- response_metadata_->downloaded_file = std::move(downloaded_file);
auto request_info = BuildRequestInfo(&head);
const network::ResourceRequest& request = create_loader_params_->request;
request_info->is_download =
request_info->is_navigation && request.allow_download &&
- (is_download_ || navigation_loader_util::IsDownload(
+ (is_download_ || download_utils::IsDownload(
request.url, head.headers.get(), head.mime_type));
NotifyClient(std::move(request_info));
}
@@ -1182,12 +1180,6 @@ void InterceptionJob::OnReceiveRedirect(
NotifyClient(std::move(request_info));
}
-void InterceptionJob::OnDataDownloaded(int64_t data_length,
- int64_t encoded_length) {
- if (ShouldBypassForResponse())
- client_->OnDataDownloaded(data_length, encoded_length);
-}
-
void InterceptionJob::OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) {
diff --git a/chromium/content/browser/devtools/devtools_url_request_interceptor.cc b/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
index 260a5206a1f..0a02236d4dc 100644
--- a/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
+++ b/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
@@ -219,7 +219,9 @@ DevToolsURLRequestInterceptor::FilterEntryForRequest(
return nullptr;
const std::vector<std::unique_ptr<FilterEntry>>& entries = it->second;
- const std::string url_str = protocol::NetworkHandler::ClearUrlRef(url).spec();
+ std::string unused;
+ const std::string url_str =
+ protocol::NetworkHandler::ExtractFragment(url, &unused);
for (const auto& entry : entries) {
for (const Pattern& pattern : entry->patterns) {
if (!pattern.resource_types.empty() &&
diff --git a/chromium/content/browser/devtools/devtools_video_consumer.cc b/chromium/content/browser/devtools/devtools_video_consumer.cc
index fb91996670c..2b185d09f79 100644
--- a/chromium/content/browser/devtools/devtools_video_consumer.cc
+++ b/chromium/content/browser/devtools/devtools_video_consumer.cc
@@ -4,6 +4,8 @@
#include "content/browser/devtools/devtools_video_consumer.h"
+#include <utility>
+
#include "cc/paint/skia_paint_canvas.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h"
@@ -25,6 +27,11 @@ constexpr base::TimeDelta kDefaultMinPeriod = base::TimeDelta();
// Allow variable aspect ratio.
const bool kDefaultUseFixedAspectRatio = false;
+// Creates a ClientFrameSinkVideoCapturer via HostFrameSinkManager.
+std::unique_ptr<viz::ClientFrameSinkVideoCapturer> CreateCapturer() {
+ return GetHostFrameSinkManager()->CreateVideoCapturer();
+}
+
} // namespace
// static
@@ -37,8 +44,7 @@ DevToolsVideoConsumer::DevToolsVideoConsumer(OnFrameCapturedCallback callback)
: callback_(std::move(callback)),
min_capture_period_(kDefaultMinCapturePeriod),
min_frame_size_(kDefaultMinFrameSize),
- max_frame_size_(kDefaultMaxFrameSize),
- binding_(this) {}
+ max_frame_size_(kDefaultMaxFrameSize) {}
DevToolsVideoConsumer::~DevToolsVideoConsumer() = default;
@@ -63,16 +69,18 @@ void DevToolsVideoConsumer::StartCapture() {
void DevToolsVideoConsumer::StopCapture() {
if (!capturer_)
return;
- binding_.Close();
- capturer_->Stop();
capturer_.reset();
}
void DevToolsVideoConsumer::SetFrameSinkId(
const viz::FrameSinkId& frame_sink_id) {
frame_sink_id_ = frame_sink_id;
- if (capturer_)
- capturer_->ChangeTarget(frame_sink_id_);
+ if (capturer_) {
+ if (frame_sink_id_.is_valid())
+ capturer_->ChangeTarget(frame_sink_id_);
+ else
+ capturer_->ChangeTarget(base::nullopt);
+ }
}
void DevToolsVideoConsumer::SetMinCapturePeriod(
@@ -93,28 +101,19 @@ void DevToolsVideoConsumer::SetMinAndMaxFrameSize(gfx::Size min_frame_size,
}
}
-viz::mojom::FrameSinkVideoCapturerPtrInfo
-DevToolsVideoConsumer::CreateCapturer() {
- viz::HostFrameSinkManager* const manager = GetHostFrameSinkManager();
- viz::mojom::FrameSinkVideoCapturerPtr capturer;
- manager->CreateVideoCapturer(mojo::MakeRequest(&capturer));
- return capturer.PassInterface();
-}
-
void DevToolsVideoConsumer::InnerStartCapture(
- viz::mojom::FrameSinkVideoCapturerPtrInfo capturer_info) {
- capturer_.Bind(std::move(capturer_info));
+ std::unique_ptr<viz::ClientFrameSinkVideoCapturer> capturer) {
+ capturer_ = std::move(capturer);
// Give |capturer_| the capture parameters.
capturer_->SetMinCapturePeriod(min_capture_period_);
capturer_->SetMinSizeChangePeriod(kDefaultMinPeriod);
capturer_->SetResolutionConstraints(min_frame_size_, max_frame_size_,
kDefaultUseFixedAspectRatio);
- capturer_->ChangeTarget(frame_sink_id_);
+ if (frame_sink_id_.is_valid())
+ capturer_->ChangeTarget(frame_sink_id_);
- viz::mojom::FrameSinkVideoConsumerPtr consumer;
- binding_.Bind(mojo::MakeRequest(&consumer));
- capturer_->Start(std::move(consumer));
+ capturer_->Start(this);
}
bool DevToolsVideoConsumer::IsValidMinAndMaxFrameSize(
@@ -160,9 +159,6 @@ void DevToolsVideoConsumer::OnFrameCaptured(
callback_.Run(std::move(frame));
}
-void DevToolsVideoConsumer::OnTargetLost(
- const viz::FrameSinkId& frame_sink_id) {}
-
void DevToolsVideoConsumer::OnStopped() {}
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_video_consumer.h b/chromium/content/browser/devtools/devtools_video_consumer.h
index fc9bbdba359..dd17f36abdd 100644
--- a/chromium/content/browser/devtools/devtools_video_consumer.h
+++ b/chromium/content/browser/devtools/devtools_video_consumer.h
@@ -5,10 +5,12 @@
#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_VIDEO_CONSUMER_H_
#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_VIDEO_CONSUMER_H_
+#include <memory>
+
#include "base/time/time.h"
+#include "components/viz/host/client_frame_sink_video_capturer.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
#include "ui/gfx/geometry/size.h"
class SkBitmap;
@@ -18,8 +20,8 @@ namespace content {
// This class is the video consumer to FrameSinkVideoCapturerImpl. This class,
// in turn sends video frames to its host via the OnFrameCapturedCallback. Used
// when the VizDisplayCompositor feature is enabled.
-// TODO(https://crbug.com/813929): Use this class everywhere even if viz is not
-// enabled.
+// TODO(crbug.com/846811): This class can probably be merged into
+// viz::ClientFrameSinkVideoCapturer.
class CONTENT_EXPORT DevToolsVideoConsumer
: public viz::mojom::FrameSinkVideoConsumer {
public:
@@ -35,7 +37,7 @@ class CONTENT_EXPORT DevToolsVideoConsumer
// If not currently capturing, this creates the capturer and starts capturing.
void StartCapture();
- // Closes |binding_|. Stops capturing and resets |capturer_|.
+ // Stops capturing and resets |capturer_|.
void StopCapture();
// These functions cache the values passed to them and if we're currently
@@ -49,15 +51,11 @@ class CONTENT_EXPORT DevToolsVideoConsumer
private:
friend class DevToolsVideoConsumerTest;
- // Sets up a mojo message pipe and requests the HostFrameSinkManager create a
- // new capturer instance bound to it. Returns the client-side interface.
- viz::mojom::FrameSinkVideoCapturerPtrInfo CreateCapturer();
- // Binds |capturer_info| to the |capturer_|, sets capture parameters, and
- // starts capture. Normally, CreateCapturer produces the |capturer_info|, but
- // unittests can provide a mock.
+ // Sets |capturer_|, sends capture parameters, and starts capture. Normally,
+ // CreateCapturer produces the |capturer|, but unittests can provide a mock.
void InnerStartCapture(
- viz::mojom::FrameSinkVideoCapturerPtrInfo capturer_info);
+ std::unique_ptr<viz::ClientFrameSinkVideoCapturer> capturer);
// Checks that |min_frame_size| and |max_frame_size| are in the expected
// range. Limits are specified in media::limits.
@@ -72,7 +70,6 @@ class CONTENT_EXPORT DevToolsVideoConsumer
const gfx::Rect& update_rect,
const gfx::Rect& content_rect,
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) override;
- void OnTargetLost(const viz::FrameSinkId& frame_sink_id) override;
void OnStopped() override;
// Default min frame size is 1x1, as otherwise, nothing would be captured.
@@ -90,11 +87,8 @@ class CONTENT_EXPORT DevToolsVideoConsumer
gfx::Size max_frame_size_;
viz::FrameSinkId frame_sink_id_;
- // Mojo pointer to the viz::FrameSinkVideoCapturer instance. If |capturer_|
- // is alive, then we are currently capturing.
- viz::mojom::FrameSinkVideoCapturerPtr capturer_;
-
- mojo::Binding<viz::mojom::FrameSinkVideoConsumer> binding_;
+ // If |capturer_| is alive, then we are currently capturing.
+ std::unique_ptr<viz::ClientFrameSinkVideoCapturer> capturer_;
DISALLOW_COPY_AND_ASSIGN(DevToolsVideoConsumer);
};
diff --git a/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc b/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
index 20f9b2fdb62..826ab906e49 100644
--- a/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <memory>
+#include <utility>
+#include <vector>
#include "base/message_loop/message_loop.h"
#include "content/browser/devtools/devtools_video_consumer.h"
@@ -38,6 +39,11 @@ class MockFrameSinkVideoCapturer : public viz::mojom::FrameSinkVideoCapturer {
binding_.Bind(std::move(request));
}
+ void Reset() {
+ binding_.Close();
+ consumer_.reset();
+ }
+
// This is never called.
MOCK_METHOD2(SetFormat,
void(media::VideoPixelFormat format,
@@ -66,8 +72,9 @@ class MockFrameSinkVideoCapturer : public viz::mojom::FrameSinkVideoCapturer {
bool use_fixed_aspect_ratio));
// This is never called.
MOCK_METHOD1(SetAutoThrottlingEnabled, void(bool));
- void ChangeTarget(const viz::FrameSinkId& frame_sink_id) final {
- frame_sink_id_ = frame_sink_id;
+ void ChangeTarget(
+ const base::Optional<viz::FrameSinkId>& frame_sink_id) final {
+ frame_sink_id_ = frame_sink_id ? *frame_sink_id : viz::FrameSinkId();
MockChangeTarget(frame_sink_id_);
}
MOCK_METHOD1(MockChangeTarget, void(const viz::FrameSinkId& frame_sink_id));
@@ -177,7 +184,7 @@ class DevToolsVideoConsumerTest : public testing::Test {
}
void StartCaptureWithMockCapturer() {
- consumer_->InnerStartCapture(BindMockCapturer());
+ consumer_->InnerStartCapture(CreateMockCapturer());
}
bool IsValidMinAndMaxFrameSize(gfx::Size min_frame_size,
@@ -208,10 +215,14 @@ class DevToolsVideoConsumerTest : public testing::Test {
std::unique_ptr<DevToolsVideoConsumer> consumer_;
private:
- viz::mojom::FrameSinkVideoCapturerPtrInfo BindMockCapturer() {
- viz::mojom::FrameSinkVideoCapturerPtr capturer_ptr;
- capturer_.Bind(mojo::MakeRequest(&capturer_ptr));
- return capturer_ptr.PassInterface();
+ std::unique_ptr<viz::ClientFrameSinkVideoCapturer> CreateMockCapturer() {
+ return std::make_unique<viz::ClientFrameSinkVideoCapturer>(
+ base::BindRepeating(
+ [](base::WeakPtr<DevToolsVideoConsumerTest> self,
+ viz::mojom::FrameSinkVideoCapturerRequest request) {
+ self->capturer_.Bind(std::move(request));
+ },
+ weak_factory_.GetWeakPtr()));
}
base::MessageLoop message_loop_;
@@ -281,9 +292,10 @@ TEST_F(DevToolsVideoConsumerTest, StartCaptureCallsSetFunctions) {
base::RunLoop().RunUntilIdle();
// Stop capturing.
- EXPECT_CALL(capturer_, MockStop());
consumer_->StopCapture();
- base::RunLoop().RunUntilIdle();
+
+ // Reset the mock to allow the next consumer to connect.
+ capturer_.Reset();
// Start capturing again, and expect that these |capturer_| functions are
// called once. This will re-bind the |capturer_| and ensures that destroyed
diff --git a/chromium/content/browser/devtools/protocol/browser_handler.cc b/chromium/content/browser/devtools/protocol/browser_handler.cc
index 7e03482fde2..618ca845bad 100644
--- a/chromium/content/browser/devtools/protocol/browser_handler.cc
+++ b/chromium/content/browser/devtools/protocol/browser_handler.cc
@@ -47,10 +47,14 @@ Response BrowserHandler::GetVersion(std::string* protocol_version,
namespace {
// Converts an histogram.
-std::unique_ptr<Browser::Histogram> Convert(
- const base::HistogramBase& in_histogram) {
- const std::unique_ptr<const base::HistogramSamples> in_buckets =
- in_histogram.SnapshotSamples();
+std::unique_ptr<Browser::Histogram> Convert(base::HistogramBase& in_histogram,
+ bool in_delta) {
+ std::unique_ptr<const base::HistogramSamples> in_buckets;
+ if (!in_delta) {
+ in_buckets = in_histogram.SnapshotSamples();
+ } else {
+ in_buckets = in_histogram.SnapshotDelta();
+ }
DCHECK(in_buckets);
auto out_buckets = std::make_unique<Array<Browser::Bucket>>();
@@ -81,16 +85,17 @@ std::unique_ptr<Browser::Histogram> Convert(
Response BrowserHandler::GetHistograms(
const Maybe<std::string> in_query,
+ const Maybe<bool> in_delta,
std::unique_ptr<Array<Browser::Histogram>>* const out_histograms) {
// Convert histograms.
DCHECK(out_histograms);
*out_histograms = std::make_unique<Array<Browser::Histogram>>();
- for (const base::HistogramBase* const h :
+ for (base::HistogramBase* const h :
base::StatisticsRecorder::Sort(base::StatisticsRecorder::WithName(
base::StatisticsRecorder::GetHistograms(),
in_query.fromMaybe("")))) {
DCHECK(h);
- (*out_histograms)->addItem(Convert(*h));
+ (*out_histograms)->addItem(Convert(*h, in_delta.fromMaybe(false)));
}
return Response::OK();
@@ -98,16 +103,17 @@ Response BrowserHandler::GetHistograms(
Response BrowserHandler::GetHistogram(
const std::string& in_name,
+ const Maybe<bool> in_delta,
std::unique_ptr<Browser::Histogram>* const out_histogram) {
// Get histogram by name.
- const base::HistogramBase* const in_histogram =
+ base::HistogramBase* const in_histogram =
base::StatisticsRecorder::FindHistogram(in_name);
if (!in_histogram)
return Response::InvalidParams("Cannot find histogram: " + in_name);
// Convert histogram.
DCHECK(out_histogram);
- *out_histogram = Convert(*in_histogram);
+ *out_histogram = Convert(*in_histogram, in_delta.fromMaybe(false));
return Response::OK();
}
diff --git a/chromium/content/browser/devtools/protocol/browser_handler.h b/chromium/content/browser/devtools/protocol/browser_handler.h
index b4f3e05eccc..9ced0243186 100644
--- a/chromium/content/browser/devtools/protocol/browser_handler.h
+++ b/chromium/content/browser/devtools/protocol/browser_handler.h
@@ -28,10 +28,12 @@ class BrowserHandler : public DevToolsDomainHandler, public Browser::Backend {
Response GetHistograms(
Maybe<std::string> in_query,
+ Maybe<bool> in_delta,
std::unique_ptr<Array<Browser::Histogram>>* histograms) override;
Response GetHistogram(
const std::string& in_name,
+ Maybe<bool> in_delta,
std::unique_ptr<Browser::Histogram>* out_histogram) override;
Response GetBrowserCommandLine(
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index e63b7fc855d..aa29868d07d 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -546,9 +546,9 @@ IN_PROC_BROWSER_TEST_F(SyntheticKeyEventTest, KeyEventSynthesizeKey) {
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
Attach();
ASSERT_TRUE(content::ExecuteScript(
- shell()->web_contents()->GetRenderViewHost(),
+ shell()->web_contents(),
"function handleKeyEvent(event) {"
- "domAutomationController.send(event.key);"
+ "domAutomationController.send(event.key);"
"}"
"document.body.addEventListener('keydown', handleKeyEvent);"
"document.body.addEventListener('keyup', handleKeyEvent);"));
@@ -579,7 +579,7 @@ IN_PROC_BROWSER_TEST_F(SyntheticKeyEventTest, KeyboardEventAck) {
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
Attach();
ASSERT_TRUE(content::ExecuteScript(
- shell()->web_contents()->GetRenderViewHost(),
+ shell()->web_contents(),
"document.body.addEventListener('keydown', () => {debugger;});"));
auto filter = std::make_unique<InputMsgWatcher>(
@@ -605,7 +605,7 @@ IN_PROC_BROWSER_TEST_F(SyntheticMouseEventTest, MouseEventAck) {
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
Attach();
ASSERT_TRUE(content::ExecuteScript(
- shell()->web_contents()->GetRenderViewHost(),
+ shell()->web_contents(),
"document.body.addEventListener('mousedown', () => {debugger;});"));
auto filter = std::make_unique<InputMsgWatcher>(
@@ -781,7 +781,7 @@ class CaptureScreenshotTest : public DevToolsProtocolTest {
// Draw a blue box of provided size in the horizontal center of the page.
EXPECT_TRUE(content::ExecuteScript(
- shell()->web_contents()->GetRenderViewHost(),
+ shell()->web_contents(),
base::StringPrintf(
"var style = document.body.style; "
"style.overflow = 'hidden'; "
@@ -2605,9 +2605,15 @@ IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, ResetDownloadState) {
ASSERT_EQ(download::DownloadItem::COMPLETE, download->GetState());
}
+// Flakly on ChromeOS https://crbug.com/860312
+#if defined(OS_CHROMEOS)
+#define MAYBE_MultiDownload DISABLED_MultiDownload
+#else
+#define MAYBE_MultiDownload MultiDownload
+#endif
// Check that downloading multiple (in this case, 2) files does not result in
// corrupted files.
-IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, MultiDownload) {
+IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, MAYBE_MultiDownload) {
base::ThreadRestrictions::SetIOAllowed(true);
SetupEnsureNoPendingDownloads();
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.cc b/chromium/content/browser/devtools/protocol/emulation_handler.cc
index ca11b87a749..af6d9a2b197 100644
--- a/chromium/content/browser/devtools/protocol/emulation_handler.cc
+++ b/chromium/content/browser/devtools/protocol/emulation_handler.cc
@@ -8,13 +8,15 @@
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
+#include "content/browser/devtools/devtools_session.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/input/touch_emulator.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/view_messages.h"
#include "content/public/common/url_constants.h"
-#include "device/geolocation/public/cpp/geoposition.h"
+#include "net/http/http_util.h"
+#include "services/device/public/cpp/geolocation/geoposition.h"
#include "services/device/public/mojom/geolocation_context.mojom.h"
#include "services/device/public/mojom/geoposition.mojom.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
@@ -64,6 +66,13 @@ EmulationHandler::EmulationHandler()
EmulationHandler::~EmulationHandler() {
}
+// static
+std::vector<EmulationHandler*> EmulationHandler::ForAgentHost(
+ DevToolsAgentHostImpl* host) {
+ return DevToolsSession::HandlersForAgentHost<EmulationHandler>(
+ host, Emulation::Metainfo::domainName);
+}
+
void EmulationHandler::SetRenderer(int process_host_id,
RenderFrameHostImpl* frame_host) {
if (host_ == frame_host)
@@ -84,6 +93,7 @@ Response EmulationHandler::Disable() {
touch_emulation_enabled_ = false;
UpdateTouchEventEmulationState();
}
+ user_agent_ = std::string();
device_emulation_enabled_ = false;
UpdateDeviceEmulationState();
return Response::OK();
@@ -304,6 +314,23 @@ Response EmulationHandler::SetVisibleSize(int width, int height) {
return Response::OK();
}
+Response EmulationHandler::SetUserAgentOverride(
+ const std::string& user_agent,
+ Maybe<std::string> accept_language,
+ Maybe<std::string> platform) {
+ if (!user_agent.empty() && !net::HttpUtil::IsValidHeaderValue(user_agent))
+ return Response::InvalidParams("Invalid characters found in userAgent");
+ std::string accept_lang = accept_language.fromMaybe(std::string());
+ if (!accept_lang.empty() && !net::HttpUtil::IsValidHeaderValue(accept_lang)) {
+ return Response::InvalidParams(
+ "Invalid characters found in acceptLanguage");
+ }
+
+ user_agent_ = user_agent;
+ accept_language_ = accept_lang;
+ return Response::FallThrough();
+}
+
blink::WebDeviceEmulationParams EmulationHandler::GetDeviceEmulationParams() {
return device_emulation_params_;
}
@@ -372,5 +399,15 @@ void EmulationHandler::UpdateDeviceEmulationState() {
}
}
+void EmulationHandler::ApplyOverrides(net::HttpRequestHeaders* headers) {
+ if (!user_agent_.empty())
+ headers->SetHeader(net::HttpRequestHeaders::kUserAgent, user_agent_);
+ if (!accept_language_.empty()) {
+ headers->SetHeader(
+ net::HttpRequestHeaders::kAcceptLanguage,
+ net::HttpUtil::GenerateAcceptLanguageHeader(accept_language_));
+ }
+}
+
} // namespace protocol
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.h b/chromium/content/browser/devtools/protocol/emulation_handler.h
index 1503b2e70da..5890b6797b6 100644
--- a/chromium/content/browser/devtools/protocol/emulation_handler.h
+++ b/chromium/content/browser/devtools/protocol/emulation_handler.h
@@ -10,8 +10,13 @@
#include "content/browser/devtools/protocol/emulation.h"
#include "third_party/blink/public/web/web_device_emulation_params.h"
+namespace net {
+class HttpRequestHeaders;
+} // namespace net
+
namespace content {
+class DevToolsAgentHostImpl;
class RenderFrameHostImpl;
class WebContentsImpl;
@@ -23,6 +28,9 @@ class EmulationHandler : public DevToolsDomainHandler,
EmulationHandler();
~EmulationHandler() override;
+ static std::vector<EmulationHandler*> ForAgentHost(
+ DevToolsAgentHostImpl* host);
+
void Wire(UberDispatcher* dispatcher) override;
void SetRenderer(int process_host_id,
RenderFrameHostImpl* frame_host) override;
@@ -38,6 +46,10 @@ class EmulationHandler : public DevToolsDomainHandler,
bool enabled,
Maybe<std::string> configuration) override;
+ Response SetUserAgentOverride(const std::string& user_agent,
+ Maybe<std::string> accept_language,
+ Maybe<std::string> platform) override;
+
Response CanEmulate(bool* result) override;
Response SetDeviceMetricsOverride(
int width,
@@ -61,6 +73,8 @@ class EmulationHandler : public DevToolsDomainHandler,
bool device_emulation_enabled() { return device_emulation_enabled_; }
+ void ApplyOverrides(net::HttpRequestHeaders* headers);
+
private:
WebContentsImpl* GetWebContents();
void UpdateTouchEventEmulationState();
@@ -71,6 +85,8 @@ class EmulationHandler : public DevToolsDomainHandler,
bool device_emulation_enabled_;
blink::WebDeviceEmulationParams device_emulation_params_;
+ std::string user_agent_;
+ std::string accept_language_;
RenderFrameHostImpl* host_;
diff --git a/chromium/content/browser/devtools/protocol/input_handler.cc b/chromium/content/browser/devtools/protocol/input_handler.cc
index 4440a13e4c4..e6b74e54193 100644
--- a/chromium/content/browser/devtools/protocol/input_handler.cc
+++ b/chromium/content/browser/devtools/protocol/input_handler.cc
@@ -19,7 +19,6 @@
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input/synthetic_tap_gesture_params.h"
-#include "content/public/common/content_features.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/web_input_event_traits.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
@@ -285,15 +284,12 @@ class InputHandler::InputInjector
return;
}
- if (base::FeatureList::IsEnabled(
- features::kTouchpadAndWheelScrollLatching)) {
- // Send a synthetic wheel event with phaseEnded to finish scrolling.
- wheel_event->delta_x = 0;
- wheel_event->delta_y = 0;
- wheel_event->phase = blink::WebMouseWheelEvent::kPhaseEnded;
- wheel_event->dispatch_type = blink::WebInputEvent::kEventNonBlocking;
- widget_host_->ForwardWheelEvent(*wheel_event);
- }
+ // Send a synthetic wheel event with phaseEnded to finish scrolling.
+ wheel_event->delta_x = 0;
+ wheel_event->delta_y = 0;
+ wheel_event->phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ wheel_event->dispatch_type = blink::WebInputEvent::kEventNonBlocking;
+ widget_host_->ForwardWheelEvent(*wheel_event);
}
void InjectMouseEvent(const blink::WebMouseEvent& mouse_event,
@@ -585,11 +581,8 @@ void InputHandler::DispatchMouseEvent(
}
wheel_event->delta_x = static_cast<float>(-delta_x.fromJust());
wheel_event->delta_y = static_cast<float>(-delta_y.fromJust());
- if (base::FeatureList::IsEnabled(
- features::kTouchpadAndWheelScrollLatching)) {
- wheel_event->phase = blink::WebMouseWheelEvent::kPhaseBegan;
- wheel_event->dispatch_type = blink::WebInputEvent::kBlocking;
- }
+ wheel_event->phase = blink::WebMouseWheelEvent::kPhaseBegan;
+ wheel_event->dispatch_type = blink::WebInputEvent::kBlocking;
} else {
mouse_event.reset(new blink::WebMouseEvent(type, modifiers, timestamp));
}
@@ -802,10 +795,7 @@ Response InputHandler::EmulateTouchFromMouseEvent(const std::string& type,
event.reset(wheel_event);
wheel_event->delta_x = static_cast<float>(delta_x.fromJust());
wheel_event->delta_y = static_cast<float>(delta_y.fromJust());
- if (base::FeatureList::IsEnabled(
- features::kTouchpadAndWheelScrollLatching)) {
- wheel_event->phase = blink::WebMouseWheelEvent::kPhaseBegan;
- }
+ wheel_event->phase = blink::WebMouseWheelEvent::kPhaseBegan;
} else {
mouse_event = new blink::WebMouseEvent(
event_type,
@@ -828,15 +818,12 @@ Response InputHandler::EmulateTouchFromMouseEvent(const std::string& type,
if (wheel_event) {
host_->GetRenderWidgetHost()->ForwardWheelEvent(*wheel_event);
- if (base::FeatureList::IsEnabled(
- features::kTouchpadAndWheelScrollLatching)) {
- // Send a synthetic wheel event with phaseEnded to finish scrolling.
- wheel_event->delta_x = 0;
- wheel_event->delta_y = 0;
- wheel_event->phase = blink::WebMouseWheelEvent::kPhaseEnded;
- wheel_event->dispatch_type = blink::WebInputEvent::kEventNonBlocking;
- host_->GetRenderWidgetHost()->ForwardWheelEvent(*wheel_event);
- }
+ // Send a synthetic wheel event with phaseEnded to finish scrolling.
+ wheel_event->delta_x = 0;
+ wheel_event->delta_y = 0;
+ wheel_event->phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ wheel_event->dispatch_type = blink::WebInputEvent::kEventNonBlocking;
+ host_->GetRenderWidgetHost()->ForwardWheelEvent(*wheel_event);
} else {
host_->GetRenderWidgetHost()->ForwardMouseEvent(*mouse_event);
}
diff --git a/chromium/content/browser/devtools/protocol/network_handler.cc b/chromium/content/browser/devtools/protocol/network_handler.cc
index b8ea9fc9205..905fe910beb 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.cc
+++ b/chromium/content/browser/devtools/protocol/network_handler.cc
@@ -31,7 +31,8 @@
#include "content/browser/frame_host/navigation_request.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/storage_partition_impl.h"
-#include "content/browser/web_package/signed_exchange_header.h"
+#include "content/browser/web_package/signed_exchange_envelope.h"
+#include "content/browser/web_package/signed_exchange_error.h"
#include "content/common/navigation_params.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -53,6 +54,8 @@
#include "net/base/upload_bytes_element_reader.h"
#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_sct_to_string.h"
+#include "net/cert/x509_certificate.h"
+#include "net/cert/x509_util.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_store.h"
#include "net/http/http_response_headers.h"
@@ -85,9 +88,6 @@ using DeleteCookiesCallback = Network::Backend::DeleteCookiesCallback;
using ClearBrowserCookiesCallback =
Network::Backend::ClearBrowserCookiesCallback;
-const char kDevToolsEmulateNetworkConditionsClientId[] =
- "X-DevTools-Emulate-Network-Conditions-Client-Id";
-
Network::CertificateTransparencyCompliance SerializeCTPolicyCompliance(
net::ct::CTPolicyCompliance ct_compliance) {
switch (ct_compliance) {
@@ -379,8 +379,6 @@ void DeleteFilteredCookies(network::mojom::CookieManager* cookie_manager,
const std::string& path,
std::unique_ptr<DeleteCookiesCallback> callback,
const std::vector<net::CanonicalCookie>& cookies) {
- base::Time yesterday(base::Time::Now() - base::TimeDelta::FromDays(1));
-
std::vector<net::CanonicalCookie> filtered_list =
FilterCookies(cookies, name, normalized_domain, path);
@@ -389,17 +387,10 @@ void DeleteFilteredCookies(network::mojom::CookieManager* cookie_manager,
base::BindOnce(&DeleteCookiesCallback::sendSuccess, std::move(callback)));
for (auto& cookie : filtered_list) {
- // Delete a single cookie by setting its expiration time into the past.
- cookie_manager->SetCanonicalCookie(
- net::CanonicalCookie(cookie.Name(), cookie.Value(), cookie.Domain(),
- cookie.Path(), cookie.CreationDate(), yesterday,
- cookie.LastAccessDate(), cookie.IsSecure(),
- cookie.IsHttpOnly(), cookie.SameSite(),
- cookie.Priority()),
- true /* secure_source */, true /* modify_http_only */,
- base::BindOnce(
- [](base::RepeatingClosure callback, bool) { callback.Run(); },
- barrier_closure));
+ cookie_manager->DeleteCanonicalCookie(
+ cookie, base::BindOnce([](base::RepeatingClosure callback,
+ bool) { callback.Run(); },
+ barrier_closure));
}
}
@@ -705,15 +696,21 @@ bool AddInterceptedResourceType(
intercepted_resource_types->insert(RESOURCE_TYPE_PREFETCH);
return true;
}
+ if (resource_type == protocol::Page::ResourceTypeEnum::CSPViolationReport) {
+ intercepted_resource_types->insert(RESOURCE_TYPE_CSP_REPORT);
+ return true;
+ }
+ if (resource_type == protocol::Page::ResourceTypeEnum::Ping) {
+ intercepted_resource_types->insert(RESOURCE_TYPE_PING);
+ return true;
+ }
if (resource_type == protocol::Page::ResourceTypeEnum::Other) {
intercepted_resource_types->insert(RESOURCE_TYPE_SUB_RESOURCE);
intercepted_resource_types->insert(RESOURCE_TYPE_OBJECT);
intercepted_resource_types->insert(RESOURCE_TYPE_WORKER);
intercepted_resource_types->insert(RESOURCE_TYPE_SHARED_WORKER);
intercepted_resource_types->insert(RESOURCE_TYPE_FAVICON);
- intercepted_resource_types->insert(RESOURCE_TYPE_PING);
intercepted_resource_types->insert(RESOURCE_TYPE_SERVICE_WORKER);
- intercepted_resource_types->insert(RESOURCE_TYPE_CSP_REPORT);
intercepted_resource_types->insert(RESOURCE_TYPE_PLUGIN_RESOURCE);
return true;
}
@@ -820,12 +817,6 @@ class NetworkNavigationThrottle : public content::NavigationThrottle {
DISALLOW_COPY_AND_ASSIGN(NetworkNavigationThrottle);
};
-void ConfigureServiceWorkerContextOnIO() {
- std::set<std::string> headers;
- headers.insert(kDevToolsEmulateNetworkConditionsClientId);
- content::ServiceWorkerContext::AddExcludedHeadersForFetchEvent(headers);
-}
-
bool GetPostData(const net::URLRequest* request, std::string* post_data) {
if (!request->has_upload())
return false;
@@ -868,10 +859,44 @@ bool GetPostData(const network::ResourceRequestBody& request_body,
return true;
}
-std::string StripFragment(const GURL& url) {
- url::Replacements<char> replacements;
- replacements.ClearRef();
- return url.ReplaceComponents(replacements).spec();
+String SignedExchangeErrorErrorFieldToString(SignedExchangeError::Field field) {
+ switch (field) {
+ case SignedExchangeError::Field::kSignatureSig:
+ return Network::SignedExchangeErrorFieldEnum::SignatureSig;
+ case SignedExchangeError::Field::kSignatureIintegrity:
+ return Network::SignedExchangeErrorFieldEnum::SignatureIntegrity;
+ case SignedExchangeError::Field::kSignatureCertUrl:
+ return Network::SignedExchangeErrorFieldEnum::SignatureCertUrl;
+ case SignedExchangeError::Field::kSignatureCertSha256:
+ return Network::SignedExchangeErrorFieldEnum::SignatureCertSha256;
+ case SignedExchangeError::Field::kSignatureValidityUrl:
+ return Network::SignedExchangeErrorFieldEnum::SignatureValidityUrl;
+ case SignedExchangeError::Field::kSignatureTimestamps:
+ return Network::SignedExchangeErrorFieldEnum::SignatureTimestamps;
+ }
+ NOTREACHED();
+ return "";
+}
+
+std::unique_ptr<Network::SignedExchangeError> BuildSignedExchangeError(
+ const SignedExchangeError& error) {
+ std::unique_ptr<Network::SignedExchangeError> signed_exchange_error =
+ Network::SignedExchangeError::Create().SetMessage(error.message).Build();
+ if (error.field) {
+ signed_exchange_error->SetSignatureIndex(error.field->first);
+ signed_exchange_error->SetErrorField(
+ SignedExchangeErrorErrorFieldToString(error.field->second));
+ }
+ return signed_exchange_error;
+}
+
+std::unique_ptr<Array<Network::SignedExchangeError>> BuildSignedExchangeErrors(
+ const std::vector<SignedExchangeError>& errors) {
+ std::unique_ptr<Array<Network::SignedExchangeError>> signed_exchange_errors =
+ Array<Network::SignedExchangeError>::create();
+ for (const auto& error : errors)
+ signed_exchange_errors->addItem(BuildSignedExchangeError(error));
+ return signed_exchange_errors;
}
} // namespace
@@ -933,9 +958,11 @@ class BackgroundSyncRestorer {
};
NetworkHandler::NetworkHandler(const std::string& host_id,
+ const base::UnguessableToken& devtools_token,
DevToolsIOContext* io_context)
: DevToolsDomainHandler(Network::Metainfo::domainName),
host_id_(host_id),
+ devtools_token_(devtools_token),
io_context_(io_context),
browser_context_(nullptr),
storage_partition_(nullptr),
@@ -949,8 +976,6 @@ NetworkHandler::NetworkHandler(const std::string& host_id,
if (have_configured_service_worker_context)
return;
have_configured_service_worker_context = true;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ConfigureServiceWorkerContextOnIO));
}
NetworkHandler::~NetworkHandler() {
@@ -993,7 +1018,6 @@ Response NetworkHandler::Enable(Maybe<int> max_total_size,
Response NetworkHandler::Disable() {
enabled_ = false;
- user_agent_ = std::string();
interception_handle_.reset();
url_loader_interceptor_.reset();
SetNetworkConditions(nullptr);
@@ -1264,16 +1288,6 @@ void NetworkHandler::DeleteCookies(
normalized_domain, path.fromMaybe(""), std::move(callback)));
}
-Response NetworkHandler::SetUserAgentOverride(const std::string& user_agent) {
- if (user_agent.find('\n') != std::string::npos ||
- user_agent.find('\r') != std::string::npos ||
- user_agent.find('\0') != std::string::npos) {
- return Response::InvalidParams("Invalid characters found in userAgent");
- }
- user_agent_ = user_agent;
- return Response::FallThrough();
-}
-
Response NetworkHandler::SetExtraHTTPHeaders(
std::unique_ptr<protocol::Network::Headers> headers) {
std::vector<std::pair<std::string, std::string>> new_headers;
@@ -1442,9 +1456,10 @@ std::unique_ptr<Network::Response> BuildResponse(
status_text = "OK";
}
+ std::string url_fragment;
auto response =
Network::Response::Create()
- .SetUrl(StripFragment(url))
+ .SetUrl(NetworkHandler::ExtractFragment(url, &url_fragment))
.SetStatus(status)
.SetStatusText(status_text)
.SetHeaders(Object::fromValue(headers_dict.get(), nullptr))
@@ -1502,6 +1517,8 @@ String blockedReason(blink::ResourceRequestBlockedReason reason) {
return protocol::Network::BlockedReasonEnum::ContentType;
case blink::ResourceRequestBlockedReason::kOther:
return protocol::Network::BlockedReasonEnum::Other;
+ case blink::ResourceRequestBlockedReason::kCollapsedByClient:
+ return protocol::Network::BlockedReasonEnum::CollapsedByClient;
}
NOTREACHED();
return protocol::Network::BlockedReasonEnum::Other;
@@ -1540,14 +1557,19 @@ void NetworkHandler::NavigationRequestWillBeSent(
redirect_response = BuildResponse(request_params.redirects.back(),
request_params.redirect_response.back());
}
+ std::string url_fragment;
+ std::string url_without_fragment =
+ ExtractFragment(common_params.url, &url_fragment);
auto request =
Network::Request::Create()
- .SetUrl(StripFragment(common_params.url))
+ .SetUrl(url_without_fragment)
.SetMethod(common_params.method)
.SetHeaders(Object::fromValue(headers_dict.get(), nullptr))
.SetInitialPriority(resourcePriority(net::HIGHEST))
.SetReferrerPolicy(referrerPolicy(common_params.referrer.policy))
.Build();
+ if (!url_fragment.empty())
+ request->SetUrlFragment(url_fragment);
std::string post_data;
if (common_params.post_data &&
@@ -1578,9 +1600,8 @@ void NetworkHandler::NavigationRequestWillBeSent(
std::string frame_token =
nav_request.frame_tree_node()->devtools_frame_token().ToString();
frontend_->RequestWillBeSent(
- id, id, StripFragment(common_params.url), std::move(request),
- current_ticks, current_wall_time, std::move(initiator),
- std::move(redirect_response),
+ id, id, url_without_fragment, std::move(request), current_ticks,
+ current_wall_time, std::move(initiator), std::move(redirect_response),
std::string(Page::ResourceTypeEnum::Document), std::move(frame_token),
common_params.has_user_gesture);
}
@@ -1599,15 +1620,21 @@ void NetworkHandler::RequestSent(const std::string& request_id,
Network::Initiator::Create().SetType(initiator_type).Build();
if (initiator_url)
initiator->SetUrl(initiator_url->spec());
- frontend_->RequestWillBeSent(
- request_id, loader_id, StripFragment(request.url),
+ std::string url_fragment;
+ std::string url_without_fragment =
+ ExtractFragment(request.url, &url_fragment);
+ auto request_object =
Network::Request::Create()
- .SetUrl(StripFragment(request.url))
+ .SetUrl(url_without_fragment)
.SetMethod(request.method)
.SetHeaders(Object::fromValue(headers_dict.get(), nullptr))
.SetInitialPriority(resourcePriority(request.priority))
.SetReferrerPolicy(referrerPolicy(request.referrer_policy))
- .Build(),
+ .Build();
+ if (!url_fragment.empty())
+ request_object->SetUrlFragment(url_fragment);
+ frontend_->RequestWillBeSent(
+ request_id, loader_id, url_without_fragment, std::move(request_object),
base::TimeTicks::Now().ToInternalValue() /
static_cast<double>(base::Time::kMicrosecondsPerSecond),
base::Time::Now().ToDoubleT(), std::move(initiator),
@@ -1660,9 +1687,10 @@ void NetworkHandler::OnSignedExchangeReceived(
base::Optional<const base::UnguessableToken> devtools_navigation_token,
const GURL& outer_request_url,
const network::ResourceResponseHead& outer_response,
- const base::Optional<SignedExchangeHeader>& header,
+ const base::Optional<SignedExchangeEnvelope>& envelope,
+ const scoped_refptr<net::X509Certificate>& certificate,
const base::Optional<net::SSLInfo>& ssl_info,
- const std::vector<std::string>& error_messages) {
+ const std::vector<SignedExchangeError>& errors) {
if (!enabled_)
return;
std::unique_ptr<Network::SignedExchangeInfo> signed_exchange_info =
@@ -1670,40 +1698,59 @@ void NetworkHandler::OnSignedExchangeReceived(
.SetOuterResponse(BuildResponse(outer_request_url, outer_response))
.Build();
- if (header) {
+ if (envelope) {
std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create());
- for (const auto it : header->response_headers())
+ for (const auto it : envelope->response_headers())
headers_dict->setString(it.first, it.second);
- const SignedExchangeHeaderParser::Signature& sig = header->signature();
+ const SignedExchangeSignatureHeaderField::Signature& sig =
+ envelope->signature();
std::unique_ptr<Array<Network::SignedExchangeSignature>> signatures =
Array<Network::SignedExchangeSignature>::create();
- signatures->addItem(Network::SignedExchangeSignature::Create()
- .SetLabel(sig.label)
- .SetIntegrity(sig.integrity)
- .SetCertUrl(sig.cert_url.spec())
- .SetValidityUrl(sig.validity_url.spec())
- .SetDate(sig.date)
- .SetExpires(sig.expires)
- .Build());
+ std::unique_ptr<Network::SignedExchangeSignature> signature =
+ Network::SignedExchangeSignature::Create()
+ .SetLabel(sig.label)
+ .SetSignature(base::HexEncode(sig.sig.data(), sig.sig.size()))
+ .SetIntegrity(sig.integrity)
+ .SetCertUrl(sig.cert_url.spec())
+ .SetValidityUrl(sig.validity_url.spec())
+ .SetDate(sig.date)
+ .SetExpires(sig.expires)
+ .Build();
+ if (sig.cert_sha256) {
+ signature->SetCertSha256(base::HexEncode(sig.cert_sha256->data,
+ sizeof(sig.cert_sha256->data)));
+ }
+ if (certificate) {
+ std::unique_ptr<Array<String>> encoded_certificates =
+ Array<String>::create();
+ std::string encoded;
+ base::Base64Encode(
+ net::x509_util::CryptoBufferAsStringPiece(certificate->cert_buffer()),
+ &encoded);
+ encoded_certificates->addItem(std::move(encoded));
+ for (const auto& cert : certificate->intermediate_buffers()) {
+ base::Base64Encode(
+ net::x509_util::CryptoBufferAsStringPiece(cert.get()), &encoded);
+ encoded_certificates->addItem(std::move(encoded));
+ }
+ signature->SetCertificates(std::move(encoded_certificates));
+ }
+ signatures->addItem(std::move(signature));
signed_exchange_info->SetHeader(
Network::SignedExchangeHeader::Create()
- .SetRequestUrl(header->request_url().spec())
- .SetRequestMethod(header->request_method())
- .SetResponseCode(header->response_code())
+ .SetRequestUrl(envelope->request_url().spec())
+ .SetRequestMethod(envelope->request_method())
+ .SetResponseCode(envelope->response_code())
.SetResponseHeaders(Object::fromValue(headers_dict.get(), nullptr))
.SetSignatures(std::move(signatures))
.Build());
}
if (ssl_info)
signed_exchange_info->SetSecurityDetails(BuildSecurityDetails(*ssl_info));
- if (error_messages.size()) {
- std::unique_ptr<Array<String>> errors = Array<String>::create();
- for (const auto& message : error_messages)
- errors->addItem(message);
- signed_exchange_info->SetErrors(std::move(errors));
- }
+ if (errors.size())
+ signed_exchange_info->SetErrors(BuildSignedExchangeErrors(errors));
frontend_->SignedExchangeReceived(
devtools_navigation_token ? devtools_navigation_token->ToString() : "",
@@ -1877,12 +1924,16 @@ void NetworkHandler::OnResponseBodyPipeTaken(
}
// static
-GURL NetworkHandler::ClearUrlRef(const GURL& url) {
- if (!url.has_ref())
- return url;
+std::string NetworkHandler::ExtractFragment(const GURL& url,
+ std::string* fragment) {
+ if (!url.has_ref()) {
+ *fragment = std::string();
+ return url.spec();
+ }
+ *fragment = "#" + url.ref();
GURL::Replacements replacements;
replacements.ClearRef();
- return url.ReplaceComponents(replacements);
+ return url.ReplaceComponents(replacements).spec();
}
// static
@@ -1896,14 +1947,17 @@ NetworkHandler::CreateRequestFromResourceRequest(
headers_dict->setString(net::HttpRequestHeaders::kReferer,
request.referrer.spec());
}
+ std::string url_fragment;
std::unique_ptr<protocol::Network::Request> request_object =
Network::Request::Create()
- .SetUrl(ClearUrlRef(request.url).spec())
+ .SetUrl(ExtractFragment(request.url, &url_fragment))
.SetMethod(request.method)
.SetHeaders(Object::fromValue(headers_dict.get(), nullptr))
.SetInitialPriority(resourcePriority(request.priority))
.SetReferrerPolicy(referrerPolicy(request.referrer_policy))
.Build();
+ if (!url_fragment.empty())
+ request_object->SetUrlFragment(url_fragment);
std::string post_data;
if (request.request_body && GetPostData(*request.request_body, &post_data))
request_object->SetPostData(std::move(post_data));
@@ -1912,24 +1966,30 @@ NetworkHandler::CreateRequestFromResourceRequest(
// static
std::unique_ptr<Network::Request> NetworkHandler::CreateRequestFromURLRequest(
- const net::URLRequest* request) {
+ const net::URLRequest* request,
+ const std::string& cookie) {
std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create());
for (net::HttpRequestHeaders::Iterator it(request->extra_request_headers());
it.GetNext();) {
headers_dict->setString(it.name(), it.value());
}
+ if (!cookie.empty())
+ headers_dict->setString(net::HttpRequestHeaders::kCookie, cookie);
if (!request->referrer().empty()) {
headers_dict->setString(net::HttpRequestHeaders::kReferer,
request->referrer());
}
+ std::string url_fragment;
std::unique_ptr<protocol::Network::Request> request_object =
Network::Request::Create()
- .SetUrl(ClearUrlRef(request->url()).spec())
+ .SetUrl(ExtractFragment(request->url(), &url_fragment))
.SetMethod(request->method())
.SetHeaders(Object::fromValue(headers_dict.get(), nullptr))
.SetInitialPriority(resourcePriority(request->priority()))
.SetReferrerPolicy(referrerPolicy(request->referrer_policy()))
.Build();
+ if (!url_fragment.empty())
+ request_object->SetUrlFragment(url_fragment);
std::string post_data;
if (GetPostData(request, &post_data))
request_object->SetPostData(std::move(post_data));
@@ -1969,9 +2029,6 @@ bool NetworkHandler::MaybeCreateProxyForInterception(
void NetworkHandler::ApplyOverrides(net::HttpRequestHeaders* headers,
bool* skip_service_worker,
bool* disable_cache) {
- headers->SetHeader(kDevToolsEmulateNetworkConditionsClientId, host_id_);
- if (!user_agent_.empty())
- headers->SetHeader(net::HttpRequestHeaders::kUserAgent, user_agent_);
for (auto& entry : extra_headers_)
headers->SetHeader(entry.first, entry.second);
*skip_service_worker |= bypass_service_worker_;
@@ -2011,11 +2068,11 @@ const char* ResourceTypeToString(ResourceType resource_type) {
case RESOURCE_TYPE_XHR:
return protocol::Page::ResourceTypeEnum::XHR;
case RESOURCE_TYPE_PING:
- return protocol::Page::ResourceTypeEnum::Other;
+ return protocol::Page::ResourceTypeEnum::Ping;
case RESOURCE_TYPE_SERVICE_WORKER:
return protocol::Page::ResourceTypeEnum::Other;
case RESOURCE_TYPE_CSP_REPORT:
- return protocol::Page::ResourceTypeEnum::Other;
+ return protocol::Page::ResourceTypeEnum::CSPViolationReport;
case RESOURCE_TYPE_PLUGIN_RESOURCE:
return protocol::Page::ResourceTypeEnum::Other;
default:
@@ -2046,7 +2103,9 @@ void NetworkHandler::SetNetworkConditions(
network::mojom::NetworkContext* context =
storage_partition_->GetNetworkContext();
bool offline = conditions ? conditions->offline : false;
- context->SetNetworkConditions(host_id_, std::move(conditions));
+
+ if (!devtools_token_.is_empty())
+ context->SetNetworkConditions(devtools_token_, std::move(conditions));
if (offline == !!background_sync_restorer_)
return;
diff --git a/chromium/content/browser/devtools/protocol/network_handler.h b/chromium/content/browser/devtools/protocol/network_handler.h
index 121d24f0bf5..e83b50cad5b 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.h
+++ b/chromium/content/browser/devtools/protocol/network_handler.h
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
+#include "base/unguessable_token.h"
#include "content/browser/devtools/devtools_url_loader_interceptor.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/network.h"
@@ -21,14 +22,11 @@
#include "net/cookies/canonical_cookie.h"
#include "services/network/public/mojom/network_service.mojom.h"
-namespace base {
-class UnguessableToken;
-};
-
namespace net {
class HttpRequestHeaders;
class URLRequest;
class SSLInfo;
+class X509Certificate;
} // namespace net
namespace network {
@@ -46,10 +44,11 @@ class InterceptionHandle;
class NavigationHandle;
class NavigationRequest;
class NavigationThrottle;
-class SignedExchangeHeader;
+class SignedExchangeEnvelope;
class StoragePartition;
struct GlobalRequestID;
struct InterceptedRequestInfo;
+struct SignedExchangeError;
namespace protocol {
class BackgroundSyncRestorer;
@@ -57,7 +56,9 @@ class BackgroundSyncRestorer;
class NetworkHandler : public DevToolsDomainHandler,
public Network::Backend {
public:
- NetworkHandler(const std::string& host_id, DevToolsIOContext* io_context);
+ NetworkHandler(const std::string& host_id,
+ const base::UnguessableToken& devtools_token,
+ DevToolsIOContext* io_context);
~NetworkHandler() override;
static std::vector<NetworkHandler*> ForAgentHost(DevToolsAgentHostImpl* host);
@@ -101,7 +102,6 @@ class NetworkHandler : public DevToolsDomainHandler,
std::unique_ptr<protocol::Array<Network::CookieParam>> cookies,
std::unique_ptr<SetCookiesCallback> callback) override;
- Response SetUserAgentOverride(const std::string& user_agent) override;
Response SetExtraHTTPHeaders(
std::unique_ptr<Network::Headers> headers) override;
Response CanEmulateNetworkConditions(bool* result) override;
@@ -166,19 +166,21 @@ class NetworkHandler : public DevToolsDomainHandler,
base::Optional<const base::UnguessableToken> devtools_navigation_token,
const GURL& outer_request_url,
const network::ResourceResponseHead& outer_response,
- const base::Optional<SignedExchangeHeader>& header,
+ const base::Optional<SignedExchangeEnvelope>& header,
+ const scoped_refptr<net::X509Certificate>& certificate,
const base::Optional<net::SSLInfo>& ssl_info,
- const std::vector<std::string>& error_messages);
+ const std::vector<SignedExchangeError>& errors);
bool enabled() const { return enabled_; }
Network::Frontend* frontend() const { return frontend_.get(); }
- static GURL ClearUrlRef(const GURL& url);
+ static std::string ExtractFragment(const GURL& url, std::string* fragment);
static std::unique_ptr<Network::Request> CreateRequestFromResourceRequest(
const network::ResourceRequest& request);
static std::unique_ptr<Network::Request> CreateRequestFromURLRequest(
- const net::URLRequest* request);
+ const net::URLRequest* request,
+ const std::string& cookie);
std::unique_ptr<NavigationThrottle> CreateThrottleForNavigation(
NavigationHandle* navigation_handle);
@@ -197,7 +199,10 @@ class NetworkHandler : public DevToolsDomainHandler,
mojo::ScopedDataPipeConsumerHandle pipe,
const std::string& mime_type);
+ // TODO(dgozman): Remove this.
const std::string host_id_;
+
+ const base::UnguessableToken devtools_token_;
DevToolsIOContext* const io_context_;
std::unique_ptr<Network::Frontend> frontend_;
@@ -205,7 +210,6 @@ class NetworkHandler : public DevToolsDomainHandler,
StoragePartition* storage_partition_;
RenderFrameHostImpl* host_;
bool enabled_;
- std::string user_agent_;
std::vector<std::pair<std::string, std::string>> extra_headers_;
std::unique_ptr<InterceptionHandle> interception_handle_;
std::unique_ptr<DevToolsURLLoaderInterceptor> url_loader_interceptor_;
diff --git a/chromium/content/browser/devtools/protocol/page_handler.cc b/chromium/content/browser/devtools/protocol/page_handler.cc
index 7e497a0402b..a55920d878a 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.cc
+++ b/chromium/content/browser/devtools/protocol/page_handler.cc
@@ -153,11 +153,12 @@ gfx::Size DetermineSnapshotSize(const gfx::Size& surface_size,
return gfx::ToRoundedSize(gfx::ScaleSize(gfx::SizeF(surface_size), scale));
}
-#if !defined(OS_ANDROID)
void GetMetadataFromFrame(const media::VideoFrame& frame,
double* device_scale_factor,
double* page_scale_factor,
- gfx::Vector2dF* root_scroll_offset) {
+ gfx::Vector2dF* root_scroll_offset,
+ double* top_controls_height,
+ double* top_controls_shown_ratio) {
// Get metadata from |frame| and ensure that no metadata is missing.
bool success = true;
double root_scroll_offset_x, root_scroll_offset_y;
@@ -169,12 +170,16 @@ void GetMetadataFromFrame(const media::VideoFrame& frame,
media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_X, &root_scroll_offset_x);
success &= frame.metadata()->GetDouble(
media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_Y, &root_scroll_offset_y);
+ success &= frame.metadata()->GetDouble(
+ media::VideoFrameMetadata::TOP_CONTROLS_HEIGHT, top_controls_height);
+ success &= frame.metadata()->GetDouble(
+ media::VideoFrameMetadata::TOP_CONTROLS_SHOWN_RATIO,
+ top_controls_shown_ratio);
DCHECK(success);
root_scroll_offset->set_x(root_scroll_offset_x);
root_scroll_offset->set_y(root_scroll_offset_y);
}
-#endif // !defined(OS_ANDROID)
} // namespace
@@ -191,15 +196,12 @@ PageHandler::PageHandler(EmulationHandler* emulation_handler)
session_id_(0),
frame_counter_(0),
frames_in_flight_(0),
-#if !defined(OS_ANDROID)
video_consumer_(nullptr),
last_surface_size_(gfx::Size()),
-#endif // !defined(OS_ANDROID)
host_(nullptr),
emulation_handler_(emulation_handler),
observer_(this),
weak_factory_(this) {
-#if !defined(OS_ANDROID)
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
base::FeatureList::IsEnabled(
features::kUseVideoCaptureApiForDevToolsSnapshots)) {
@@ -207,7 +209,6 @@ PageHandler::PageHandler(EmulationHandler* emulation_handler)
base::BindRepeating(&PageHandler::OnFrameFromVideoConsumer,
weak_factory_.GetWeakPtr()));
}
-#endif // !defined(OS_ANDROID)
DCHECK(emulation_handler_);
}
@@ -252,12 +253,10 @@ void PageHandler::SetRenderer(int process_host_id,
if (widget_host)
observer_.Add(widget_host);
-#if !defined(OS_ANDROID)
if (video_consumer_ && frame_host) {
video_consumer_->SetFrameSinkId(
frame_host->GetRenderWidgetHost()->GetFrameSinkId());
}
-#endif // !defined(OS_ANDROID)
}
void PageHandler::Wire(UberDispatcher* dispatcher) {
@@ -267,6 +266,9 @@ void PageHandler::Wire(UberDispatcher* dispatcher) {
void PageHandler::OnSwapCompositorFrame(
viz::CompositorFrameMetadata frame_metadata) {
+ if (video_consumer_)
+ return;
+
last_compositor_frame_metadata_ = std::move(frame_metadata);
has_compositor_frame_metadata_ = true;
@@ -365,10 +367,8 @@ Response PageHandler::Disable() {
enabled_ = false;
screencast_enabled_ = false;
-#if !defined(OS_ANDROID)
if (video_consumer_)
video_consumer_->StopCapture();
-#endif // !defined(OS_ANDROID)
if (!pending_dialog_.is_null()) {
WebContentsImpl* web_contents = GetWebContents();
@@ -768,7 +768,6 @@ Response PageHandler::StartScreencast(Maybe<std::string> format,
bool visible = !widget_host->is_hidden();
NotifyScreencastVisibility(visible);
-#if !defined(OS_ANDROID)
if (video_consumer_) {
gfx::Size surface_size = gfx::Size();
RenderWidgetHostViewBase* const view =
@@ -786,7 +785,6 @@ Response PageHandler::StartScreencast(Maybe<std::string> format,
video_consumer_->StartCapture();
return Response::FallThrough();
}
-#endif // !defined(OS_ANDROID)
if (!visible)
return Response::FallThrough();
@@ -794,18 +792,15 @@ Response PageHandler::StartScreencast(Maybe<std::string> format,
if (has_compositor_frame_metadata_) {
InnerSwapCompositorFrame();
} else {
- widget_host->Send(new ViewMsg_ForceRedraw(widget_host->GetRoutingID(),
- ui::LatencyInfo()));
+ widget_host->Send(new ViewMsg_ForceRedraw(widget_host->GetRoutingID(), 0));
}
return Response::FallThrough();
}
Response PageHandler::StopScreencast() {
screencast_enabled_ = false;
-#if !defined(OS_ANDROID)
if (video_consumer_)
video_consumer_->StopCapture();
-#endif // !defined(OS_ANDROID)
return Response::FallThrough();
}
@@ -969,7 +964,6 @@ void PageHandler::InnerSwapCompositorFrame() {
frames_in_flight_++;
}
-#if !defined(OS_ANDROID)
void PageHandler::OnFrameFromVideoConsumer(
scoped_refptr<media::VideoFrame> frame) {
if (!host_)
@@ -995,24 +989,21 @@ void PageHandler::OnFrameFromVideoConsumer(
}
double device_scale_factor, page_scale_factor;
+ double top_controls_height, top_controls_shown_ratio;
gfx::Vector2dF root_scroll_offset;
GetMetadataFromFrame(*frame, &device_scale_factor, &page_scale_factor,
- &root_scroll_offset);
- // Top controls are only present on Android. Hence use default values of 0.f.
- // TODO(dgozman): fix this when viz capture is available on Android.
- const float kTopControlsHeight = 0.f;
- const float kTopControlsShownRatio = 0.f;
+ &root_scroll_offset, &top_controls_height,
+ &top_controls_shown_ratio);
std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata =
- BuildScreencastFrameMetadata(surface_size, device_scale_factor,
- page_scale_factor, root_scroll_offset,
- kTopControlsHeight, kTopControlsShownRatio);
+ BuildScreencastFrameMetadata(
+ surface_size, device_scale_factor, page_scale_factor,
+ root_scroll_offset, top_controls_height, top_controls_shown_ratio);
if (!page_metadata)
return;
ScreencastFrameCaptured(std::move(page_metadata),
DevToolsVideoConsumer::GetSkBitmapFromFrame(frame));
}
-#endif // !defined(OS_ANDROID)
void PageHandler::ScreencastFrameCaptured(
std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata,
@@ -1121,13 +1112,11 @@ Response PageHandler::SetWebLifecycleState(const std::string& state) {
// TODO(fmeawad): Instead of forcing a visibility change, only allow
// freezing a page if it was already hidden.
web_contents->WasHidden();
- web_contents->FreezePage();
+ web_contents->SetPageFrozen(true);
return Response::OK();
}
if (state == Page::SetWebLifecycleState::StateEnum::Active) {
- // Making the page visible should make it active as visible pages cannot be
- // frozen.
- web_contents->WasShown();
+ web_contents->SetPageFrozen(false);
return Response::OK();
}
return Response::Error("Unidentified lifecycle state");
diff --git a/chromium/content/browser/devtools/protocol/page_handler.h b/chromium/content/browser/devtools/protocol/page_handler.h
index c9c0b1f1ed4..eb6a09acea3 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.h
+++ b/chromium/content/browser/devtools/protocol/page_handler.h
@@ -19,6 +19,7 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
+#include "content/browser/devtools/devtools_video_consumer.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
#include "content/browser/devtools/protocol/page.h"
@@ -28,10 +29,6 @@
#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
#include "url/gurl.h"
-#if !defined(OS_ANDROID)
-#include "content/browser/devtools/devtools_video_consumer.h"
-#endif // !defined(OS_ANDROID)
-
class SkBitmap;
namespace base {
@@ -162,9 +159,7 @@ class PageHandler : public DevToolsDomainHandler,
WebContentsImpl* GetWebContents();
void NotifyScreencastVisibility(bool visible);
void InnerSwapCompositorFrame();
-#if !defined(OS_ANDROID)
void OnFrameFromVideoConsumer(scoped_refptr<media::VideoFrame> frame);
-#endif // !defined(OS_ANDROID)
void ScreencastFrameCaptured(
std::unique_ptr<Page::ScreencastFrameMetadata> metadata,
const SkBitmap& bitmap);
@@ -206,7 +201,6 @@ class PageHandler : public DevToolsDomainHandler,
int frame_counter_;
int frames_in_flight_;
-#if !defined(OS_ANDROID)
// |video_consumer_| consumes video frames from FrameSinkVideoCapturerImpl,
// and provides PageHandler with these frames via OnFrameFromVideoConsumer.
// This is only used if Viz is enabled and if OS is not Android.
@@ -215,7 +209,6 @@ class PageHandler : public DevToolsDomainHandler,
// The last surface size used to determine if frames with new sizes need
// to be requested. This changes due to window resizing.
gfx::Size last_surface_size_;
-#endif // !defined(OS_ANDROID)
RenderFrameHostImpl* host_;
EmulationHandler* emulation_handler_;
diff --git a/chromium/content/browser/devtools/protocol/service_worker_handler.cc b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
index 5449b409717..77d1cc9fda7 100644
--- a/chromium/content/browser/devtools/protocol/service_worker_handler.cc
+++ b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
@@ -114,9 +114,10 @@ void DidFindRegistrationForDispatchSyncEventOnIO(
scoped_refptr<BackgroundSyncContext> sync_context,
const std::string& tag,
bool last_chance,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<content::ServiceWorkerRegistration> registration) {
- if (status != SERVICE_WORKER_OK || !registration->active_version())
+ if (status != blink::ServiceWorkerStatusCode::kOk ||
+ !registration->active_version())
return;
BackgroundSyncManager* background_sync_manager =
sync_context->background_sync_manager();
@@ -127,7 +128,7 @@ void DidFindRegistrationForDispatchSyncEventOnIO(
tag, std::move(version), last_chance,
base::BindOnce(base::DoNothing::Once<
scoped_refptr<content::ServiceWorkerRegistration>,
- ServiceWorkerStatusCode>(),
+ blink::ServiceWorkerStatusCode>(),
std::move(registration)));
}
diff --git a/chromium/content/browser/devtools/protocol/system_info_handler.cc b/chromium/content/browser/devtools/protocol/system_info_handler.cc
index 618ad4a9f24..c6673d3451c 100644
--- a/chromium/content/browser/devtools/protocol/system_info_handler.cc
+++ b/chromium/content/browser/devtools/protocol/system_info_handler.cc
@@ -83,6 +83,10 @@ class AuxGPUInfoEnumerator : public gpu::GPUInfo::Enumerator {
void EndVideoEncodeAcceleratorSupportedProfile() override {}
+ void BeginOverlayCapability() override {}
+
+ void EndOverlayCapability() override {}
+
void BeginAuxAttributes() override {
in_aux_attributes_ = true;
}
diff --git a/chromium/content/browser/devtools/protocol/target_handler.cc b/chromium/content/browser/devtools/protocol/target_handler.cc
index 1ebf94ff0ef..1d467539ccc 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.cc
+++ b/chromium/content/browser/devtools/protocol/target_handler.cc
@@ -4,15 +4,23 @@
#include "content/browser/devtools/protocol/target_handler.h"
+#include "base/base64.h"
+#include "base/containers/flat_map.h"
#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "base/strings/stringprintf.h"
+#include "base/unguessable_token.h"
#include "base/values.h"
+#include "build/build_config.h"
+#include "content/browser/devtools/browser_devtools_agent_host.h"
#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/devtools_session.h"
+#include "content/browser/devtools/target_registry.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/devtools_agent_host_client.h"
#include "content/public/browser/navigation_throttle.h"
+#include "content/public/browser/web_contents.h"
namespace content {
namespace protocol {
@@ -21,6 +29,19 @@ namespace {
static const char kMethod[] = "method";
static const char kResumeMethod[] = "Runtime.runIfWaitingForDebugger";
+static const char kInitializerScript[] = R"(
+ (function() {
+ const bindingName = "%s";
+ const binding = window[bindingName];
+ delete window[bindingName];
+ if (window.self === window.top) {
+ window[bindingName] = {
+ onmessage: () => {},
+ send: binding
+ };
+ }
+ })();
+)";
std::unique_ptr<Target::TargetInfo> CreateInfo(DevToolsAgentHost* host) {
std::unique_ptr<Target::TargetInfo> target_info =
@@ -38,6 +59,152 @@ std::unique_ptr<Target::TargetInfo> CreateInfo(DevToolsAgentHost* host) {
return target_info;
}
+static std::string TerminationStatusToString(base::TerminationStatus status) {
+ switch (status) {
+ case base::TERMINATION_STATUS_NORMAL_TERMINATION:
+ return "normal";
+ case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
+ return "abnormal";
+ case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
+ return "killed";
+ case base::TERMINATION_STATUS_PROCESS_CRASHED:
+ return "crashed";
+ case base::TERMINATION_STATUS_STILL_RUNNING:
+ return "still running";
+#if defined(OS_CHROMEOS)
+ // Used for the case when oom-killer kills a process on ChromeOS.
+ case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
+ return "oom killed";
+#endif
+#if defined(OS_ANDROID)
+ // On Android processes are spawned from the system Zygote and we do not get
+ // the termination status. We can't know if the termination was a crash or
+ // an oom kill for sure: but we can use status of the strong process
+ // bindings as a hint.
+ case base::TERMINATION_STATUS_OOM_PROTECTED:
+ return "oom protected";
+#endif
+ case base::TERMINATION_STATUS_LAUNCH_FAILED:
+ return "failed to launch";
+ case base::TERMINATION_STATUS_OOM:
+ return "oom";
+ case base::TERMINATION_STATUS_MAX_ENUM:
+ break;
+ }
+ NOTREACHED() << "Unknown Termination Status.";
+ return "unknown";
+}
+
+class BrowserToPageConnector;
+
+base::LazyInstance<base::flat_map<DevToolsAgentHost*,
+ std::unique_ptr<BrowserToPageConnector>>>::
+ Leaky g_browser_to_page_connectors;
+
+class BrowserToPageConnector : public DevToolsAgentHostClient {
+ public:
+ BrowserToPageConnector(const std::string& binding_name,
+ DevToolsAgentHost* page_host)
+ : binding_name_(binding_name), page_host_(page_host) {
+ browser_host_ = BrowserDevToolsAgentHost::CreateForDiscovery();
+ browser_host_->AttachClient(this);
+ page_host_->AttachClient(this);
+
+ SendProtocolMessageToPage("Page.enable", std::make_unique<base::Value>());
+ SendProtocolMessageToPage("Runtime.enable",
+ std::make_unique<base::Value>());
+
+ std::unique_ptr<base::DictionaryValue> add_binding_params =
+ std::make_unique<base::DictionaryValue>();
+ add_binding_params->SetString("name", binding_name);
+ SendProtocolMessageToPage("Runtime.addBinding",
+ std::move(add_binding_params));
+
+ std::string initializer_script =
+ base::StringPrintf(kInitializerScript, binding_name.c_str());
+
+ std::unique_ptr<base::DictionaryValue> params =
+ std::make_unique<base::DictionaryValue>();
+ params->SetString("scriptSource", initializer_script);
+ SendProtocolMessageToPage("Page.addScriptToEvaluateOnLoad",
+ std::move(params));
+
+ std::unique_ptr<base::DictionaryValue> evaluate_params =
+ std::make_unique<base::DictionaryValue>();
+ evaluate_params->SetString("expression", initializer_script);
+ SendProtocolMessageToPage("Runtime.evaluate", std::move(evaluate_params));
+ g_browser_to_page_connectors.Get()[page_host_.get()].reset(this);
+ }
+
+ private:
+ void SendProtocolMessageToPage(const char* method,
+ std::unique_ptr<base::Value> params) {
+ base::DictionaryValue message;
+ message.SetInteger("id", page_message_id_++);
+ message.SetString("method", method);
+ message.Set("params", std::move(params));
+ std::string json_message;
+ base::JSONWriter::Write(message, &json_message);
+ page_host_->DispatchProtocolMessage(this, json_message);
+ }
+
+ void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
+ const std::string& message) override {
+ if (agent_host == page_host_.get()) {
+ std::unique_ptr<base::Value> value = base::JSONReader::Read(message);
+ if (!value || !value->is_dict())
+ return;
+ // Make sure this is a binding call.
+ base::Value* method = value->FindKey("method");
+ if (!method || !method->is_string() ||
+ method->GetString() != "Runtime.bindingCalled")
+ return;
+ base::Value* params = value->FindKey("params");
+ if (!params || !params->is_dict())
+ return;
+ base::Value* name = params->FindKey("name");
+ if (!name || !name->is_string() || name->GetString() != binding_name_)
+ return;
+ base::Value* payload = params->FindKey("payload");
+ if (!payload || !payload->is_string())
+ return;
+ browser_host_->DispatchProtocolMessage(this, payload->GetString());
+ return;
+ }
+ DCHECK(agent_host == browser_host_.get());
+
+ std::string encoded;
+ base::Base64Encode(message, &encoded);
+ std::string eval_code = "window." + binding_name_ + ".onmessage(atob(\"";
+ std::string eval_suffix = "\"))";
+ eval_code.reserve(eval_code.size() + encoded.size() + eval_suffix.size());
+ eval_code.append(encoded);
+ eval_code.append(eval_suffix);
+
+ std::unique_ptr<base::DictionaryValue> params =
+ std::make_unique<base::DictionaryValue>();
+ params->SetString("expression", eval_code);
+ SendProtocolMessageToPage("Runtime.evaluate", std::move(params));
+ }
+
+ void AgentHostClosed(DevToolsAgentHost* agent_host) override {
+ if (agent_host == browser_host_.get()) {
+ page_host_->DetachClient(this);
+ } else {
+ DCHECK(agent_host == page_host_.get());
+ browser_host_->DetachClient(this);
+ }
+ g_browser_to_page_connectors.Get().erase(page_host_.get());
+ }
+
+ std::string binding_name_;
+ scoped_refptr<DevToolsAgentHost> browser_host_;
+ scoped_refptr<DevToolsAgentHost> page_host_;
+ int page_message_id_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserToPageConnector);
+};
+
} // namespace
// Throttle is owned externally by the navigation subsystem.
@@ -49,9 +216,11 @@ class TargetHandler::Throttle : public content::NavigationThrottle {
void Clear();
// content::NavigationThrottle implementation:
NavigationThrottle::ThrottleCheckResult WillProcessResponse() override;
+ NavigationThrottle::ThrottleCheckResult WillFailRequest() override;
const char* GetNameForLogging() override;
private:
+ NavigationThrottle::ThrottleCheckResult MaybeAttach();
void CleanupPointers();
base::WeakPtr<protocol::TargetHandler> target_handler_;
@@ -64,28 +233,41 @@ class TargetHandler::Session : public DevToolsAgentHostClient {
public:
static std::string Attach(TargetHandler* handler,
DevToolsAgentHost* agent_host,
- bool waiting_for_debugger) {
- std::string id = base::StringPrintf("%s:%d", agent_host->GetId().c_str(),
- ++handler->last_session_id_);
- Session* session = new Session(handler, agent_host, id);
+ bool waiting_for_debugger,
+ bool flatten_protocol) {
+ std::string id = base::UnguessableToken::Create().ToString();
+ Session* session = new Session(handler, agent_host, id, flatten_protocol);
handler->attached_sessions_[id].reset(session);
- agent_host->AttachClient(session);
+ DevToolsAgentHostImpl* agent_host_impl =
+ static_cast<DevToolsAgentHostImpl*>(agent_host);
+ if (flatten_protocol) {
+ handler->target_registry_->AttachSubtargetSession(id, agent_host_impl,
+ session);
+ } else {
+ agent_host_impl->AttachClient(session);
+ }
handler->frontend_->AttachedToTarget(id, CreateInfo(agent_host),
waiting_for_debugger);
return id;
}
~Session() override {
- if (agent_host_)
- agent_host_->DetachClient(this);
+ if (!agent_host_)
+ return;
+ if (handler_->target_registry_)
+ handler_->target_registry_->DetachSubtargetSession(id_);
+ agent_host_->DetachClient(this);
}
void Detach(bool host_closed) {
handler_->frontend_->DetachedFromTarget(id_, agent_host_->GetId());
if (host_closed)
handler_->auto_attacher_.AgentHostClosed(agent_host_.get());
- else
+ else {
+ if (handler_->target_registry_)
+ handler_->target_registry_->DetachSubtargetSession(id_);
agent_host_->DetachClient(this);
+ }
handler_->auto_attached_sessions_.erase(agent_host_.get());
agent_host_ = nullptr;
handler_->attached_sessions_.erase(id_);
@@ -114,15 +296,26 @@ class TargetHandler::Session : public DevToolsAgentHostClient {
}
private:
+ friend class TargetHandler;
+
Session(TargetHandler* handler,
DevToolsAgentHost* agent_host,
- const std::string& id)
- : handler_(handler), agent_host_(agent_host), id_(id) {}
+ const std::string& id,
+ bool flatten_protocol)
+ : handler_(handler),
+ agent_host_(agent_host),
+ id_(id),
+ flatten_protocol_(flatten_protocol) {}
// DevToolsAgentHostClient implementation.
void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
const std::string& message) override {
DCHECK(agent_host == agent_host_.get());
+ if (flatten_protocol_) {
+ handler_->target_registry_->SendMessageToClient(id_, message);
+ return;
+ }
+
handler_->frontend_->ReceivedMessageFromTarget(id_, message,
agent_host_->GetId());
}
@@ -135,6 +328,7 @@ class TargetHandler::Session : public DevToolsAgentHostClient {
TargetHandler* handler_;
scoped_refptr<DevToolsAgentHost> agent_host_;
std::string id_;
+ bool flatten_protocol_;
Throttle* throttle_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(Session);
@@ -166,6 +360,15 @@ void TargetHandler::Throttle::CleanupPointers() {
NavigationThrottle::ThrottleCheckResult
TargetHandler::Throttle::WillProcessResponse() {
+ return MaybeAttach();
+}
+
+NavigationThrottle::ThrottleCheckResult
+TargetHandler::Throttle::WillFailRequest() {
+ return MaybeAttach();
+}
+
+NavigationThrottle::ThrottleCheckResult TargetHandler::Throttle::MaybeAttach() {
if (!target_handler_)
return PROCEED;
agent_host_ = target_handler_->auto_attacher_.AutoAttachToFrame(
@@ -189,13 +392,17 @@ void TargetHandler::Throttle::Clear() {
}
}
-TargetHandler::TargetHandler(bool browser_only)
+TargetHandler::TargetHandler(bool browser_only,
+ const std::string& owner_target_id,
+ TargetRegistry* target_registry)
: DevToolsDomainHandler(Target::Metainfo::domainName),
auto_attacher_(
base::Bind(&TargetHandler::AutoAttach, base::Unretained(this)),
base::Bind(&TargetHandler::AutoDetach, base::Unretained(this))),
discover_(false),
browser_only_(browser_only),
+ owner_target_id_(owner_target_id),
+ target_registry_(target_registry),
weak_factory_(this) {}
TargetHandler::~TargetHandler() {
@@ -247,7 +454,8 @@ void TargetHandler::ClearThrottles() {
void TargetHandler::AutoAttach(DevToolsAgentHost* host,
bool waiting_for_debugger) {
- std::string session_id = Session::Attach(this, host, waiting_for_debugger);
+ std::string session_id =
+ Session::Attach(this, host, waiting_for_debugger, false);
auto_attached_sessions_[host] = attached_sessions_[session_id].get();
}
@@ -323,13 +531,27 @@ Response TargetHandler::SetRemoteLocations(
}
Response TargetHandler::AttachToTarget(const std::string& target_id,
+ Maybe<bool> flatten,
std::string* out_session_id) {
// TODO(dgozman): only allow reported hosts.
scoped_refptr<DevToolsAgentHost> agent_host =
DevToolsAgentHost::GetForId(target_id);
if (!agent_host)
return Response::InvalidParams("No target with given id found");
- *out_session_id = Session::Attach(this, agent_host.get(), false);
+ if (flatten.fromMaybe(false) && !target_registry_) {
+ return Response::InvalidParams(
+ "Will only provide flatten access for browser endpoint");
+ }
+ *out_session_id =
+ Session::Attach(this, agent_host.get(), false, flatten.fromMaybe(false));
+ return Response::OK();
+}
+
+Response TargetHandler::AttachToBrowserTarget(std::string* out_session_id) {
+ scoped_refptr<DevToolsAgentHost> agent_host =
+ DevToolsAgentHost::CreateForBrowser(
+ nullptr, DevToolsAgentHost::CreateServerSocketCallback());
+ *out_session_id = Session::Attach(this, agent_host.get(), false, true);
return Response::OK();
}
@@ -352,13 +574,20 @@ Response TargetHandler::SendMessageToTarget(const std::string& message,
FindSession(std::move(session_id), std::move(target_id), &session, true);
if (!response.isSuccess())
return response;
+ if (session->flatten_protocol_) {
+ return Response::Error(
+ "When using flat protocol, messages are routed to the target "
+ "via the sessionId attribute.");
+ }
session->SendMessageToAgentHost(message);
return Response::OK();
}
Response TargetHandler::GetTargetInfo(
- const std::string& target_id,
+ Maybe<std::string> maybe_target_id,
std::unique_ptr<Target::TargetInfo>* target_info) {
+ const std::string& target_id =
+ maybe_target_id.isJust() ? maybe_target_id.fromJust() : owner_target_id_;
// TODO(dgozman): only allow reported hosts.
scoped_refptr<DevToolsAgentHost> agent_host(
DevToolsAgentHost::GetForId(target_id));
@@ -388,6 +617,32 @@ Response TargetHandler::CloseTarget(const std::string& target_id,
return Response::OK();
}
+Response TargetHandler::ExposeDevToolsProtocol(
+ const std::string& target_id,
+ Maybe<std::string> binding_name) {
+ if (!browser_only_) {
+ return Response::InvalidParams(
+ "Cannot grant remote debugging capability from non-browser session.");
+ }
+ scoped_refptr<DevToolsAgentHost> agent_host =
+ DevToolsAgentHost::GetForId(target_id);
+ if (!agent_host)
+ return Response::InvalidParams("No target with given id found");
+
+ if (g_browser_to_page_connectors.Get()[agent_host.get()]) {
+ return Response::Error(base::StringPrintf(
+ "Target with id %s is already granted remote debugging bindings.",
+ target_id.c_str()));
+ }
+ if (!agent_host->GetWebContents()) {
+ return Response::Error(
+ "RemoteDebuggingBinding can be granted only to page targets");
+ }
+
+ new BrowserToPageConnector(binding_name.fromMaybe("cdp"), agent_host.get());
+ return Response::OK();
+}
+
Response TargetHandler::CreateBrowserContext(std::string* out_context_id) {
return Response::Error("Not supported");
}
@@ -467,5 +722,15 @@ void TargetHandler::DevToolsAgentHostDetached(DevToolsAgentHost* host) {
frontend_->TargetInfoChanged(CreateInfo(host));
}
+void TargetHandler::DevToolsAgentHostCrashed(DevToolsAgentHost* host,
+ base::TerminationStatus status) {
+ if (reported_hosts_.find(host) == reported_hosts_.end())
+ return;
+ frontend_->TargetCrashed(host->GetId(), TerminationStatusToString(status),
+ host->GetWebContents()
+ ? host->GetWebContents()->GetCrashedErrorCode()
+ : 0);
+}
+
} // namespace protocol
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/target_handler.h b/chromium/content/browser/devtools/protocol/target_handler.h
index 7d75e62ad4c..ba5702adbd0 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.h
+++ b/chromium/content/browser/devtools/protocol/target_handler.h
@@ -21,6 +21,7 @@ class DevToolsAgentHostImpl;
class NavigationHandle;
class NavigationThrottle;
class RenderFrameHostImpl;
+class TargetRegistry;
namespace protocol {
@@ -28,7 +29,9 @@ class TargetHandler : public DevToolsDomainHandler,
public Target::Backend,
public DevToolsAgentHostObserver {
public:
- explicit TargetHandler(bool browser_only);
+ TargetHandler(bool browser_only,
+ const std::string& owner_target_id,
+ TargetRegistry* target_registry);
~TargetHandler() override;
static std::vector<TargetHandler*> ForAgentHost(DevToolsAgentHostImpl* host);
@@ -50,18 +53,22 @@ class TargetHandler : public DevToolsDomainHandler,
Response SetRemoteLocations(
std::unique_ptr<protocol::Array<Target::RemoteLocation>>) override;
Response AttachToTarget(const std::string& target_id,
+ Maybe<bool> flatten,
std::string* out_session_id) override;
+ Response AttachToBrowserTarget(std::string* out_session_id) override;
Response DetachFromTarget(Maybe<std::string> session_id,
Maybe<std::string> target_id) override;
Response SendMessageToTarget(const std::string& message,
Maybe<std::string> session_id,
Maybe<std::string> target_id) override;
Response GetTargetInfo(
- const std::string& target_id,
+ Maybe<std::string> target_id,
std::unique_ptr<Target::TargetInfo>* target_info) override;
Response ActivateTarget(const std::string& target_id) override;
Response CloseTarget(const std::string& target_id,
bool* out_success) override;
+ Response ExposeDevToolsProtocol(const std::string& target_id,
+ Maybe<std::string> binding_name) override;
Response CreateBrowserContext(std::string* out_context_id) override;
Response DisposeBrowserContext(const std::string& context_id) override;
Response GetBrowserContexts(
@@ -95,6 +102,8 @@ class TargetHandler : public DevToolsDomainHandler,
void DevToolsAgentHostDestroyed(DevToolsAgentHost* agent_host) override;
void DevToolsAgentHostAttached(DevToolsAgentHost* agent_host) override;
void DevToolsAgentHostDetached(DevToolsAgentHost* agent_host) override;
+ void DevToolsAgentHostCrashed(DevToolsAgentHost* agent_host,
+ base::TerminationStatus status) override;
std::unique_ptr<Target::Frontend> frontend_;
TargetAutoAttacher auto_attacher_;
@@ -102,8 +111,9 @@ class TargetHandler : public DevToolsDomainHandler,
std::map<std::string, std::unique_ptr<Session>> attached_sessions_;
std::map<DevToolsAgentHost*, Session*> auto_attached_sessions_;
std::set<DevToolsAgentHost*> reported_hosts_;
- int last_session_id_ = 0;
bool browser_only_;
+ std::string owner_target_id_;
+ TargetRegistry* target_registry_;
base::flat_set<Throttle*> throttles_;
base::WeakPtrFactory<TargetHandler> weak_factory_;
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.cc b/chromium/content/browser/devtools/protocol/tracing_handler.cc
index 3435d90b298..9546e5dd5a3 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.cc
@@ -42,6 +42,10 @@
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
#include "services/tracing/public/mojom/constants.mojom.h"
+#ifdef OS_ANDROID
+#include "content/browser/renderer_host/compositor_impl_android.h"
+#endif
+
namespace content {
namespace protocol {
@@ -190,15 +194,15 @@ void FillFrameData(base::trace_event::TracedValue* data,
node->parent()->devtools_frame_token().ToString());
if (frame_host) {
RenderProcessHost* process_host = frame_host->GetProcess();
- base::ProcessId process_id = process_host->GetProcess().Pid();
- if (process_id == base::kNullProcessId) {
+ const base::Process& process_handle = process_host->GetProcess();
+ if (!process_handle.IsValid()) {
data->SetString("processPseudoId", GetProcessHostHex(process_host));
frame_host->GetProcess()->PostTaskWhenProcessIsReady(
base::BindOnce(&SendProcessReadyInBrowserEvent,
node->devtools_frame_token(), process_host));
} else {
// Cast process id to int to be compatible with tracing.
- data->SetInteger("processId", static_cast<int>(process_id));
+ data->SetInteger("processId", static_cast<int>(process_handle.Pid()));
}
}
}
@@ -214,17 +218,23 @@ TracingHandler::TracingHandler(FrameTreeNode* frame_tree_node_,
return_as_stream_(false),
gzip_compression_(false),
weak_factory_(this) {
- if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
+ bool use_video_capture_api =
+ base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
base::FeatureList::IsEnabled(
- features::kUseVideoCaptureApiForDevToolsSnapshots)) {
+ features::kUseVideoCaptureApiForDevToolsSnapshots);
+#ifdef OS_ANDROID
+ // Video capture API cannot be used on Android WebView.
+ if (!CompositorImpl::IsInitialized())
+ use_video_capture_api = false;
+#endif
+ if (use_video_capture_api) {
video_consumer_ =
std::make_unique<DevToolsVideoConsumer>(base::BindRepeating(
&TracingHandler::OnFrameFromVideoConsumer, base::Unretained(this)));
}
}
-TracingHandler::~TracingHandler() {
-}
+TracingHandler::~TracingHandler() = default;
// static
std::vector<TracingHandler*> TracingHandler::ForAgentHost(
@@ -386,17 +396,17 @@ void TracingHandler::Start(Maybe<std::string> categories,
if (buffer_usage_reporting_interval.isJust())
SetupTimer(buffer_usage_reporting_interval.fromJust());
- base::trace_event::TraceConfig trace_config;
+ trace_config_ = base::trace_event::TraceConfig();
if (config.isJust()) {
std::unique_ptr<base::Value> value =
protocol::toBaseValue(config.fromJust()->toValue().get(), 1000);
if (value && value->is_dict()) {
- trace_config = GetTraceConfigFromDevToolsConfig(
+ trace_config_ = GetTraceConfigFromDevToolsConfig(
*static_cast<base::DictionaryValue*>(value.get()));
}
} else if (categories.isJust() || options.isJust()) {
- trace_config = base::trace_event::TraceConfig(
- categories.fromMaybe(""), options.fromMaybe(""));
+ trace_config_ = base::trace_event::TraceConfig(categories.fromMaybe(""),
+ options.fromMaybe(""));
}
// If inspected target is a render process Tracing.start will be handled by
@@ -404,11 +414,57 @@ void TracingHandler::Start(Maybe<std::string> categories,
if (frame_tree_node_)
callback->fallThrough();
+ SetupProcessFilter(nullptr);
+
TracingController::GetInstance()->StartTracing(
- trace_config,
- base::Bind(&TracingHandler::OnRecordingEnabled,
- weak_factory_.GetWeakPtr(),
- base::Passed(std::move(callback))));
+ trace_config_, base::BindRepeating(&TracingHandler::OnRecordingEnabled,
+ weak_factory_.GetWeakPtr(),
+ base::Passed(std::move(callback))));
+}
+
+void TracingHandler::SetupProcessFilter(
+ RenderFrameHost* new_render_frame_host) {
+ if (!frame_tree_node_)
+ return;
+
+ base::ProcessId browser_pid = base::Process::Current().Pid();
+ std::unordered_set<base::ProcessId> included_process_ids({browser_pid});
+ if (new_render_frame_host)
+ AppendProcessId(new_render_frame_host, &included_process_ids);
+ for (FrameTreeNode* node :
+ frame_tree_node_->frame_tree()->SubtreeNodes(frame_tree_node_)) {
+ RenderFrameHost* frame_host = node->current_frame_host();
+ if (frame_host)
+ AppendProcessId(frame_host, &included_process_ids);
+ }
+ trace_config_.SetProcessFilterConfig(
+ base::trace_event::TraceConfig::ProcessFilterConfig(
+ included_process_ids));
+}
+
+void TracingHandler::AppendProcessId(
+ RenderFrameHost* render_frame_host,
+ std::unordered_set<base::ProcessId>* process_set) {
+ RenderProcessHost* process_host = render_frame_host->GetProcess();
+ if (process_host->GetProcess().IsValid()) {
+ process_set->insert(process_host->GetProcess().Pid());
+ } else {
+ process_host->PostTaskWhenProcessIsReady(
+ base::BindOnce(&TracingHandler::OnProcessReady,
+ weak_factory_.GetWeakPtr(), process_host));
+ }
+}
+
+void TracingHandler::OnProcessReady(RenderProcessHost* process_host) {
+ if (!did_initiate_recording_)
+ return;
+ std::unordered_set<base::ProcessId> included_process_ids(
+ {process_host->GetProcess().Pid()});
+ trace_config_.SetProcessFilterConfig(
+ base::trace_event::TraceConfig::ProcessFilterConfig(
+ included_process_ids));
+ TracingController::GetInstance()->StartTracing(
+ trace_config_, base::RepeatingCallback<void()>());
}
void TracingHandler::End(std::unique_ptr<EndCallback> callback) {
@@ -474,6 +530,8 @@ void TracingHandler::OnRecordingEnabled(
void TracingHandler::OnBufferUsage(float percent_full,
size_t approximate_event_count) {
+ if (!did_initiate_recording_)
+ return;
// TODO(crbug426117): remove set_value once all clients have switched to
// the new interface of the event.
frontend_->BufferUsage(percent_full, approximate_event_count, percent_full);
@@ -549,14 +607,13 @@ void TracingHandler::SetupTimer(double usage_reporting_interval) {
base::TimeDelta interval = base::TimeDelta::FromMilliseconds(
std::ceil(usage_reporting_interval));
- buffer_usage_poll_timer_.reset(new base::Timer(
+ buffer_usage_poll_timer_.reset(new base::RepeatingTimer());
+ buffer_usage_poll_timer_->Start(
FROM_HERE, interval,
base::Bind(base::IgnoreResult(&TracingController::GetTraceBufferUsage),
base::Unretained(TracingController::GetInstance()),
base::Bind(&TracingHandler::OnBufferUsage,
- weak_factory_.GetWeakPtr())),
- true));
- buffer_usage_poll_timer_->Reset();
+ weak_factory_.GetWeakPtr())));
}
void TracingHandler::StopTracing(
@@ -605,6 +662,10 @@ void TracingHandler::ReadyToCommitNavigation(
TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
"FrameCommittedInBrowser", TRACE_EVENT_SCOPE_THREAD,
"data", std::move(data));
+
+ SetupProcessFilter(navigation_handle->GetRenderFrameHost());
+ TracingController::GetInstance()->StartTracing(
+ trace_config_, base::RepeatingCallback<void()>());
}
void TracingHandler::FrameDeleted(RenderFrameHostImpl* frame_host) {
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.h b/chromium/content/browser/devtools/protocol/tracing_handler.h
index 7f21754cc10..82f11ef2a25 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.h
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.h
@@ -11,6 +11,7 @@
#include <memory>
#include <set>
#include <string>
+#include <unordered_set>
#include <vector>
#include "base/gtest_prod_util.h"
@@ -23,7 +24,7 @@
#include "content/public/browser/tracing_controller.h"
namespace base {
-class Timer;
+class RepeatingTimer;
}
namespace media {
@@ -37,6 +38,8 @@ class DevToolsVideoConsumer;
class DevToolsIOContext;
class FrameTreeNode;
class NavigationHandleImpl;
+class RenderFrameHost;
+class RenderProcessHost;
namespace protocol {
@@ -113,8 +116,12 @@ class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend {
CONTENT_EXPORT static base::trace_event::TraceConfig
GetTraceConfigFromDevToolsConfig(
const base::DictionaryValue& devtools_config);
+ void SetupProcessFilter(RenderFrameHost*);
+ void AppendProcessId(RenderFrameHost*,
+ std::unordered_set<base::ProcessId>* process_set);
+ void OnProcessReady(RenderProcessHost*);
- std::unique_ptr<base::Timer> buffer_usage_poll_timer_;
+ std::unique_ptr<base::RepeatingTimer> buffer_usage_poll_timer_;
std::unique_ptr<Tracing::Frontend> frontend_;
DevToolsIOContext* io_context_;
@@ -125,6 +132,7 @@ class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend {
TraceDataBufferState trace_data_buffer_state_;
std::unique_ptr<DevToolsVideoConsumer> video_consumer_;
int number_of_screenshots_from_video_consumer_ = 0;
+ base::trace_event::TraceConfig trace_config_;
base::WeakPtrFactory<TracingHandler> weak_factory_;
FRIEND_TEST_ALL_PREFIXES(TracingHandlerTest,
diff --git a/chromium/content/browser/devtools/protocol_config.json b/chromium/content/browser/devtools/protocol_config.json
index 90c595d05dc..0919b220303 100644
--- a/chromium/content/browser/devtools/protocol_config.json
+++ b/chromium/content/browser/devtools/protocol_config.json
@@ -20,7 +20,7 @@
},
{
"domain": "Emulation",
- "include": ["setGeolocationOverride", "clearGeolocationOverride", "setEmitTouchEventsForMouse", "canEmulate", "setDeviceMetricsOverride", "clearDeviceMetricsOverride", "setVisibleSize"]
+ "include": ["setGeolocationOverride", "clearGeolocationOverride", "setEmitTouchEventsForMouse", "canEmulate", "setDeviceMetricsOverride", "clearDeviceMetricsOverride", "setVisibleSize", "setUserAgentOverride"]
},
{
"domain": "Input",
@@ -41,7 +41,7 @@
},
{
"domain": "Network",
- "include": ["enable", "disable", "clearBrowserCache", "clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "setUserAgentOverride", "setExtraHTTPHeaders", "canEmulateNetworkConditions", "emulateNetworkConditions", "setBypassServiceWorker", "setRequestInterception", "continueInterceptedRequest", "getResponseBodyForInterception", "setCacheDisabled", "takeResponseBodyForInterceptionAsStream"],
+ "include": ["enable", "disable", "clearBrowserCache", "clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "setExtraHTTPHeaders", "canEmulateNetworkConditions", "emulateNetworkConditions", "setBypassServiceWorker", "setRequestInterception", "continueInterceptedRequest", "getResponseBodyForInterception", "setCacheDisabled", "takeResponseBodyForInterceptionAsStream"],
"include_events": ["requestWillBeSent", "responseReceived", "loadingFinished", "loadingFailed", "requestIntercepted", "signedExchangeReceived"],
"async": ["clearBrowserCookies", "clearBrowserCache", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "continueInterceptedRequest", "getResponseBodyForInterception", "takeResponseBodyForInterceptionAsStream"]
},
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 8c663d94e92..9493103481a 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -41,7 +41,7 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/web_package/signed_exchange_header.h"
+#include "content/browser/web_package/signed_exchange_envelope.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -60,6 +60,7 @@
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#if defined(OS_ANDROID)
+#include "content/browser/renderer_host/compositor_impl_android.h"
#include "content/public/browser/render_widget_host_view.h"
#include "services/device/public/mojom/wake_lock_context.mojom.h"
#endif
@@ -230,13 +231,14 @@ void RenderFrameDevToolsAgentHost::OnSignedExchangeReceived(
base::Optional<const base::UnguessableToken> devtools_navigation_token,
const GURL& outer_request_url,
const network::ResourceResponseHead& outer_response,
- const base::Optional<SignedExchangeHeader>& header,
+ const base::Optional<SignedExchangeEnvelope>& envelope,
+ const scoped_refptr<net::X509Certificate>& certificate,
const base::Optional<net::SSLInfo>& ssl_info,
- const std::vector<std::string>& error_messages) {
+ const std::vector<SignedExchangeError>& errors) {
DispatchToAgents(frame_tree_node,
&protocol::NetworkHandler::OnSignedExchangeReceived,
devtools_navigation_token, outer_request_url, outer_response,
- header, ssl_info, error_messages);
+ envelope, certificate, ssl_info, errors);
}
// static
@@ -334,6 +336,10 @@ void RenderFrameDevToolsAgentHost::ApplyOverrides(
network->ApplyOverrides(&headers, &begin_params->skip_service_worker,
&disable_cache);
}
+
+ for (auto* emulation : protocol::EmulationHandler::ForAgentHost(agent_host))
+ emulation->ApplyOverrides(&headers);
+
if (disable_cache) {
begin_params->load_flags &=
~(net::LOAD_VALIDATE_CACHE | net::LOAD_SKIP_CACHE_VALIDATION |
@@ -421,9 +427,18 @@ WebContents* RenderFrameDevToolsAgentHost::GetWebContents() {
return web_contents();
}
-bool RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session) {
- if (session->restricted() && !IsFrameHostAllowedForRestrictedSessions())
+bool RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session,
+ TargetRegistry* registry) {
+ DevToolsManager* manager = DevToolsManager::GetInstance();
+ if (manager->delegate() && web_contents()) {
+ if (!manager->delegate()->AllowInspectingWebContents(web_contents()))
+ return false;
+ }
+ const bool is_webui =
+ frame_host_ && (frame_host_->web_ui() || frame_host_->pending_web_ui());
+ if (!session->client()->MayAttachToRenderer(frame_host_, is_webui))
return false;
+
session->SetRenderer(frame_host_ ? frame_host_->GetProcess()->GetID()
: ChildProcessHost::kInvalidUniqueID,
frame_host_);
@@ -438,14 +453,17 @@ bool RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session) {
session->AddHandler(base::WrapUnique(new protocol::IOHandler(
GetIOContext())));
session->AddHandler(base::WrapUnique(new protocol::MemoryHandler()));
- session->AddHandler(
- base::WrapUnique(new protocol::NetworkHandler(GetId(), GetIOContext())));
+ session->AddHandler(base::WrapUnique(new protocol::NetworkHandler(
+ GetId(),
+ frame_tree_node_ ? frame_tree_node_->devtools_frame_token()
+ : base::UnguessableToken(),
+ GetIOContext())));
session->AddHandler(base::WrapUnique(new protocol::SchemaHandler()));
session->AddHandler(base::WrapUnique(new protocol::ServiceWorkerHandler()));
session->AddHandler(base::WrapUnique(new protocol::StorageHandler()));
if (!session->restricted()) {
- session->AddHandler(base::WrapUnique(
- new protocol::TargetHandler(false /* browser_only */)));
+ session->AddHandler(base::WrapUnique(new protocol::TargetHandler(
+ false /* browser_only */, GetId(), registry)));
}
session->AddHandler(
base::WrapUnique(new protocol::PageHandler(emulation_handler)));
@@ -459,12 +477,19 @@ bool RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session) {
session->AttachToAgent(agent_ptr_);
if (sessions().size() == 1) {
- // Taking screenshots using the video capture API is done in TracingHandler.
- if (!base::FeatureList::IsEnabled(features::kVizDisplayCompositor) &&
- !base::FeatureList::IsEnabled(
- features::kUseVideoCaptureApiForDevToolsSnapshots)) {
+ bool use_video_capture_api =
+ base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
+ base::FeatureList::IsEnabled(
+ features::kUseVideoCaptureApiForDevToolsSnapshots);
+#ifdef OS_ANDROID
+ // Video capture API cannot be used on Android WebView.
+ if (!CompositorImpl::IsInitialized())
+ use_video_capture_api = false;
+#endif
+ // When video capture API is used, don't instantiate
+ // DevToolsFrameTraceRecorder. Taking snapshots happens in TracingHandler.
+ if (!use_video_capture_api)
frame_trace_recorder_.reset(new DevToolsFrameTraceRecorder());
- }
GrantPolicy();
#if defined(OS_ANDROID)
GetWakeLock()->RequestWakeLock();
@@ -484,12 +509,6 @@ void RenderFrameDevToolsAgentHost::DetachSession(DevToolsSession* session) {
}
}
-void RenderFrameDevToolsAgentHost::DispatchProtocolMessage(
- DevToolsSession* session,
- const std::string& message) {
- session->DispatchProtocolMessage(message);
-}
-
void RenderFrameDevToolsAgentHost::InspectElement(RenderFrameHost* frame_host,
int x,
int y) {
@@ -584,8 +603,17 @@ void RenderFrameDevToolsAgentHost::UpdateFrameHost(
frame_host_ = frame_host;
agent_ptr_.reset();
- if (!IsFrameHostAllowedForRestrictedSessions())
- ForceDetachRestrictedSessions();
+ std::vector<DevToolsSession*> restricted_sessions;
+ const bool is_webui =
+ frame_host && (frame_host->web_ui() || frame_host->pending_web_ui());
+
+ for (DevToolsSession* session : sessions()) {
+ if (!session->client()->MayAttachToRenderer(frame_host, is_webui))
+ restricted_sessions.push_back(session);
+ }
+
+ if (!restricted_sessions.empty())
+ ForceDetachRestrictedSessions(restricted_sessions);
if (!render_frame_alive_) {
render_frame_alive_ = true;
@@ -729,6 +757,7 @@ void RenderFrameDevToolsAgentHost::RenderProcessGone(
case base::TERMINATION_STATUS_LAUNCH_FAILED:
for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
inspector->TargetCrashed();
+ NotifyCrashed(status);
break;
default:
for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
@@ -952,9 +981,4 @@ bool RenderFrameDevToolsAgentHost::IsChildFrame() {
return frame_tree_node_ && frame_tree_node_->parent();
}
-bool RenderFrameDevToolsAgentHost::IsFrameHostAllowedForRestrictedSessions() {
- return !frame_host_ ||
- (!frame_host_->web_ui() && !frame_host_->pending_web_ui());
-}
-
} // 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 d4c77584e64..b4184bb250d 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -42,6 +42,7 @@ class CompositorFrameMetadata;
namespace net {
class SSLInfo;
+class X509Certificate;
}
namespace content {
@@ -53,7 +54,8 @@ class NavigationHandleImpl;
class NavigationRequest;
class NavigationThrottle;
class RenderFrameHostImpl;
-class SignedExchangeHeader;
+class SignedExchangeEnvelope;
+struct SignedExchangeError;
class CONTENT_EXPORT RenderFrameDevToolsAgentHost
: public DevToolsAgentHostImpl,
@@ -101,9 +103,10 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
base::Optional<const base::UnguessableToken> devtools_navigation_token,
const GURL& outer_request_url,
const network::ResourceResponseHead& outer_response,
- const base::Optional<SignedExchangeHeader>& header,
+ const base::Optional<SignedExchangeEnvelope>& header,
+ const scoped_refptr<net::X509Certificate>& certificate,
const base::Optional<net::SSLInfo>& ssl_info,
- const std::vector<std::string>& error_messages);
+ const std::vector<SignedExchangeError>& errors);
static void OnSignedExchangeCertificateRequestSent(
FrameTreeNode* frame_tree_node,
const base::UnguessableToken& request_id,
@@ -158,11 +161,10 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
~RenderFrameDevToolsAgentHost() override;
// DevToolsAgentHostImpl overrides.
- bool AttachSession(DevToolsSession* session) override;
+ bool AttachSession(DevToolsSession* session,
+ TargetRegistry* registry) override;
void DetachSession(DevToolsSession* session) override;
void InspectElement(RenderFrameHost* frame_host, int x, int y) override;
- void DispatchProtocolMessage(DevToolsSession* session,
- const std::string& message) override;
// WebContentsObserver overrides.
void DidStartNavigation(NavigationHandle* navigation_handle) override;
@@ -180,7 +182,6 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
void OnPageScaleFactorChanged(float page_scale_factor) override;
bool IsChildFrame();
- bool IsFrameHostAllowedForRestrictedSessions();
void OnSwapCompositorFrame(const IPC::Message& message);
void DestroyOnRenderFrameGone();
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 64801cf7cda..32f191e75cc 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
@@ -115,7 +115,8 @@ ServiceWorkerDevToolsAgentHost::~ServiceWorkerDevToolsAgentHost() {
ServiceWorkerDevToolsManager::GetInstance()->AgentHostDestroyed(this);
}
-bool ServiceWorkerDevToolsAgentHost::AttachSession(DevToolsSession* session) {
+bool ServiceWorkerDevToolsAgentHost::AttachSession(DevToolsSession* session,
+ TargetRegistry* registry) {
if (state_ == WORKER_READY) {
if (sessions().size() == 1) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
@@ -126,8 +127,8 @@ bool ServiceWorkerDevToolsAgentHost::AttachSession(DevToolsSession* session) {
session->AttachToAgent(agent_ptr_);
}
session->AddHandler(base::WrapUnique(new protocol::InspectorHandler()));
- session->AddHandler(
- base::WrapUnique(new protocol::NetworkHandler(GetId(), GetIOContext())));
+ session->AddHandler(base::WrapUnique(new protocol::NetworkHandler(
+ GetId(), devtools_worker_token_, GetIOContext())));
session->AddHandler(base::WrapUnique(new protocol::SchemaHandler()));
return true;
}
@@ -141,12 +142,6 @@ void ServiceWorkerDevToolsAgentHost::DetachSession(DevToolsSession* session) {
}
}
-void ServiceWorkerDevToolsAgentHost::DispatchProtocolMessage(
- DevToolsSession* session,
- const std::string& message) {
- session->DispatchProtocolMessage(message);
-}
-
void ServiceWorkerDevToolsAgentHost::WorkerReadyForInspection(
blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
DCHECK_EQ(WORKER_NOT_READY, state_);
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 453f52c6da9..b2612093058 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.h
@@ -47,10 +47,9 @@ class ServiceWorkerDevToolsAgentHost : public DevToolsAgentHostImpl {
bool Close() override;
// DevToolsAgentHostImpl overrides.
- bool AttachSession(DevToolsSession* session) override;
+ bool AttachSession(DevToolsSession* session,
+ TargetRegistry* registry) override;
void DetachSession(DevToolsSession* session) override;
- void DispatchProtocolMessage(DevToolsSession* session,
- const std::string& message) override;
void WorkerRestarted(int worker_process_id, int worker_route_id);
void WorkerReadyForInspection(
diff --git a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
index fd40420eed3..c09e04a0717 100644
--- a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
@@ -66,10 +66,11 @@ bool SharedWorkerDevToolsAgentHost::Close() {
return true;
}
-bool SharedWorkerDevToolsAgentHost::AttachSession(DevToolsSession* session) {
+bool SharedWorkerDevToolsAgentHost::AttachSession(DevToolsSession* session,
+ TargetRegistry* registry) {
session->AddHandler(std::make_unique<protocol::InspectorHandler>());
- session->AddHandler(
- std::make_unique<protocol::NetworkHandler>(GetId(), GetIOContext()));
+ session->AddHandler(std::make_unique<protocol::NetworkHandler>(
+ GetId(), devtools_worker_token_, GetIOContext()));
session->AddHandler(std::make_unique<protocol::SchemaHandler>());
session->SetRenderer(worker_host_ ? worker_host_->process_id() : -1, nullptr);
if (state_ == WORKER_READY)
@@ -81,12 +82,6 @@ void SharedWorkerDevToolsAgentHost::DetachSession(DevToolsSession* session) {
// Destroying session automatically detaches in renderer.
}
-void SharedWorkerDevToolsAgentHost::DispatchProtocolMessage(
- DevToolsSession* session,
- const std::string& message) {
- session->DispatchProtocolMessage(message);
-}
-
bool SharedWorkerDevToolsAgentHost::Matches(SharedWorkerHost* worker_host) {
return instance_->Matches(*worker_host->instance());
}
diff --git a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.h b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.h
index 6a1d800795b..c0a867de030 100644
--- a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.h
@@ -33,10 +33,9 @@ class SharedWorkerDevToolsAgentHost : public DevToolsAgentHostImpl {
bool Close() override;
// DevToolsAgentHostImpl overrides.
- bool AttachSession(DevToolsSession* session) override;
+ bool AttachSession(DevToolsSession* session,
+ TargetRegistry* registry) override;
void DetachSession(DevToolsSession* session) override;
- void DispatchProtocolMessage(DevToolsSession* session,
- const std::string& message) override;
bool Matches(SharedWorkerHost* worker_host);
void WorkerReadyForInspection();
diff --git a/chromium/content/browser/devtools/target_registry.cc b/chromium/content/browser/devtools/target_registry.cc
new file mode 100644
index 00000000000..07d168aa79b
--- /dev/null
+++ b/chromium/content/browser/devtools/target_registry.cc
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/target_registry.h"
+
+#include "base/strings/stringprintf.h"
+#include "content/browser/devtools/devtools_session.h"
+
+namespace content {
+
+TargetRegistry::TargetRegistry(DevToolsSession* root_session)
+ : root_session_(root_session) {}
+
+TargetRegistry::~TargetRegistry() {}
+
+void TargetRegistry::AttachSubtargetSession(const std::string& session_id,
+ DevToolsAgentHostImpl* agent_host,
+ DevToolsAgentHostClient* client) {
+ sessions_[session_id] = std::make_pair(agent_host, client);
+ agent_host->AttachSubtargetClient(client, this);
+}
+void TargetRegistry::DetachSubtargetSession(const std::string& session_id) {
+ sessions_.erase(session_id);
+}
+
+bool TargetRegistry::DispatchMessageOnAgentHost(
+ const std::string& message,
+ base::DictionaryValue* parsed_message) {
+ std::string session_id;
+ if (!parsed_message->GetString("sessionId", &session_id))
+ return false;
+ auto it = sessions_.find(session_id);
+ if (it == sessions_.end()) {
+ LOG(ERROR) << "Unknown session " << session_id;
+ return true;
+ }
+ scoped_refptr<DevToolsAgentHostImpl> agent_host = it->second.first;
+ DevToolsAgentHostClient* client = it->second.second;
+ return agent_host->DispatchProtocolMessage(client, message, parsed_message);
+}
+
+void TargetRegistry::SendMessageToClient(const std::string& session_id,
+ const std::string& message) {
+ DCHECK(message[message.length() - 1] == '}');
+ std::string suffix =
+ base::StringPrintf(", \"sessionId\": \"%s\"}", session_id.c_str());
+ std::string patched;
+ patched.reserve(message.length() + suffix.length() - 1);
+ patched.append(message.data(), message.length() - 1);
+ patched.append(suffix);
+ root_session_->client()->DispatchProtocolMessage(root_session_->agent_host(),
+ patched);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/target_registry.h b/chromium/content/browser/devtools/target_registry.h
new file mode 100644
index 00000000000..d915e1f1368
--- /dev/null
+++ b/chromium/content/browser/devtools/target_registry.h
@@ -0,0 +1,44 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_TARGET_REGISTRY_H_
+#define CONTENT_BROWSER_DEVTOOLS_TARGET_REGISTRY_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/containers/flat_map.h"
+#include "base/values.h"
+#include "content/browser/devtools/devtools_agent_host_impl.h"
+
+namespace content {
+
+class DevToolsSession;
+
+class TargetRegistry {
+ public:
+ explicit TargetRegistry(DevToolsSession* root_session);
+ ~TargetRegistry();
+
+ void AttachSubtargetSession(const std::string& session_id,
+ DevToolsAgentHostImpl* agent_host,
+ DevToolsAgentHostClient* client);
+ void DetachSubtargetSession(const std::string& session_id);
+ bool DispatchMessageOnAgentHost(const std::string& message,
+ base::DictionaryValue* parsed_message);
+ void SendMessageToClient(const std::string& session_id,
+ const std::string& message);
+
+ private:
+ DevToolsSession* root_session_;
+ base::flat_map<
+ std::string,
+ std::pair<scoped_refptr<DevToolsAgentHostImpl>, DevToolsAgentHostClient*>>
+ sessions_;
+ DISALLOW_COPY_AND_ASSIGN(TargetRegistry);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_TARGET_REGISTRY_H_
diff --git a/chromium/content/browser/display_cutout/OWNERS b/chromium/content/browser/display_cutout/OWNERS
new file mode 100644
index 00000000000..3b7954a88fd
--- /dev/null
+++ b/chromium/content/browser/display_cutout/OWNERS
@@ -0,0 +1,3 @@
+file://chrome/android/java/src/org/chromium/chrome/browser/display_cutout/OWNERS
+
+# COMPONENT: Blink>Layout
diff --git a/chromium/content/browser/display_cutout/display_cutout_browsertest.cc b/chromium/content/browser/display_cutout/display_cutout_browsertest.cc
new file mode 100644
index 00000000000..f254afeff13
--- /dev/null
+++ b/chromium/content/browser/display_cutout/display_cutout_browsertest.cc
@@ -0,0 +1,468 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/run_loop.h"
+#include "build/build_config.h"
+#include "components/ukm/test_ukm_recorder.h"
+#include "content/browser/display_cutout/display_cutout_constants.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents_delegate.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_frame_navigation_observer.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/mojom/page/display_cutout.mojom.h"
+
+namespace content {
+
+namespace {
+
+#if defined(OS_ANDROID)
+
+// These inset and flags simulate when we are not extending into the cutout.
+const gfx::Insets kNoCutoutInsets = gfx::Insets();
+const int kNoCutoutInsetsExpectedFlags = DisplayCutoutSafeArea::kEmpty;
+
+// These inset and flags simulate when the we are extending into the cutout.
+const gfx::Insets kCutoutInsets = gfx::Insets(1, 0, 1, 0);
+const int kCutoutInsetsExpectedFlags =
+ DisplayCutoutSafeArea::kTop | DisplayCutoutSafeArea::kBottom;
+
+// These inset and flags simulate when we are extending into the cutout and have
+// rotated the device so that the cutout is on the other sides.
+const gfx::Insets kRotatedCutoutInsets = gfx::Insets(0, 1, 0, 1);
+const int kRotatedCutoutInsetsExpectedFlags =
+ DisplayCutoutSafeArea::kLeft | DisplayCutoutSafeArea::kRight;
+
+#endif
+
+class TestWebContentsObserver : public WebContentsObserver {
+ public:
+ explicit TestWebContentsObserver(content::WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+
+ // WebContentsObserver override.
+ void ViewportFitChanged(blink::mojom::ViewportFit value) override {
+ value_ = value;
+
+ if (value_ == wanted_value_)
+ run_loop_.Quit();
+ }
+
+ bool has_value() const { return value_.has_value(); }
+
+ void WaitForWantedValue(blink::mojom::ViewportFit wanted_value) {
+ if (value_.has_value()) {
+ EXPECT_EQ(wanted_value, value_);
+ return;
+ }
+
+ wanted_value_ = wanted_value;
+ run_loop_.Run();
+ }
+
+ private:
+ base::RunLoop run_loop_;
+ base::Optional<blink::mojom::ViewportFit> value_;
+ blink::mojom::ViewportFit wanted_value_ = blink::mojom::ViewportFit::kAuto;
+
+ DISALLOW_COPY_AND_ASSIGN(TestWebContentsObserver);
+};
+
+// Used for forcing a specific |blink::WebDisplayMode| during a test.
+class DisplayCutoutWebContentsDelegate : public WebContentsDelegate {
+ public:
+ blink::WebDisplayMode GetDisplayMode(
+ const WebContents* web_contents) const override {
+ return display_mode_;
+ }
+
+ void SetDisplayMode(blink::WebDisplayMode display_mode) {
+ display_mode_ = display_mode;
+ }
+
+ private:
+ blink::WebDisplayMode display_mode_ =
+ blink::WebDisplayMode::kWebDisplayModeBrowser;
+};
+
+const char kTestHTML[] =
+ "<!DOCTYPE html>"
+ "<style>"
+ " #target {"
+ " margin-top: env(safe-area-inset-top);"
+ " margin-left: env(safe-area-inset-left);"
+ " margin-bottom: env(safe-area-inset-bottom);"
+ " margin-right: env(safe-area-inset-right);"
+ " }"
+ "</style>"
+ "<div id=target></div>";
+
+} // namespace
+
+class DisplayCutoutBrowserTest : public ContentBrowserTest {
+ public:
+ DisplayCutoutBrowserTest() = default;
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitchASCII("enable-blink-features",
+ "DisplayCutoutAPI");
+ }
+
+ void LoadTestPageWithViewportFitFromMeta(const std::string& value) {
+ LoadTestPageWithData(
+ "<!DOCTYPE html>"
+ "<meta name='viewport' content='viewport-fit=" +
+ value + "'><iframe></iframe>");
+ }
+
+ void LoadSubFrameWithViewportFitMetaValue(const std::string& value) {
+ const std::string data =
+ "data:text/html;charset=utf-8,<!DOCTYPE html>"
+ "<meta name='viewport' content='viewport-fit=" +
+ value + "'>";
+
+ FrameTreeNode* root = web_contents_impl()->GetFrameTree()->root();
+ FrameTreeNode* child = root->child_at(0);
+
+ TestFrameNavigationObserver observer(child);
+ NavigationController::LoadURLParams params(GURL::EmptyGURL());
+ params.url = GURL(data);
+ params.frame_tree_node_id = child->frame_tree_node_id();
+ params.load_type = NavigationController::LOAD_TYPE_DATA;
+ web_contents_impl()->GetController().LoadURLWithParams(params);
+ web_contents_impl()->Focus();
+ observer.Wait();
+ }
+
+ bool ClearViewportFitTag() {
+ return ExecuteScript(
+ web_contents_impl(),
+ "document.getElementsByTagName('meta')[0].content = ''");
+ }
+
+ void SendSafeAreaToFrame(int top, int left, int bottom, int right) {
+ blink::mojom::DisplayCutoutClientAssociatedPtr client;
+ MainFrame()->GetRemoteAssociatedInterfaces()->GetInterface(&client);
+ client->SetSafeArea(
+ blink::mojom::DisplayCutoutSafeArea::New(top, left, bottom, right));
+ }
+
+ std::string GetCurrentSafeAreaValue(const std::string& name) {
+ std::string value;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ MainFrame(),
+ "(() => {"
+ "const e = document.getElementById('target');"
+ "const style = window.getComputedStyle(e, null);"
+ "window.domAutomationController.send("
+ " style.getPropertyValue('margin-" +
+ name +
+ "'));"
+ "})();",
+ &value));
+ return value;
+ }
+
+ void LoadTestPageWithData(const std::string& data) {
+ GURL url("https://www.example.com");
+ ResetUKM();
+
+ TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
+#if defined(OS_ANDROID)
+ shell()->LoadDataAsStringWithBaseURL(url, data, url);
+#else
+ shell()->LoadDataWithBaseURL(url, data, url);
+#endif
+ same_tab_observer.Wait();
+ }
+
+ void SimulateFullscreenStateChanged(RenderFrameHost* frame,
+ bool is_fullscreen) {
+ web_contents_impl()->FullscreenStateChanged(frame, is_fullscreen);
+ }
+
+ void SimulateFullscreenExit() {
+ web_contents_impl()->ExitFullscreenMode(true);
+ }
+
+ RenderFrameHost* MainFrame() { return web_contents_impl()->GetMainFrame(); }
+
+ RenderFrameHost* ChildFrame() {
+ FrameTreeNode* root = web_contents_impl()->GetFrameTree()->root();
+ return root->child_at(0)->current_frame_host();
+ }
+
+ WebContentsImpl* web_contents_impl() {
+ return static_cast<WebContentsImpl*>(shell()->web_contents());
+ }
+
+ unsigned GetUKMEntryCount() const {
+ using Entry = ukm::builders::Layout_DisplayCutout_StateChanged;
+ auto ukm_entries = test_ukm_recorder_->GetEntriesByName(Entry::kEntryName);
+ return ukm_entries.size();
+ }
+
+ void ExpectUKMEntry(int index,
+ ukm::SourceId source_id,
+ bool is_main_frame,
+ blink::mojom::ViewportFit applied_value,
+ blink::mojom::ViewportFit supplied_value,
+ int ignored_reason,
+ int safe_areas_present) {
+ using Entry = ukm::builders::Layout_DisplayCutout_StateChanged;
+ auto ukm_entries = test_ukm_recorder_->GetEntriesByName(Entry::kEntryName);
+
+ EXPECT_EQ(source_id, ukm_entries[index]->source_id);
+ EXPECT_EQ(is_main_frame, *test_ukm_recorder_->GetEntryMetric(
+ ukm_entries[index], Entry::kIsMainFrameName));
+ EXPECT_EQ(static_cast<int>(applied_value),
+ *test_ukm_recorder_->GetEntryMetric(
+ ukm_entries[index], Entry::kViewportFit_AppliedName));
+ EXPECT_EQ(static_cast<int>(supplied_value),
+ *test_ukm_recorder_->GetEntryMetric(
+ ukm_entries[index], Entry::kViewportFit_SuppliedName));
+ EXPECT_EQ(ignored_reason,
+ *test_ukm_recorder_->GetEntryMetric(
+ ukm_entries[index], Entry::kViewportFit_IgnoredReasonName));
+ EXPECT_EQ(safe_areas_present,
+ *test_ukm_recorder_->GetEntryMetric(
+ ukm_entries[index], Entry::kSafeAreasPresentName));
+ }
+
+ private:
+ void ResetUKM() {
+ test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
+ }
+
+ std::unique_ptr<ukm::TestUkmRecorder> test_ukm_recorder_;
+
+ DISALLOW_COPY_AND_ASSIGN(DisplayCutoutBrowserTest);
+};
+
+// The viewport meta tag is only enabled on Android.
+#if defined(OS_ANDROID)
+
+IN_PROC_BROWSER_TEST_F(DisplayCutoutBrowserTest, ViewportFit_Fullscreen) {
+ LoadTestPageWithViewportFitFromMeta("cover");
+ LoadSubFrameWithViewportFitMetaValue("contain");
+
+ {
+ TestWebContentsObserver observer(web_contents_impl());
+ SimulateFullscreenStateChanged(MainFrame(), true);
+ observer.WaitForWantedValue(blink::mojom::ViewportFit::kCover);
+ web_contents_impl()->SetDisplayCutoutSafeArea(kCutoutInsets);
+ }
+
+ {
+ TestWebContentsObserver observer(web_contents_impl());
+ SimulateFullscreenStateChanged(ChildFrame(), true);
+ observer.WaitForWantedValue(blink::mojom::ViewportFit::kContain);
+ web_contents_impl()->SetDisplayCutoutSafeArea(kNoCutoutInsets);
+ }
+
+ {
+ TestWebContentsObserver observer(web_contents_impl());
+ SimulateFullscreenStateChanged(ChildFrame(), false);
+ observer.WaitForWantedValue(blink::mojom::ViewportFit::kCover);
+
+ // This simulates the user rotating the device.
+ web_contents_impl()->SetDisplayCutoutSafeArea(kCutoutInsets);
+ web_contents_impl()->SetDisplayCutoutSafeArea(kRotatedCutoutInsets);
+ }
+
+ {
+ TestWebContentsObserver observer(web_contents_impl());
+ SimulateFullscreenStateChanged(MainFrame(), false);
+ SimulateFullscreenExit();
+ observer.WaitForWantedValue(blink::mojom::ViewportFit::kAuto);
+ web_contents_impl()->SetDisplayCutoutSafeArea(kNoCutoutInsets);
+ }
+
+ // Get the source id for the page and close the |shell|. This will flush any
+ // unrecorded UKM metrics.
+ ukm::SourceId source_id =
+ web_contents_impl()->GetUkmSourceIdForLastCommittedSource();
+ shell()->Close();
+
+ // Check UKM metrics are recorded. The first two entries are from loading the
+ // frame and the subframe with a viewport fit attribute.
+ EXPECT_EQ(5u, GetUKMEntryCount());
+ ExpectUKMEntry(0, source_id, true, blink::mojom::ViewportFit::kAuto,
+ blink::mojom::ViewportFit::kCover,
+ DisplayCutoutIgnoredReason::kWebContentsNotFullscreen,
+ kNoCutoutInsetsExpectedFlags);
+ ExpectUKMEntry(1, source_id, false, blink::mojom::ViewportFit::kAuto,
+ blink::mojom::ViewportFit::kContain,
+ DisplayCutoutIgnoredReason::kWebContentsNotFullscreen,
+ kNoCutoutInsetsExpectedFlags);
+
+ // This is when we take the main frame fullscreen.
+ ExpectUKMEntry(2, source_id, true, blink::mojom::ViewportFit::kCover,
+ blink::mojom::ViewportFit::kCover,
+ DisplayCutoutIgnoredReason::kAllowed,
+ kCutoutInsetsExpectedFlags);
+
+ // This is when we take the subframe fullscreen.
+ ExpectUKMEntry(3, source_id, false, blink::mojom::ViewportFit::kContain,
+ blink::mojom::ViewportFit::kContain,
+ DisplayCutoutIgnoredReason::kAllowed,
+ kNoCutoutInsetsExpectedFlags);
+
+ // These is when the subframe exits fullscreen.
+ ExpectUKMEntry(4, source_id, true, blink::mojom::ViewportFit::kCover,
+ blink::mojom::ViewportFit::kCover,
+ DisplayCutoutIgnoredReason::kAllowed,
+ kRotatedCutoutInsetsExpectedFlags);
+}
+
+IN_PROC_BROWSER_TEST_F(DisplayCutoutBrowserTest,
+ ViewportFit_Fullscreen_Update) {
+ LoadTestPageWithViewportFitFromMeta("cover");
+
+ {
+ TestWebContentsObserver observer(web_contents_impl());
+ SimulateFullscreenStateChanged(MainFrame(), true);
+ observer.WaitForWantedValue(blink::mojom::ViewportFit::kCover);
+ web_contents_impl()->SetDisplayCutoutSafeArea(kNoCutoutInsets);
+ }
+
+ {
+ TestWebContentsObserver observer(web_contents_impl());
+ EXPECT_TRUE(ClearViewportFitTag());
+ observer.WaitForWantedValue(blink::mojom::ViewportFit::kAuto);
+ web_contents_impl()->SetDisplayCutoutSafeArea(kNoCutoutInsets);
+ }
+
+ // Get the source id for the page and close the |shell|. This will flush any
+ // unrecorded UKM metrics.
+ ukm::SourceId source_id =
+ web_contents_impl()->GetUkmSourceIdForLastCommittedSource();
+ shell()->Close();
+
+ // Check UKM metrics are recorded.
+ EXPECT_EQ(2u, GetUKMEntryCount());
+ ExpectUKMEntry(0, source_id, true, blink::mojom::ViewportFit::kAuto,
+ blink::mojom::ViewportFit::kCover,
+ DisplayCutoutIgnoredReason::kWebContentsNotFullscreen,
+ kNoCutoutInsetsExpectedFlags);
+ ExpectUKMEntry(1, source_id, true, blink::mojom::ViewportFit::kCover,
+ blink::mojom::ViewportFit::kCover,
+ DisplayCutoutIgnoredReason::kAllowed,
+ kNoCutoutInsetsExpectedFlags);
+}
+
+IN_PROC_BROWSER_TEST_F(DisplayCutoutBrowserTest, ViewportFit_Noop_Navigate) {
+ {
+ TestWebContentsObserver observer(web_contents_impl());
+ LoadTestPageWithViewportFitFromMeta("cover");
+ EXPECT_FALSE(observer.has_value());
+ }
+
+ ukm::SourceId source_id =
+ web_contents_impl()->GetUkmSourceIdForLastCommittedSource();
+ LoadTestPageWithData("");
+
+ // Check UKM metrics are recorded.
+ EXPECT_EQ(1u, GetUKMEntryCount());
+ ExpectUKMEntry(0, source_id, true, blink::mojom::ViewportFit::kAuto,
+ blink::mojom::ViewportFit::kCover,
+ DisplayCutoutIgnoredReason::kWebContentsNotFullscreen,
+ kNoCutoutInsetsExpectedFlags);
+}
+
+IN_PROC_BROWSER_TEST_F(DisplayCutoutBrowserTest,
+ ViewportFit_Noop_WebContentsDestroyed) {
+ {
+ TestWebContentsObserver observer(web_contents_impl());
+ LoadTestPageWithViewportFitFromMeta("cover");
+ EXPECT_FALSE(observer.has_value());
+ }
+
+ ukm::SourceId source_id =
+ web_contents_impl()->GetUkmSourceIdForLastCommittedSource();
+ shell()->Close();
+
+ // Check UKM metrics are recorded.
+ EXPECT_EQ(1u, GetUKMEntryCount());
+ ExpectUKMEntry(0, source_id, true, blink::mojom::ViewportFit::kAuto,
+ blink::mojom::ViewportFit::kCover,
+ DisplayCutoutIgnoredReason::kWebContentsNotFullscreen,
+ kNoCutoutInsetsExpectedFlags);
+}
+
+IN_PROC_BROWSER_TEST_F(DisplayCutoutBrowserTest, WebDisplayMode) {
+ // Inject the custom delegate used for this test.
+ std::unique_ptr<DisplayCutoutWebContentsDelegate> delegate(
+ new DisplayCutoutWebContentsDelegate());
+ web_contents_impl()->SetDelegate(delegate.get());
+ EXPECT_EQ(delegate.get(), web_contents_impl()->GetDelegate());
+
+ {
+ TestWebContentsObserver observer(web_contents_impl());
+ LoadTestPageWithViewportFitFromMeta("cover");
+ EXPECT_FALSE(observer.has_value());
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(DisplayCutoutBrowserTest, WebDisplayMode_Fullscreen) {
+ // Inject the custom delegate used for this test.
+ std::unique_ptr<DisplayCutoutWebContentsDelegate> delegate(
+ new DisplayCutoutWebContentsDelegate());
+ delegate->SetDisplayMode(blink::WebDisplayMode::kWebDisplayModeFullscreen);
+ web_contents_impl()->SetDelegate(delegate.get());
+ EXPECT_EQ(delegate.get(), web_contents_impl()->GetDelegate());
+
+ {
+ TestWebContentsObserver observer(web_contents_impl());
+ LoadTestPageWithViewportFitFromMeta("cover");
+ observer.WaitForWantedValue(blink::mojom::ViewportFit::kCover);
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(DisplayCutoutBrowserTest, WebDisplayMode_Standalone) {
+ // Inject the custom delegate used for this test.
+ std::unique_ptr<DisplayCutoutWebContentsDelegate> delegate(
+ new DisplayCutoutWebContentsDelegate());
+ delegate->SetDisplayMode(blink::WebDisplayMode::kWebDisplayModeStandalone);
+ web_contents_impl()->SetDelegate(delegate.get());
+ EXPECT_EQ(delegate.get(), web_contents_impl()->GetDelegate());
+
+ {
+ TestWebContentsObserver observer(web_contents_impl());
+ LoadTestPageWithViewportFitFromMeta("cover");
+ EXPECT_FALSE(observer.has_value());
+ }
+}
+
+#endif
+
+IN_PROC_BROWSER_TEST_F(DisplayCutoutBrowserTest, PublishSafeAreaVariables) {
+ LoadTestPageWithData(kTestHTML);
+
+ // Make sure all the safe areas are currently zero.
+ EXPECT_EQ("0px", GetCurrentSafeAreaValue("top"));
+ EXPECT_EQ("0px", GetCurrentSafeAreaValue("left"));
+ EXPECT_EQ("0px", GetCurrentSafeAreaValue("bottom"));
+ EXPECT_EQ("0px", GetCurrentSafeAreaValue("right"));
+
+ SendSafeAreaToFrame(1, 2, 3, 4);
+
+ // Make sure all the safe ares are correctly set.
+ EXPECT_EQ("1px", GetCurrentSafeAreaValue("top"));
+ EXPECT_EQ("2px", GetCurrentSafeAreaValue("left"));
+ EXPECT_EQ("3px", GetCurrentSafeAreaValue("bottom"));
+ EXPECT_EQ("4px", GetCurrentSafeAreaValue("right"));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/display_cutout/display_cutout_constants.h b/chromium/content/browser/display_cutout/display_cutout_constants.h
new file mode 100644
index 00000000000..fe070209868
--- /dev/null
+++ b/chromium/content/browser/display_cutout/display_cutout_constants.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All 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_DISPLAY_CUTOUT_DISPLAY_CUTOUT_CONSTANTS_H_
+#define CONTENT_BROWSER_DISPLAY_CUTOUT_DISPLAY_CUTOUT_CONSTANTS_H_
+
+namespace content {
+
+// Contains the reasons why a |RenderFrameHost| does not have control over a
+// the Display Cutout. This enum is used in metrics so the order should not
+// be changed.
+enum DisplayCutoutIgnoredReason {
+ // The frame was not ignored.
+ kAllowed = 0,
+
+ // The frame was ignored because it was not the current active fullscreen
+ // frame.
+ kFrameNotCurrentFullscreen,
+
+ // The frame was ignored because the WebContents was not fullscreen.
+ kWebContentsNotFullscreen,
+};
+
+// Contains flags as to which safe areas are present and greater than zero. This
+// enum is used in metrics so the order should not be changed.
+enum DisplayCutoutSafeArea {
+ kEmpty = 0,
+ kTop = 1 << 0,
+ kLeft = 1 << 1,
+ kBottom = 1 << 2,
+ kRight = 1 << 3,
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DISPLAY_CUTOUT_DISPLAY_CUTOUT_CONSTANTS_H_
diff --git a/chromium/content/browser/display_cutout/display_cutout_host_impl.cc b/chromium/content/browser/display_cutout/display_cutout_host_impl.cc
new file mode 100644
index 00000000000..4785df22f40
--- /dev/null
+++ b/chromium/content/browser/display_cutout/display_cutout_host_impl.cc
@@ -0,0 +1,230 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/display_cutout/display_cutout_host_impl.h"
+
+#include "content/browser/display_cutout/display_cutout_constants.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/navigation_handle.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+
+namespace content {
+
+DisplayCutoutHostImpl::DisplayCutoutHostImpl(
+ WebContentsImpl* web_contents,
+ ViewportFitChangedCallback callback)
+ : WebContentsObserver(web_contents),
+ viewport_fit_changed_callback_(callback),
+ bindings_(web_contents, this) {}
+
+DisplayCutoutHostImpl::~DisplayCutoutHostImpl() = default;
+
+void DisplayCutoutHostImpl::NotifyViewportFitChanged(
+ blink::mojom::ViewportFit value) {
+ ViewportFitChangedForFrame(bindings_.GetCurrentTargetFrame(), value);
+}
+
+void DisplayCutoutHostImpl::ViewportFitChangedForFrame(
+ RenderFrameHost* rfh,
+ blink::mojom::ViewportFit value) {
+ if (GetValueOrDefault(rfh) == value)
+ return;
+
+ values_[rfh] = value;
+
+ // If we are the current |RenderFrameHost| frame then notify
+ // WebContentsObservers about the new value.
+ if (current_rfh_ == rfh)
+ viewport_fit_changed_callback_.Run(value);
+
+ MaybeQueueUKMEvent(rfh);
+}
+
+void DisplayCutoutHostImpl::DidAcquireFullscreen(RenderFrameHost* rfh) {
+ SetCurrentRenderFrameHost(rfh);
+}
+
+void DisplayCutoutHostImpl::DidToggleFullscreenModeForTab(
+ bool entered_fullscreen,
+ bool will_cause_resize) {
+ if (!entered_fullscreen)
+ SetCurrentRenderFrameHost(nullptr);
+}
+
+void DisplayCutoutHostImpl::DidStartNavigation(
+ NavigationHandle* navigation_handle) {
+ // If the navigation is not in the main frame or if we are a same document
+ // navigation then we should stop now.
+ if (!navigation_handle->IsInMainFrame() ||
+ navigation_handle->IsSameDocument()) {
+ return;
+ }
+
+ RecordPendingUKMEvents();
+}
+
+void DisplayCutoutHostImpl::DidFinishNavigation(
+ NavigationHandle* navigation_handle) {
+ // If the navigation is not in the main frame or if we are a same document
+ // navigation then we should stop now.
+ if (!navigation_handle->IsInMainFrame() ||
+ navigation_handle->IsSameDocument()) {
+ return;
+ }
+
+ // If we finish a main frame navigation and the |WebDisplayMode| is
+ // fullscreen then we should make the main frame the current
+ // |RenderFrameHost|.
+ RenderWidgetHostImpl* rwh =
+ web_contents_impl()->GetRenderViewHost()->GetWidget();
+ blink::WebDisplayMode mode = web_contents_impl()->GetDisplayMode(rwh);
+ if (mode == blink::WebDisplayMode::kWebDisplayModeFullscreen) {
+ SetCurrentRenderFrameHost(web_contents_impl()->GetMainFrame());
+ }
+}
+
+void DisplayCutoutHostImpl::RenderFrameDeleted(RenderFrameHost* rfh) {
+ values_.erase(rfh);
+
+ // If we were the current |RenderFrameHost| then we should clear that.
+ if (current_rfh_ == rfh)
+ SetCurrentRenderFrameHost(nullptr);
+}
+
+void DisplayCutoutHostImpl::RenderFrameCreated(RenderFrameHost* rfh) {
+ ViewportFitChangedForFrame(rfh, blink::mojom::ViewportFit::kAuto);
+}
+
+void DisplayCutoutHostImpl::WebContentsDestroyed() {
+ // Record any pending UKM events that we are waiting to record.
+ RecordPendingUKMEvents();
+}
+
+void DisplayCutoutHostImpl::SetDisplayCutoutSafeArea(gfx::Insets insets) {
+ insets_ = insets;
+
+ if (current_rfh_)
+ SendSafeAreaToFrame(current_rfh_, insets);
+
+ // If we have a pending UKM event on the top of the stack that is |kAllowed|
+ // and we have a |current_rfh_| then we should update that UKM event as it
+ // was recorded before we received the safe area.
+ if (!pending_ukm_events_.empty() && current_rfh_) {
+ PendingUKMEvent& last_entry = pending_ukm_events_.back();
+ if (last_entry.ignored_reason == DisplayCutoutIgnoredReason::kAllowed)
+ last_entry.safe_areas_present = GetSafeAreasPresentUKMValue();
+ }
+}
+
+void DisplayCutoutHostImpl::SetCurrentRenderFrameHost(RenderFrameHost* rfh) {
+ if (current_rfh_ == rfh)
+ return;
+
+ // If we had a previous frame then we should clear the insets on that frame.
+ if (current_rfh_)
+ SendSafeAreaToFrame(current_rfh_, gfx::Insets());
+
+ // Update the |current_rfh_| with the new frame.
+ current_rfh_ = rfh;
+
+ // If the new RenderFrameHost is nullptr we should stop here and notify
+ // observers that the new viewport fit is kAuto (the default).
+ if (!rfh) {
+ viewport_fit_changed_callback_.Run(blink::mojom::ViewportFit::kAuto);
+ return;
+ }
+
+ // Record a UKM event for the new frame.
+ MaybeQueueUKMEvent(current_rfh_);
+
+ // Send the current safe area to the new frame.
+ SendSafeAreaToFrame(rfh, insets_);
+
+ // Notify the WebContentsObservers that the viewport fit value has changed.
+ viewport_fit_changed_callback_.Run(GetValueOrDefault(rfh));
+}
+
+void DisplayCutoutHostImpl::SendSafeAreaToFrame(RenderFrameHost* rfh,
+ gfx::Insets insets) {
+ blink::AssociatedInterfaceProvider* provider =
+ rfh->GetRemoteAssociatedInterfaces();
+ if (!provider)
+ return;
+
+ blink::mojom::DisplayCutoutClientAssociatedPtr client;
+ provider->GetInterface(&client);
+ client->SetSafeArea(blink::mojom::DisplayCutoutSafeArea::New(
+ insets.top(), insets.left(), insets.bottom(), insets.right()));
+}
+
+blink::mojom::ViewportFit DisplayCutoutHostImpl::GetValueOrDefault(
+ RenderFrameHost* rfh) const {
+ auto value = values_.find(rfh);
+ if (value != values_.end())
+ return value->second;
+ return blink::mojom::ViewportFit::kAuto;
+}
+
+WebContentsImpl* DisplayCutoutHostImpl::web_contents_impl() {
+ return static_cast<WebContentsImpl*>(web_contents());
+}
+
+void DisplayCutoutHostImpl::MaybeQueueUKMEvent(RenderFrameHost* frame) {
+ if (!frame)
+ return;
+
+ // Get the current applied ViewportFit and the ViewportFit value supplied by
+ // |frame|. If the |supplied_value| is kAuto then we will not record the
+ // event since it is the default.
+ blink::mojom::ViewportFit supplied_value = GetValueOrDefault(frame);
+ if (supplied_value == blink::mojom::ViewportFit::kAuto)
+ return;
+ blink::mojom::ViewportFit applied_value = GetValueOrDefault(current_rfh_);
+
+ // Set the reason why this frame is not the current frame.
+ int ignored_reason = DisplayCutoutIgnoredReason::kAllowed;
+ if (current_rfh_ != frame) {
+ ignored_reason =
+ current_rfh_ == nullptr
+ ? DisplayCutoutIgnoredReason::kWebContentsNotFullscreen
+ : DisplayCutoutIgnoredReason::kFrameNotCurrentFullscreen;
+ }
+
+ // Adds the UKM event to the list of pending events.
+ PendingUKMEvent pending_event;
+ pending_event.is_main_frame = !frame->GetParent();
+ pending_event.applied_value = applied_value;
+ pending_event.supplied_value = supplied_value;
+ pending_event.ignored_reason = ignored_reason;
+ if (ignored_reason == DisplayCutoutIgnoredReason::kAllowed)
+ pending_event.safe_areas_present = GetSafeAreasPresentUKMValue();
+ pending_ukm_events_.push_back(pending_event);
+}
+
+void DisplayCutoutHostImpl::RecordPendingUKMEvents() {
+ for (const auto& event : pending_ukm_events_) {
+ ukm::builders::Layout_DisplayCutout_StateChanged builder(
+ web_contents_impl()->GetUkmSourceIdForLastCommittedSource());
+ builder.SetIsMainFrame(event.is_main_frame);
+ builder.SetViewportFit_Applied(static_cast<int>(event.applied_value));
+ builder.SetViewportFit_Supplied(static_cast<int>(event.supplied_value));
+ builder.SetViewportFit_IgnoredReason(event.ignored_reason);
+ builder.SetSafeAreasPresent(event.safe_areas_present);
+ builder.Record(ukm::UkmRecorder::Get());
+ }
+
+ pending_ukm_events_.clear();
+}
+
+int DisplayCutoutHostImpl::GetSafeAreasPresentUKMValue() const {
+ int flags = 0;
+ flags |= insets_.top() ? DisplayCutoutSafeArea::kTop : 0;
+ flags |= insets_.left() ? DisplayCutoutSafeArea::kLeft : 0;
+ flags |= insets_.bottom() ? DisplayCutoutSafeArea::kBottom : 0;
+ flags |= insets_.right() ? DisplayCutoutSafeArea::kRight : 0;
+ return flags;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/display_cutout/display_cutout_host_impl.h b/chromium/content/browser/display_cutout/display_cutout_host_impl.h
new file mode 100644
index 00000000000..eba70e23dac
--- /dev/null
+++ b/chromium/content/browser/display_cutout/display_cutout_host_impl.h
@@ -0,0 +1,100 @@
+// Copyright 2018 The Chromium Authors. All 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_DISPLAY_CUTOUT_DISPLAY_CUTOUT_HOST_IMPL_H_
+#define CONTENT_BROWSER_DISPLAY_CUTOUT_DISPLAY_CUTOUT_HOST_IMPL_H_
+
+#include "content/public/browser/web_contents_binding_set.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "third_party/blink/public/mojom/page/display_cutout.mojom.h"
+
+namespace content {
+
+class DisplayCutoutHostImpl : public blink::mojom::DisplayCutoutHost,
+ public WebContentsObserver {
+ public:
+ // Called when the effective viewport fit value has changed.
+ using ViewportFitChangedCallback =
+ base::RepeatingCallback<void(blink::mojom::ViewportFit)>;
+
+ DisplayCutoutHostImpl(WebContentsImpl*, ViewportFitChangedCallback);
+ ~DisplayCutoutHostImpl() override;
+
+ // blink::mojom::DisplayCutoutHost
+ void NotifyViewportFitChanged(blink::mojom::ViewportFit value) override;
+
+ // Stores the updated viewport fit value for a |frame| and notifies observers
+ // if it has changed.
+ void ViewportFitChangedForFrame(RenderFrameHost* rfh,
+ blink::mojom::ViewportFit value);
+
+ // WebContentsObserver override.
+ void DidAcquireFullscreen(RenderFrameHost* rfh) override;
+ void DidToggleFullscreenModeForTab(bool entered_fullscreen,
+ bool will_cause_resize) override;
+ void DidStartNavigation(NavigationHandle* navigation_handle) override;
+ void DidFinishNavigation(NavigationHandle* navigation_handle) override;
+ void RenderFrameDeleted(RenderFrameHost* rfh) override;
+ void RenderFrameCreated(RenderFrameHost* rfh) override;
+ void WebContentsDestroyed() override;
+
+ // Updates the safe area insets on the current frame.
+ void SetDisplayCutoutSafeArea(gfx::Insets insets);
+
+ private:
+ // Stores the data for a pending UKM event.
+ struct PendingUKMEvent {
+ bool is_main_frame;
+ blink::mojom::ViewportFit applied_value;
+ blink::mojom::ViewportFit supplied_value;
+ int ignored_reason;
+ int safe_areas_present = 0;
+ };
+
+ // Set the current |RenderFrameHost| that should have control over the
+ // viewport fit value and we should set safe area insets on.
+ void SetCurrentRenderFrameHost(RenderFrameHost* rfh);
+
+ // Send the safe area insets to a |RenderFrameHost|.
+ void SendSafeAreaToFrame(RenderFrameHost* rfh, gfx::Insets insets);
+
+ // Get the stored viewport fit value for a frame or kAuto if there is no
+ // stored value.
+ blink::mojom::ViewportFit GetValueOrDefault(RenderFrameHost* rfh) const;
+
+ WebContentsImpl* web_contents_impl();
+
+ // Builds and records a Layout.DisplayCutout.StateChanged UKM event for the
+ // provided |frame|. The event will be added to the list of pending events.
+ void MaybeQueueUKMEvent(RenderFrameHost* frame);
+
+ // Records any UKM events that we have not recorded yet.
+ void RecordPendingUKMEvents();
+
+ // Gets the integer value of the current safe areas for recording to UKM.
+ int GetSafeAreasPresentUKMValue() const;
+
+ // Stores pending UKM events.
+ std::list<PendingUKMEvent> pending_ukm_events_;
+
+ // Stores the current safe area insets.
+ gfx::Insets insets_;
+
+ // Stores the current |RenderFrameHost| that has the applied safe area insets
+ // and is controlling the viewport fit value.
+ RenderFrameHost* current_rfh_ = nullptr;
+
+ // Stores a map of RenderFrameHosts and their current viewport fit values.
+ std::map<RenderFrameHost*, blink::mojom::ViewportFit> values_;
+
+ // Stores the callback for when the effective viewport fit value has changed.
+ ViewportFitChangedCallback viewport_fit_changed_callback_;
+
+ // Holds WebContents associated mojo bindings.
+ WebContentsFrameBindingSet<blink::mojom::DisplayCutoutHost> bindings_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DISPLAY_CUTOUT_DISPLAY_CUTOUT_HOST_IMPL_H_
diff --git a/chromium/content/browser/do_not_track_browsertest.cc b/chromium/content/browser/do_not_track_browsertest.cc
index c09c64f7a5b..83c39160e4c 100644
--- a/chromium/content/browser/do_not_track_browsertest.cc
+++ b/chromium/content/browser/do_not_track_browsertest.cc
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/renderer_preferences.h"
#include "content/public/test/browser_test_utils.h"
@@ -9,18 +12,52 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.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"
+
+#if defined(OS_ANDROID)
+#include "base/sys_info.h"
+#endif
namespace content {
namespace {
+class MockContentBrowserClient final : public ContentBrowserClient {
+ public:
+ void UpdateRendererPreferencesForWorker(BrowserContext*,
+ RendererPreferences* prefs) override {
+ prefs->enable_do_not_track = true;
+ prefs->enable_referrers = true;
+ }
+};
+
class DoNotTrackTest : public ContentBrowserTest {
protected:
- void EnableDoNotTrack() {
+ void TearDownOnMainThread() override {
+ if (original_client_)
+ SetBrowserClientForTesting(original_client_);
+ }
+
+ // Returns false if we cannot enable do not track. It happens only when
+ // Android Kitkat or older systems.
+ // TODO(crbug.com/864403): It seems that we call unsupported Android APIs on
+ // KitKat when we set a ContentBrowserClient. Don't call such APIs and make
+ // this test available on KitKat.
+ bool EnableDoNotTrack() {
+#if defined(OS_ANDROID)
+ int32_t major_version = 0, minor_version = 0, bugfix_version = 0;
+ base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version,
+ &bugfix_version);
+ if (major_version < 5)
+ return false;
+#endif
+ original_client_ = SetBrowserClientForTesting(&client_);
RendererPreferences* prefs =
shell()->web_contents()->GetMutableRendererPrefs();
EXPECT_FALSE(prefs->enable_do_not_track);
prefs->enable_do_not_track = true;
+ return true;
}
void ExpectPageTextEq(const std::string& expected_content) {
@@ -41,8 +78,26 @@ class DoNotTrackTest : public ContentBrowserTest {
&value));
return value;
}
+
+ private:
+ ContentBrowserClient* original_client_ = nullptr;
+ MockContentBrowserClient client_;
};
+std::unique_ptr<net::test_server::HttpResponse> CaptureHeaderHandler(
+ const std::string& path,
+ net::test_server::HttpRequest::HeaderMap* header_map,
+ base::OnceClosure done_callback,
+ const net::test_server::HttpRequest& request) {
+ GURL request_url = request.GetURL();
+ if (request_url.path() != path)
+ return nullptr;
+
+ *header_map = request.headers;
+ std::move(done_callback).Run();
+ return std::make_unique<net::test_server::BasicHttpResponse>();
+}
+
// Checks that the DNT header is not sent by default.
IN_PROC_BROWSER_TEST_F(DoNotTrackTest, NotEnabled) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -56,7 +111,8 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, NotEnabled) {
// Checks that the DNT header is sent when the corresponding preference is set.
IN_PROC_BROWSER_TEST_F(DoNotTrackTest, Simple) {
ASSERT_TRUE(embedded_test_server()->Start());
- EnableDoNotTrack();
+ if (!EnableDoNotTrack())
+ return;
GURL url = embedded_test_server()->GetURL("/echoheader?DNT");
EXPECT_TRUE(NavigateToURL(shell(), url));
ExpectPageTextEq("1");
@@ -68,7 +124,8 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, Redirect) {
GURL final_url = embedded_test_server()->GetURL("/echoheader?DNT");
GURL url = embedded_test_server()->GetURL(std::string("/server-redirect?") +
final_url.spec());
- EnableDoNotTrack();
+ if (!EnableDoNotTrack())
+ return;
// We don't check the result NavigateToURL as it returns true only if the
// final URL is equal to the passed URL.
NavigateToURL(shell(), url);
@@ -79,11 +136,137 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, Redirect) {
IN_PROC_BROWSER_TEST_F(DoNotTrackTest, DOMProperty) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/echo");
- EnableDoNotTrack();
+ if (!EnableDoNotTrack())
+ return;
EXPECT_TRUE(NavigateToURL(shell(), url));
EXPECT_EQ("1", GetDOMDoNotTrackProperty());
}
+// Checks that the DNT header is sent in a request for a dedicated worker
+// script.
+IN_PROC_BROWSER_TEST_F(DoNotTrackTest, Worker) {
+ net::test_server::HttpRequest::HeaderMap header_map;
+ base::RunLoop loop;
+ embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
+ &CaptureHeaderHandler, "/capture", &header_map, loop.QuitClosure()));
+ ASSERT_TRUE(embedded_test_server()->Start());
+ if (!EnableDoNotTrack())
+ return;
+ const GURL url = embedded_test_server()->GetURL(
+ std::string("/workers/create_worker.html?worker_url=/capture"));
+ NavigateToURL(shell(), url);
+ loop.Run();
+
+ EXPECT_TRUE(header_map.find("DNT") != header_map.end());
+ EXPECT_EQ("1", header_map["DNT"]);
+}
+
+// Checks that the DNT header is sent in a request for shared worker script.
+// Disabled on Android since a shared worker is not available on Android:
+// crbug.com/869745.
+#if defined(OS_ANDROID)
+#define MAYBE_SharedWorker DISABLED_SharedWorker
+#else
+#define MAYBE_SharedWorker SharedWorker
+#endif
+IN_PROC_BROWSER_TEST_F(DoNotTrackTest, MAYBE_SharedWorker) {
+ net::test_server::HttpRequest::HeaderMap header_map;
+ base::RunLoop loop;
+ embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
+ &CaptureHeaderHandler, "/capture", &header_map, loop.QuitClosure()));
+ ASSERT_TRUE(embedded_test_server()->Start());
+ if (!EnableDoNotTrack())
+ return;
+ const GURL url = embedded_test_server()->GetURL(
+ std::string("/workers/create_shared_worker.html?worker_url=/capture"));
+ NavigateToURL(shell(), url);
+ loop.Run();
+
+ EXPECT_TRUE(header_map.find("DNT") != header_map.end());
+ EXPECT_EQ("1", header_map["DNT"]);
+}
+
+// Checks that the DNT header is sent in a request for a service worker
+// script.
+IN_PROC_BROWSER_TEST_F(DoNotTrackTest, ServiceWorker) {
+ net::test_server::HttpRequest::HeaderMap header_map;
+ base::RunLoop loop;
+ embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
+ &CaptureHeaderHandler, "/capture", &header_map, loop.QuitClosure()));
+ ASSERT_TRUE(embedded_test_server()->Start());
+ if (!EnableDoNotTrack())
+ return;
+ const GURL url = embedded_test_server()->GetURL(std::string(
+ "/service_worker/create_service_worker.html?worker_url=/capture"));
+ NavigateToURL(shell(), url);
+ loop.Run();
+
+ EXPECT_TRUE(header_map.find("DNT") != header_map.end());
+ EXPECT_EQ("1", header_map["DNT"]);
+}
+
+// Checks that the DNT header is preserved when fetching from a dedicated
+// worker.
+IN_PROC_BROWSER_TEST_F(DoNotTrackTest, FetchFromWorker) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ if (!EnableDoNotTrack())
+ return;
+ const GURL fetch_url = embedded_test_server()->GetURL("/echoheader?DNT");
+ const GURL url = embedded_test_server()->GetURL(
+ std::string("/workers/fetch_from_worker.html?url=") + fetch_url.spec());
+ NavigateToURL(shell(), url);
+
+ const base::string16 title = base::ASCIIToUTF16("DONE");
+ TitleWatcher watcher(shell()->web_contents(), title);
+ EXPECT_EQ(title, watcher.WaitAndGetTitle());
+
+ ExpectPageTextEq("1");
+}
+
+// Checks that the DNT header is preserved when fetching from a shared worker.
+//
+// Disabled on Android since a shared worker is not available on Android:
+// crbug.com/869745.
+#if defined(OS_ANDROID)
+#define MAYBE_FetchFromSharedWorker DISABLED_FetchFromSharedWorker
+#else
+#define MAYBE_FetchFromSharedWorker FetchFromSharedWorker
+#endif
+IN_PROC_BROWSER_TEST_F(DoNotTrackTest, MAYBE_FetchFromSharedWorker) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ if (!EnableDoNotTrack())
+ return;
+ const GURL fetch_url = embedded_test_server()->GetURL("/echoheader?DNT");
+ const GURL url = embedded_test_server()->GetURL(
+ std::string("/workers/fetch_from_shared_worker.html?url=") +
+ fetch_url.spec());
+ NavigateToURL(shell(), url);
+
+ const base::string16 title = base::ASCIIToUTF16("DONE");
+ TitleWatcher watcher(shell()->web_contents(), title);
+ EXPECT_EQ(title, watcher.WaitAndGetTitle());
+
+ ExpectPageTextEq("1");
+}
+
+// Checks that the DNT header is preserved when fetching from a service worker.
+IN_PROC_BROWSER_TEST_F(DoNotTrackTest, FetchFromServiceWorker) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ if (!EnableDoNotTrack())
+ return;
+ const GURL fetch_url = embedded_test_server()->GetURL("/echoheader?DNT");
+ const GURL url = embedded_test_server()->GetURL(
+ std::string("/service_worker/fetch_from_service_worker.html?url=") +
+ fetch_url.spec());
+ NavigateToURL(shell(), url);
+
+ const base::string16 title = base::ASCIIToUTF16("DONE");
+ TitleWatcher watcher(shell()->web_contents(), title);
+ EXPECT_EQ(title, watcher.WaitAndGetTitle());
+
+ ExpectPageTextEq("1");
+}
+
} // namespace
-} // namespace content \ No newline at end of file
+} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_area.cc b/chromium/content/browser/dom_storage/dom_storage_area.cc
index 593fa6d693b..590de955c5f 100644
--- a/chromium/content/browser/dom_storage/dom_storage_area.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_area.cc
@@ -24,7 +24,6 @@
#include "content/browser/dom_storage/dom_storage_task_runner.h"
#include "content/browser/dom_storage/session_storage_database.h"
#include "content/browser/dom_storage/session_storage_database_adapter.h"
-#include "content/browser/leveldb_wrapper_impl.h"
#include "content/common/dom_storage/dom_storage_map.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/browser_thread.h"
@@ -106,7 +105,6 @@ url::Origin DOMStorageArea::OriginFromDatabaseFileName(
void DOMStorageArea::EnableAggressiveCommitDelay() {
s_aggressive_flushing_enabled_ = true;
- LevelDBWrapperImpl::EnableAggressiveCommitDelay();
}
DOMStorageArea::DOMStorageArea(const std::string& namespace_id,
diff --git a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc b/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
index 61f3ebdb64a..e2e095605e5 100644
--- a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
@@ -5,18 +5,25 @@
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
#include "content/browser/dom_storage/dom_storage_area.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/dom_storage_database.h"
+#include "content/browser/dom_storage/dom_storage_task_runner.h"
#include "content/browser/dom_storage/local_storage_context_mojo.h"
+#include "content/browser/dom_storage/session_storage_context_mojo.h"
+#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/local_storage_usage_info.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -24,10 +31,15 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_launcher.h"
#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_browser_context.h"
+#include "content/shell/browser/shell_content_browser_client.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace content {
+constexpr const char kTestSessionStorageId[] =
+ "574d2d70-24ca-4d8c-ae23-c7e1e39d07be";
+
// This browser test is aimed towards exercising the DOMStorage system
// from end-to-end.
class DOMStorageBrowserTest : public ContentBrowserTest {
@@ -74,12 +86,21 @@ class DOMStorageBrowserTest : public ContentBrowserTest {
loop.Run();
}
- LocalStorageContextMojo* context() {
+ DOMStorageContextWrapper* context_wrapper() {
return static_cast<DOMStorageContextWrapper*>(
- BrowserContext::GetDefaultStoragePartition(
- shell()->web_contents()->GetBrowserContext())
- ->GetDOMStorageContext())
- ->mojo_state_;
+ BrowserContext::GetDefaultStoragePartition(
+ shell()->web_contents()->GetBrowserContext())
+ ->GetDOMStorageContext());
+ }
+
+ base::SequencedTaskRunner* mojo_task_runner() {
+ return context_wrapper()->mojo_task_runner();
+ }
+
+ LocalStorageContextMojo* context() { return context_wrapper()->mojo_state_; }
+
+ SessionStorageContextMojo* session_storage_context() {
+ return context_wrapper()->mojo_session_state_;
}
base::FilePath legacy_localstorage_path() {
@@ -88,14 +109,19 @@ class DOMStorageBrowserTest : public ContentBrowserTest {
void EnsureConnected() {
base::RunLoop run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &LocalStorageContextMojo::RunWhenConnected,
- base::Unretained(context()),
- base::BindOnce(base::IgnoreResult(&base::TaskRunner::PostTask),
- base::ThreadTaskRunnerHandle::Get(), FROM_HERE,
- run_loop.QuitClosure())));
+ mojo_task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&LocalStorageContextMojo::RunWhenConnected,
+ base::Unretained(context()), run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+
+ void EnsureSessionStorageConnected() {
+ base::RunLoop run_loop;
+ mojo_task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&SessionStorageContextMojo::RunWhenConnected,
+ base::Unretained(session_storage_context()),
+ run_loop.QuitClosure()));
run_loop.Run();
}
};
@@ -194,4 +220,78 @@ IN_PROC_BROWSER_TEST_F(DOMStorageBrowserTest, DataMigrates) {
}
}
+class DOMStorageMigrationBrowserTest : public DOMStorageBrowserTest {
+ public:
+ DOMStorageMigrationBrowserTest() : DOMStorageBrowserTest() {
+ if (IsPreTest())
+ feature_list_.InitAndDisableFeature(features::kMojoSessionStorage);
+ else
+ feature_list_.InitAndEnableFeature(features::kMojoSessionStorage);
+ }
+
+ void SessionStorageTest(const GURL& test_url) {
+ // The test page will perform tests then navigate to either
+ // a #pass or #fail ref.
+ context_wrapper()->SetSaveSessionStorageOnDisk();
+ scoped_refptr<SessionStorageNamespaceImpl> ss_namespace =
+ SessionStorageNamespaceImpl::Create(context_wrapper(),
+ kTestSessionStorageId);
+ ss_namespace->SetShouldPersist(true);
+ Shell* the_browser = Shell::CreateNewWindowWithSessionStorageNamespace(
+ ShellContentBrowserClient::Get()->browser_context(),
+ GURL(url::kAboutBlankURL), nullptr, gfx::Size(),
+ std::move(ss_namespace));
+ NavigateToURLBlockUntilNavigationsComplete(the_browser, test_url, 2);
+ context_wrapper()->Flush();
+ std::string result =
+ the_browser->web_contents()->GetLastCommittedURL().ref();
+ if (result != "pass") {
+ std::string js_result;
+ ASSERT_TRUE(ExecuteScriptAndExtractString(
+ the_browser, "window.domAutomationController.send(getLog())",
+ &js_result));
+ FAIL() << "Failed: " << js_result;
+ }
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(DOMStorageMigrationBrowserTest, PRE_DataMigrates) {
+ SessionStorageTest(
+ GetTestUrl("dom_storage", "store_session_storage_data.html"));
+}
+
+// http://crbug.com/654704 PRE_ tests aren't supported on Android.
+#if defined(OS_ANDROID)
+#define MAYBE_DataMigrates DISABLED_DataMigrates
+#else
+#define MAYBE_DataMigrates DataMigrates
+#endif
+IN_PROC_BROWSER_TEST_F(DOMStorageMigrationBrowserTest, MAYBE_DataMigrates) {
+ EXPECT_TRUE(session_storage_context());
+ EnsureSessionStorageConnected();
+ SessionStorageTest(
+ GetTestUrl("dom_storage", "verify_session_storage_data.html"));
+
+ // Check that we migrated from v0 (no version) to v1.
+ base::RunLoop loop;
+ leveldb::mojom::LevelDBDatabase* database =
+ session_storage_context()->DatabaseForTesting();
+ mojo_task_runner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ database->Get(
+ leveldb::StringPieceToUint8Vector("version"),
+ base::BindLambdaForTesting([&](leveldb::mojom::DatabaseError error,
+ const std::vector<uint8_t>& value) {
+ EXPECT_EQ(leveldb::mojom::DatabaseError::OK, error);
+ EXPECT_EQ(base::StringPiece("1"),
+ leveldb::Uint8VectorToStringPiece(value));
+ loop.Quit();
+ }));
+ }));
+ loop.Run();
+}
+
} // 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 efa6d8dc10f..3d71c01f1ec 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -21,6 +21,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.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"
@@ -153,8 +154,19 @@ DOMStorageContextWrapper::DOMStorageContextWrapper(
if (base::FeatureList::IsEnabled(features::kMojoSessionStorage)) {
mojo_session_state_ = new SessionStorageContextMojo(
- mojo_task_runner_, connector, local_partition_path,
- std::string(kSessionStorageDirectory));
+ mojo_task_runner_, connector,
+
+#if defined(OS_ANDROID)
+ // On Android there is no support for session storage restoring, and
+ // since the restoring code is responsible for database cleanup, we must
+ // manually delete the old database here before we open it.
+ SessionStorageContextMojo::BackingMode::kClearDiskStateOnOpen,
+#else
+ profile_path.empty()
+ ? SessionStorageContextMojo::BackingMode::kNoDisk
+ : SessionStorageContextMojo::BackingMode::kRestoreDiskState,
+#endif
+ local_partition_path, std::string(kSessionStorageDirectory));
}
if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) {
@@ -368,7 +380,7 @@ void DOMStorageContextWrapper::Flush() {
void DOMStorageContextWrapper::OpenLocalStorage(
const url::Origin& origin,
- mojom::LevelDBWrapperRequest request) {
+ blink::mojom::StorageAreaRequest request) {
DCHECK(mojo_state_);
// base::Unretained is safe here, because the mojo_state_ won't be deleted
// until a ShutdownAndDelete task has been ran on the mojo_task_runner_, and
@@ -383,7 +395,7 @@ void DOMStorageContextWrapper::OpenLocalStorage(
void DOMStorageContextWrapper::OpenSessionStorage(
int process_id,
const std::string& namespace_id,
- mojom::SessionStorageNamespaceRequest request) {
+ blink::mojom::SessionStorageNamespaceRequest request) {
if (!mojo_session_state_)
return;
// base::Unretained is safe here, because the mojo_state_ won't be deleted
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 0f2e85e9224..9ab2eed323a 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -14,10 +14,12 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
#include "content/browser/dom_storage/dom_storage_context_impl.h"
#include "content/common/content_export.h"
-#include "content/common/storage_partition_service.mojom.h"
#include "content/public/browser/dom_storage_context.h"
+#include "third_party/blink/public/mojom/dom_storage/session_storage_namespace.mojom.h"
+#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
#include "url/origin.h"
namespace base {
@@ -78,10 +80,10 @@ class CONTENT_EXPORT DOMStorageContextWrapper
// See mojom::StoragePartitionService interface.
void OpenLocalStorage(const url::Origin& origin,
- mojom::LevelDBWrapperRequest request);
+ blink::mojom::StorageAreaRequest request);
void OpenSessionStorage(int process_id,
const std::string& namespace_id,
- mojom::SessionStorageNamespaceRequest request);
+ blink::mojom::SessionStorageNamespaceRequest request);
void SetLocalStorageDatabaseForTesting(
leveldb::mojom::LevelDBDatabaseAssociatedPtr database);
diff --git a/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc b/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
index 5226a1a7a26..d3b199a0e86 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
@@ -354,11 +354,6 @@ TEST(DOMStorageDatabaseTest, TestCanOpenFileThatIsNotADatabase) {
{
sql::test::ScopedErrorExpecter expecter;
-
- // Old SQLite versions returned a different error code.
- ASSERT_GE(expecter.SQLiteLibVersionNumber(), 3014000)
- << "Chrome ships with SQLite 3.22.0+. The system SQLite version is "
- << "only supported on iOS 10+, which ships with SQLite 3.14.0+";
expecter.ExpectError(SQLITE_NOTADB);
// Try and open the file. As it's not a database, we should end up deleting
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.cc b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
index e83a735a3ba..d78f30fb98e 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
@@ -64,11 +64,11 @@ DOMStorageArea* DOMStorageNamespace::GetOpenStorageArea(
return nullptr;
}
-DOMStorageNamespace* DOMStorageNamespace::Clone(
+scoped_refptr<DOMStorageNamespace> DOMStorageNamespace::Clone(
const std::string& clone_namespace_id) {
DCHECK(!namespace_id_.empty());
DCHECK(!clone_namespace_id.empty());
- DOMStorageNamespace* clone = new DOMStorageNamespace(
+ auto clone = base::MakeRefCounted<DOMStorageNamespace>(
clone_namespace_id, session_storage_database_.get(), task_runner_.get());
AreaMap::const_iterator it = areas_.begin();
// Clone the in-memory structures.
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.h b/chromium/content/browser/dom_storage/dom_storage_namespace.h
index 60c1a83bc41..fc2a5c68161 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.h
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.h
@@ -63,7 +63,8 @@ class CONTENT_EXPORT DOMStorageNamespace
// Creates a clone of |this| namespace including
// shallow copies of all contained areas.
// Should only be called for session storage namespaces.
- DOMStorageNamespace* Clone(const std::string& clone_namespace_id);
+ scoped_refptr<DOMStorageNamespace> Clone(
+ const std::string& clone_namespace_id);
void DeleteSessionStorageOrigin(const url::Origin& origin);
void PurgeMemory(bool aggressively);
diff --git a/chromium/content/browser/dom_storage/local_storage_context_mojo.cc b/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
index 369046443da..3d90057ed86 100644
--- a/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
+++ b/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
@@ -27,7 +27,7 @@
#include "content/browser/dom_storage/dom_storage_database.h"
#include "content/browser/dom_storage/dom_storage_task_runner.h"
#include "content/browser/dom_storage/local_storage_database.pb.h"
-#include "content/browser/leveldb_wrapper_impl.h"
+#include "content/browser/dom_storage/storage_area_impl.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/local_storage_usage_info.h"
#include "services/file/public/mojom/constants.mojom.h"
@@ -98,12 +98,11 @@ void DatabaseErrorResponse(base::OnceClosure callback,
void MigrateStorageHelper(
base::FilePath db_path,
const scoped_refptr<base::SingleThreadTaskRunner> reply_task_runner,
- base::Callback<void(std::unique_ptr<LevelDBWrapperImpl::ValueMap>)>
- callback) {
+ base::Callback<void(std::unique_ptr<StorageAreaImpl::ValueMap>)> callback) {
DOMStorageDatabase db(db_path);
DOMStorageValuesMap map;
db.ReadAllValues(&map);
- auto values = std::make_unique<LevelDBWrapperImpl::ValueMap>();
+ auto values = std::make_unique<StorageAreaImpl::ValueMap>();
for (const auto& it : map) {
(*values)[LocalStorageContextMojo::MigrateString(it.first)] =
LocalStorageContextMojo::MigrateString(it.second.string());
@@ -113,8 +112,8 @@ void MigrateStorageHelper(
}
// Helper to convert from OnceCallback to Callback.
-void CallMigrationCalback(LevelDBWrapperImpl::ValueMapCallback callback,
- std::unique_ptr<LevelDBWrapperImpl::ValueMap> data) {
+void CallMigrationCalback(StorageAreaImpl::ValueMapCallback callback,
+ std::unique_ptr<StorageAreaImpl::ValueMap> data) {
std::move(callback).Run(std::move(data));
}
@@ -175,11 +174,10 @@ void RecordCachePurgedHistogram(CachePurgeReason reason,
} // namespace
-class LocalStorageContextMojo::LevelDBWrapperHolder final
- : public LevelDBWrapperImpl::Delegate {
+class LocalStorageContextMojo::StorageAreaHolder final
+ : public StorageAreaImpl::Delegate {
public:
- LevelDBWrapperHolder(LocalStorageContextMojo* context,
- const url::Origin& origin)
+ StorageAreaHolder(LocalStorageContextMojo* context, const url::Origin& origin)
: context_(context), origin_(origin) {
// Delay for a moment after a value is set in anticipation
// of other values being set, so changes are batched.
@@ -191,34 +189,33 @@ class LocalStorageContextMojo::LevelDBWrapperHolder final
static constexpr int kMaxBytesPerHour = kPerStorageAreaQuota;
static constexpr int kMaxCommitsPerHour = 60;
- LevelDBWrapperImpl::Options options;
+ StorageAreaImpl::Options options;
options.max_size = kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance;
options.default_commit_delay = kCommitDefaultDelaySecs;
options.max_bytes_per_hour = kMaxBytesPerHour;
options.max_commits_per_hour = kMaxCommitsPerHour;
#if defined(OS_ANDROID)
- options.cache_mode = LevelDBWrapperImpl::CacheMode::KEYS_ONLY_WHEN_POSSIBLE;
+ options.cache_mode = StorageAreaImpl::CacheMode::KEYS_ONLY_WHEN_POSSIBLE;
#else
- options.cache_mode = LevelDBWrapperImpl::CacheMode::KEYS_AND_VALUES;
+ options.cache_mode = StorageAreaImpl::CacheMode::KEYS_AND_VALUES;
if (base::SysInfo::IsLowEndDevice()) {
- options.cache_mode =
- LevelDBWrapperImpl::CacheMode::KEYS_ONLY_WHEN_POSSIBLE;
+ options.cache_mode = StorageAreaImpl::CacheMode::KEYS_ONLY_WHEN_POSSIBLE;
}
#endif
- level_db_wrapper_ = std::make_unique<LevelDBWrapperImpl>(
+ area_ = std::make_unique<StorageAreaImpl>(
context_->database_.get(),
kDataPrefix + origin_.Serialize() + kOriginSeparator, this, options);
- level_db_wrapper_ptr_ = level_db_wrapper_.get();
+ area_ptr_ = area_.get();
}
- LevelDBWrapperImpl* level_db_wrapper() { return level_db_wrapper_ptr_; }
+ StorageAreaImpl* storage_area() { return area_ptr_; }
void OnNoBindings() override {
has_bindings_ = false;
// Don't delete ourselves, but do schedule an immediate commit. Possible
// deletion will happen under memory pressure or when another localstorage
// area is opened.
- level_db_wrapper()->ScheduleImmediateCommit();
+ storage_area()->ScheduleImmediateCommit();
}
std::vector<leveldb::mojom::BatchedOperationPtr> PrepareToCommit() override {
@@ -240,13 +237,13 @@ class LocalStorageContextMojo::LevelDBWrapperHolder final
leveldb::mojom::BatchedOperation::New();
item->type = leveldb::mojom::BatchOperationType::PUT_KEY;
item->key = CreateMetaDataKey(origin_);
- if (level_db_wrapper()->empty()) {
+ if (storage_area()->empty()) {
item->type = leveldb::mojom::BatchOperationType::DELETE_KEY;
} else {
item->type = leveldb::mojom::BatchOperationType::PUT_KEY;
LocalStorageOriginMetaData data;
data.set_last_modified(base::Time::Now().ToInternalValue());
- data.set_size_bytes(level_db_wrapper()->storage_used());
+ data.set_size_bytes(storage_area()->storage_used());
item->value = leveldb::StdStringToUint8Vector(data.SerializeAsString());
}
operations.push_back(std::move(item));
@@ -274,7 +271,7 @@ class LocalStorageContextMojo::LevelDBWrapperHolder final
context_->OnCommitResult(error);
}
- void MigrateData(LevelDBWrapperImpl::ValueMapCallback callback) override {
+ void MigrateData(StorageAreaImpl::ValueMapCallback callback) override {
if (context_->task_runner_ && !context_->old_localstorage_path_.empty()) {
context_->task_runner_->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
@@ -287,9 +284,9 @@ class LocalStorageContextMojo::LevelDBWrapperHolder final
std::move(callback).Run(nullptr);
}
- std::vector<LevelDBWrapperImpl::Change> FixUpData(
- const LevelDBWrapperImpl::ValueMap& data) override {
- std::vector<LevelDBWrapperImpl::Change> changes;
+ std::vector<StorageAreaImpl::Change> FixUpData(
+ const StorageAreaImpl::ValueMap& data) override {
+ std::vector<StorageAreaImpl::Change> changes;
// Chrome M61/M62 had a bug where keys that should have been encoded as
// Latin1 were instead encoded as UTF16. Fix this by finding any 8-bit only
// keys, and re-encode those. If two encodings of the key exist, the Latin1
@@ -346,9 +343,9 @@ class LocalStorageContextMojo::LevelDBWrapperHolder final
leveldb_env::LEVELDB_STATUS_MAX);
}
- void Bind(mojom::LevelDBWrapperRequest request) {
+ void Bind(blink::mojom::StorageAreaRequest request) {
has_bindings_ = true;
- level_db_wrapper()->Bind(std::move(request));
+ storage_area()->Bind(std::move(request));
}
bool has_bindings() const { return has_bindings_; }
@@ -363,12 +360,12 @@ class LocalStorageContextMojo::LevelDBWrapperHolder final
LocalStorageContextMojo* context_;
url::Origin origin_;
- std::unique_ptr<LevelDBWrapperImpl> level_db_wrapper_;
- // Holds the same value as |level_db_wrapper_|. The reason for this is that
- // during destruction of the LevelDBWrapperImpl instance we might still get
- // called and need access to the LevelDBWrapperImpl instance. The unique_ptr
+ std::unique_ptr<StorageAreaImpl> area_;
+ // Holds the same value as |area_|. The reason for this is that
+ // during destruction of the StorageAreaImpl instance we might still get
+ // called and need access to the StorageAreaImpl instance. The unique_ptr
// could already be null, but this field should still be valid.
- LevelDBWrapperImpl* level_db_wrapper_ptr_;
+ StorageAreaImpl* area_ptr_;
bool deleted_old_data_ = false;
bool has_bindings_ = false;
};
@@ -396,7 +393,7 @@ LocalStorageContextMojo::LocalStorageContextMojo(
void LocalStorageContextMojo::OpenLocalStorage(
const url::Origin& origin,
- mojom::LevelDBWrapperRequest request) {
+ blink::mojom::StorageAreaRequest request) {
RunWhenConnected(base::BindOnce(&LocalStorageContextMojo::BindLocalStorage,
weak_ptr_factory_.GetWeakPtr(), origin,
std::move(request)));
@@ -418,13 +415,13 @@ void LocalStorageContextMojo::DeleteStorage(const url::Origin& origin,
return;
}
- auto found = level_db_wrappers_.find(origin);
- if (found != level_db_wrappers_.end()) {
+ auto found = areas_.find(origin);
+ if (found != areas_.end()) {
// Renderer process expects |source| to always be two newline separated
// strings.
- found->second->level_db_wrapper()->DeleteAll(
+ found->second->storage_area()->DeleteAll(
"\n", base::BindOnce(&SuccessResponse, std::move(callback)));
- found->second->level_db_wrapper()->ScheduleImmediateCommit();
+ found->second->storage_area()->ScheduleImmediateCommit();
} else if (database_) {
std::vector<leveldb::mojom::BatchedOperationPtr> operations;
AddDeleteOriginOperations(&operations, origin);
@@ -442,17 +439,17 @@ void LocalStorageContextMojo::Flush() {
weak_ptr_factory_.GetWeakPtr()));
return;
}
- for (const auto& it : level_db_wrappers_)
- it.second->level_db_wrapper()->ScheduleImmediateCommit();
+ for (const auto& it : areas_)
+ it.second->storage_area()->ScheduleImmediateCommit();
}
void LocalStorageContextMojo::FlushOriginForTesting(const url::Origin& origin) {
if (connection_state_ != CONNECTION_FINISHED)
return;
- const auto& it = level_db_wrappers_.find(origin);
- if (it == level_db_wrappers_.end())
+ const auto& it = areas_.find(origin);
+ if (it == areas_.end())
return;
- it->second->level_db_wrapper()->ScheduleImmediateCommit();
+ it->second->storage_area()->ScheduleImmediateCommit();
}
void LocalStorageContextMojo::ShutdownAndDelete() {
@@ -468,15 +465,15 @@ void LocalStorageContextMojo::ShutdownAndDelete() {
connection_state_ = CONNECTION_SHUTDOWN;
// Flush any uncommitted data.
- for (const auto& it : level_db_wrappers_) {
- auto* wrapper = it.second->level_db_wrapper();
+ for (const auto& it : areas_) {
+ auto* area = it.second->storage_area();
LOCAL_HISTOGRAM_BOOLEAN(
"LocalStorageContext.ShutdownAndDelete.MaybeDroppedChanges",
- wrapper->has_pending_load_tasks());
- wrapper->ScheduleImmediateCommit();
+ area->has_pending_load_tasks());
+ area->ScheduleImmediateCommit();
// TODO(dmurph): Monitor the above histogram, and if dropping changes is
// common then handle that here.
- wrapper->CancelAllPendingRequests();
+ area->CancelAllPendingRequests();
}
// Respect the content policy settings about what to
@@ -500,39 +497,39 @@ void LocalStorageContextMojo::ShutdownAndDelete() {
}
void LocalStorageContextMojo::PurgeMemory() {
- size_t total_cache_size, unused_wrapper_count;
- GetStatistics(&total_cache_size, &unused_wrapper_count);
+ size_t total_cache_size, unused_area_count;
+ GetStatistics(&total_cache_size, &unused_area_count);
- for (auto it = level_db_wrappers_.begin(); it != level_db_wrappers_.end();) {
+ for (auto it = areas_.begin(); it != areas_.end();) {
if (it->second->has_bindings()) {
- it->second->level_db_wrapper()->PurgeMemory();
+ it->second->storage_area()->PurgeMemory();
++it;
} else {
- it = level_db_wrappers_.erase(it);
+ it = areas_.erase(it);
}
}
// Track the size of cache purged.
size_t final_total_cache_size;
- GetStatistics(&final_total_cache_size, &unused_wrapper_count);
+ GetStatistics(&final_total_cache_size, &unused_area_count);
size_t purged_size_kib = (total_cache_size - final_total_cache_size) / 1024;
RecordCachePurgedHistogram(CachePurgeReason::AggressivePurgeTriggered,
purged_size_kib);
}
-void LocalStorageContextMojo::PurgeUnusedWrappersIfNeeded() {
- size_t total_cache_size, unused_wrapper_count;
- GetStatistics(&total_cache_size, &unused_wrapper_count);
+void LocalStorageContextMojo::PurgeUnusedAreasIfNeeded() {
+ size_t total_cache_size, unused_area_count;
+ GetStatistics(&total_cache_size, &unused_area_count);
// Nothing to purge.
- if (!unused_wrapper_count)
+ if (!unused_area_count)
return;
CachePurgeReason purge_reason = CachePurgeReason::NotNeeded;
if (total_cache_size > kMaxLocalStorageCacheSize)
purge_reason = CachePurgeReason::SizeLimitExceeded;
- else if (level_db_wrappers_.size() > kMaxLocalStorageAreaCount)
+ else if (areas_.size() > kMaxLocalStorageAreaCount)
purge_reason = CachePurgeReason::AreaCountLimitExceeded;
else if (is_low_end_device_)
purge_reason = CachePurgeReason::InactiveOnLowEndDevice;
@@ -540,16 +537,16 @@ void LocalStorageContextMojo::PurgeUnusedWrappersIfNeeded() {
if (purge_reason == CachePurgeReason::NotNeeded)
return;
- for (auto it = level_db_wrappers_.begin(); it != level_db_wrappers_.end();) {
+ for (auto it = areas_.begin(); it != areas_.end();) {
if (it->second->has_bindings())
++it;
else
- it = level_db_wrappers_.erase(it);
+ it = areas_.erase(it);
}
// Track the size of cache purged.
size_t final_total_cache_size;
- GetStatistics(&final_total_cache_size, &unused_wrapper_count);
+ GetStatistics(&final_total_cache_size, &unused_area_count);
size_t purged_size_kib = (total_cache_size - final_total_cache_size) / 1024;
RecordCachePurgedHistogram(purge_reason, purged_size_kib);
}
@@ -582,28 +579,28 @@ bool LocalStorageContextMojo::OnMemoryDump(
if (args.level_of_detail ==
base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
- size_t total_cache_size, unused_wrapper_count;
- GetStatistics(&total_cache_size, &unused_wrapper_count);
+ size_t total_cache_size, unused_area_count;
+ GetStatistics(&total_cache_size, &unused_area_count);
auto* mad = pmd->CreateAllocatorDump(context_name + "/cache_size");
mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
total_cache_size);
mad->AddScalar("total_areas",
base::trace_event::MemoryAllocatorDump::kUnitsObjects,
- level_db_wrappers_.size());
+ areas_.size());
return true;
}
- for (const auto& it : level_db_wrappers_) {
+ for (const auto& it : areas_) {
// Limit the url length to 50 and strip special characters.
std::string url = it.first.Serialize().substr(0, 50);
for (size_t index = 0; index < url.size(); ++index) {
if (!std::isalnum(url[index]))
url[index] = '_';
}
- std::string wrapper_dump_name = base::StringPrintf(
+ std::string area_dump_name = base::StringPrintf(
"%s/%s/0x%" PRIXPTR, context_name.c_str(), url.c_str(),
- reinterpret_cast<uintptr_t>(it.second->level_db_wrapper()));
- it.second->level_db_wrapper()->OnMemoryDump(wrapper_dump_name, pmd);
+ reinterpret_cast<uintptr_t>(it.second->storage_area()));
+ it.second->storage_area()->OnMemoryDump(area_dump_name, pmd);
}
return true;
}
@@ -688,7 +685,7 @@ void LocalStorageContextMojo::InitiateConnection(bool in_memory_only) {
void LocalStorageContextMojo::OnDirectoryOpened(base::File::Error err) {
if (err != base::File::Error::FILE_OK) {
// We failed to open the directory; continue with startup so that we create
- // the |level_db_wrappers_|.
+ // the |areas_|.
UMA_HISTOGRAM_ENUMERATION("LocalStorageContext.DirectoryOpenError", -err,
-base::File::FILE_ERROR_MAX);
LogDatabaseOpenResult(OpenResult::DIRECTORY_OPEN_FAILED);
@@ -813,14 +810,14 @@ void LocalStorageContextMojo::OnConnectionFinished() {
void LocalStorageContextMojo::DeleteAndRecreateDatabase(
const char* histogram_name) {
- // We're about to set database_ to null, so delete the LevelDBWrappers
+ // We're about to set database_ to null, so delete the StorageAreaImpls
// that might still be using the old database.
- for (const auto& it : level_db_wrappers_)
- it.second->level_db_wrapper()->CancelAllPendingRequests();
- level_db_wrappers_.clear();
+ for (const auto& it : areas_)
+ it.second->storage_area()->CancelAllPendingRequests();
+ areas_.clear();
// Reset state to be in process of connecting. This will cause requests for
- // LevelDBWrappers to be queued until the connection is complete.
+ // StorageAreas to be queued until the connection is complete.
connection_state_ = CONNECTION_IN_PROGRESS;
commit_error_count_ = 0;
database_ = nullptr;
@@ -875,30 +872,30 @@ void LocalStorageContextMojo::OnDBDestroyed(
// directly from that function, or through |on_database_open_callbacks_|.
void LocalStorageContextMojo::BindLocalStorage(
const url::Origin& origin,
- mojom::LevelDBWrapperRequest request) {
- GetOrCreateDBWrapper(origin)->Bind(std::move(request));
+ blink::mojom::StorageAreaRequest request) {
+ GetOrCreateStorageArea(origin)->Bind(std::move(request));
}
-LocalStorageContextMojo::LevelDBWrapperHolder*
-LocalStorageContextMojo::GetOrCreateDBWrapper(const url::Origin& origin) {
+LocalStorageContextMojo::StorageAreaHolder*
+LocalStorageContextMojo::GetOrCreateStorageArea(const url::Origin& origin) {
DCHECK_EQ(connection_state_, CONNECTION_FINISHED);
- auto found = level_db_wrappers_.find(origin);
- if (found != level_db_wrappers_.end()) {
+ auto found = areas_.find(origin);
+ if (found != areas_.end()) {
return found->second.get();
}
- size_t total_cache_size, unused_wrapper_count;
- GetStatistics(&total_cache_size, &unused_wrapper_count);
+ size_t total_cache_size, unused_area_count;
+ GetStatistics(&total_cache_size, &unused_area_count);
// Track the total localStorage cache size.
UMA_HISTOGRAM_COUNTS_100000("LocalStorageContext.CacheSizeInKB",
total_cache_size / 1024);
- PurgeUnusedWrappersIfNeeded();
+ PurgeUnusedAreasIfNeeded();
- auto holder = std::make_unique<LevelDBWrapperHolder>(this, origin);
- LevelDBWrapperHolder* holder_ptr = holder.get();
- level_db_wrappers_[origin] = std::move(holder);
+ auto holder = std::make_unique<StorageAreaHolder>(this, origin);
+ StorageAreaHolder* holder_ptr = holder.get();
+ areas_[origin] = std::move(holder);
return holder_ptr;
}
@@ -906,10 +903,10 @@ void LocalStorageContextMojo::RetrieveStorageUsage(
GetStorageUsageCallback callback) {
if (!database_) {
// If for whatever reason no leveldb database is available, no storage is
- // used, so return an array only containing the current leveldb wrappers.
+ // used, so return an array only containing the current areas.
std::vector<LocalStorageUsageInfo> result;
base::Time now = base::Time::Now();
- for (const auto& it : level_db_wrappers_) {
+ for (const auto& it : areas_) {
LocalStorageUsageInfo info;
info.origin = it.first.GetURL();
info.last_modified = now;
@@ -952,15 +949,15 @@ void LocalStorageContextMojo::OnGotMetaData(
base::Time::FromInternalValue(row_data.last_modified());
result.push_back(std::move(info));
}
- // Add any origins for which LevelDBWrappers exist, but which haven't
+ // Add any origins for which StorageAreas exist, but which haven't
// committed any data to disk yet.
base::Time now = base::Time::Now();
- for (const auto& it : level_db_wrappers_) {
+ for (const auto& it : areas_) {
if (origins.find(it.first) != origins.end())
continue;
// Skip any origins that definitely don't have any data.
- if (!it.second->level_db_wrapper()->has_pending_load_tasks() &&
- it.second->level_db_wrapper()->empty()) {
+ if (!it.second->storage_area()->has_pending_load_tasks() &&
+ it.second->storage_area()->empty()) {
continue;
}
LocalStorageUsageInfo info;
@@ -999,13 +996,13 @@ void LocalStorageContextMojo::OnShutdownComplete(
}
void LocalStorageContextMojo::GetStatistics(size_t* total_cache_size,
- size_t* unused_wrapper_count) {
+ size_t* unused_area_count) {
*total_cache_size = 0;
- *unused_wrapper_count = 0;
- for (const auto& it : level_db_wrappers_) {
- *total_cache_size += it.second->level_db_wrapper()->memory_used();
+ *unused_area_count = 0;
+ for (const auto& it : areas_) {
+ *total_cache_size += it.second->storage_area()->memory_used();
if (!it.second->has_bindings())
- (*unused_wrapper_count)++;
+ (*unused_area_count)++;
}
}
@@ -1030,8 +1027,8 @@ void LocalStorageContextMojo::OnCommitResult(
}
tried_to_recover_from_commit_errors_ = true;
- // Deleting LevelDBWrappers in here could cause more commits (and commit
- // errors), but those commits won't reach OnCommitResult because the wrapper
+ // Deleting StorageAreas in here could cause more commits (and commit
+ // errors), but those commits won't reach OnCommitResult because the area
// will have been deleted before the commit finishes.
DeleteAndRecreateDatabase(
"LocalStorageContext.OpenResultAfterCommitErrors");
diff --git a/chromium/content/browser/dom_storage/local_storage_context_mojo.h b/chromium/content/browser/dom_storage/local_storage_context_mojo.h
index 3670af2a646..5f7d21c98a7 100644
--- a/chromium/content/browser/dom_storage/local_storage_context_mojo.h
+++ b/chromium/content/browser/dom_storage/local_storage_context_mojo.h
@@ -16,10 +16,11 @@
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "base/trace_event/memory_dump_provider.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
#include "content/common/content_export.h"
-#include "content/common/leveldb_wrapper.mojom.h"
#include "content/public/browser/browser_thread.h"
#include "services/file/public/mojom/file_system.mojom.h"
+#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
#include "url/origin.h"
namespace service_manager {
@@ -56,7 +57,7 @@ class CONTENT_EXPORT LocalStorageContextMojo
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy);
void OpenLocalStorage(const url::Origin& origin,
- mojom::LevelDBWrapperRequest request);
+ blink::mojom::StorageAreaRequest request);
void GetStorageUsage(GetStorageUsageCallback callback);
// |callback| is called when the deletion is sent to the database and
// GetStorageUsage() will not return entries for |origin| anymore.
@@ -80,8 +81,8 @@ class CONTENT_EXPORT LocalStorageContextMojo
// storage for a particular origin will reload the data from the database.
void PurgeMemory();
- // Clears unused leveldb wrappers, when thresholds are reached.
- void PurgeUnusedWrappersIfNeeded();
+ // Clears unused storage areas, when thresholds are reached.
+ void PurgeUnusedAreasIfNeeded();
void SetDatabaseForTesting(
leveldb::mojom::LevelDBDatabaseAssociatedPtr database);
@@ -96,7 +97,7 @@ class CONTENT_EXPORT LocalStorageContextMojo
private:
friend class DOMStorageBrowserTest;
- class LevelDBWrapperHolder;
+ class StorageAreaHolder;
~LocalStorageContextMojo() override;
@@ -119,8 +120,8 @@ class CONTENT_EXPORT LocalStorageContextMojo
// 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::LevelDBWrapperRequest request);
- LevelDBWrapperHolder* GetOrCreateDBWrapper(const url::Origin& origin);
+ blink::mojom::StorageAreaRequest request);
+ StorageAreaHolder* GetOrCreateStorageArea(const url::Origin& origin);
// The (possibly delayed) implementation of GetStorageUsage(). Can be called
// directly from that function, or through |on_database_open_callbacks_|.
@@ -132,7 +133,7 @@ class CONTENT_EXPORT LocalStorageContextMojo
void OnGotStorageUsageForShutdown(std::vector<LocalStorageUsageInfo> usage);
void OnShutdownComplete(leveldb::mojom::DatabaseError error);
- void GetStatistics(size_t* total_cache_size, size_t* unused_wrapper_count);
+ void GetStatistics(size_t* total_cache_size, size_t* unused_area_count);
void OnCommitResult(leveldb::mojom::DatabaseError error);
// These values are written to logs. New enum values can be added, but
@@ -174,8 +175,7 @@ class CONTENT_EXPORT LocalStorageContextMojo
std::vector<base::OnceClosure> on_database_opened_callbacks_;
// Maps between an origin and its prefixed LevelDB view.
- std::map<url::Origin, std::unique_ptr<LevelDBWrapperHolder>>
- level_db_wrappers_;
+ std::map<url::Origin, std::unique_ptr<StorageAreaHolder>> areas_;
// Used to access old data for migration.
scoped_refptr<DOMStorageTaskRunner> task_runner_;
diff --git a/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc b/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
index b758d40ec16..a01c79873af 100644
--- a/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
+++ b/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
@@ -22,13 +22,13 @@
#include "content/browser/dom_storage/test/fake_leveldb_database_error_on_write.h"
#include "content/browser/dom_storage/test/fake_leveldb_service.h"
#include "content/browser/dom_storage/test/mojo_test_with_file_service.h"
+#include "content/browser/dom_storage/test/storage_area_test_util.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/local_storage_usage_info.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "content/test/fake_leveldb_database.h"
-#include "content/test/leveldb_wrapper_test_util.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/binding_set.h"
@@ -63,7 +63,7 @@ void GetStorageUsageCallback(const base::RepeatingClosure& callback,
callback.Run();
}
-class TestLevelDBObserver : public mojom::LevelDBObserver {
+class TestLevelDBObserver : public blink::mojom::StorageAreaObserver {
public:
struct Observation {
enum { kAdd, kChange, kDelete, kDeleteAll } type;
@@ -75,8 +75,8 @@ class TestLevelDBObserver : public mojom::LevelDBObserver {
TestLevelDBObserver() : binding_(this) {}
- mojom::LevelDBObserverAssociatedPtrInfo Bind() {
- mojom::LevelDBObserverAssociatedPtrInfo ptr_info;
+ blink::mojom::StorageAreaObserverAssociatedPtrInfo Bind() {
+ blink::mojom::StorageAreaObserverAssociatedPtrInfo ptr_info;
binding_.Bind(mojo::MakeRequest(&ptr_info));
return ptr_info;
}
@@ -110,7 +110,7 @@ class TestLevelDBObserver : public mojom::LevelDBObserver {
void ShouldSendOldValueOnMutations(bool value) override {}
std::vector<Observation> observations_;
- mojo::AssociatedBinding<mojom::LevelDBObserver> binding_;
+ mojo::AssociatedBinding<blink::mojom::StorageAreaObserver> binding_;
};
} // namespace
@@ -186,12 +186,12 @@ class LocalStorageContextMojoTest : public testing::Test {
base::Optional<std::vector<uint8_t>> DoTestGet(
const std::vector<uint8_t>& key) {
const url::Origin kOrigin = url::Origin::Create(GURL("http://foobar.com"));
- mojom::LevelDBWrapperPtr wrapper;
- mojom::LevelDBWrapperPtr dummy_wrapper; // To make sure values are cached.
- context()->OpenLocalStorage(kOrigin, MakeRequest(&wrapper));
- context()->OpenLocalStorage(kOrigin, MakeRequest(&dummy_wrapper));
+ blink::mojom::StorageAreaPtr area;
+ blink::mojom::StorageAreaPtr dummy_area; // To make sure values are cached.
+ context()->OpenLocalStorage(kOrigin, MakeRequest(&area));
+ context()->OpenLocalStorage(kOrigin, MakeRequest(&dummy_area));
std::vector<uint8_t> result;
- bool success = test::GetSync(wrapper.get(), key, &result);
+ bool success = test::GetSync(area.get(), key, &result);
return success ? base::Optional<std::vector<uint8_t>>(result)
: base::nullopt;
}
@@ -219,11 +219,11 @@ TEST_F(LocalStorageContextMojoTest, Basic) {
auto key = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
- mojom::LevelDBWrapperPtr wrapper;
+ blink::mojom::StorageAreaPtr area;
context()->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
base::RunLoop().RunUntilIdle();
@@ -239,14 +239,14 @@ TEST_F(LocalStorageContextMojoTest, OriginsAreIndependent) {
auto key2 = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
- mojom::LevelDBWrapperPtr wrapper;
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key1, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ blink::mojom::StorageAreaPtr area;
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->Put(key1, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
- context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key2, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ context()->OpenLocalStorage(origin2, MakeRequest(&area));
+ area->Put(key2, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
base::RunLoop().RunUntilIdle();
ASSERT_EQ(5u, mock_data().size());
@@ -257,22 +257,22 @@ TEST_F(LocalStorageContextMojoTest, WrapperOutlivesMojoConnection) {
auto value = StdStringToUint8Vector("value");
// Write some data to the DB.
- mojom::LevelDBWrapperPtr wrapper;
- mojom::LevelDBWrapperPtr dummy_wrapper; // To make sure values are cached.
+ blink::mojom::StorageAreaPtr area;
+ blink::mojom::StorageAreaPtr dummy_area; // To make sure values are cached.
const url::Origin kOrigin(url::Origin::Create(GURL("http://foobar.com")));
- context()->OpenLocalStorage(kOrigin, MakeRequest(&wrapper));
- context()->OpenLocalStorage(kOrigin, MakeRequest(&dummy_wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
- dummy_wrapper.reset();
+ context()->OpenLocalStorage(kOrigin, MakeRequest(&area));
+ context()->OpenLocalStorage(kOrigin, MakeRequest(&dummy_area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
+ dummy_area.reset();
base::RunLoop().RunUntilIdle();
// Clear all the data from the backing database.
EXPECT_FALSE(mock_data().empty());
clear_mock_data();
- // Data should still be readable, because despite closing the wrapper
- // connection above, the actual wrapper instance should have been kept alive.
+ // Data should still be readable, because despite closing the area
+ // connection above, the actual area instance should have been kept alive.
EXPECT_EQ(value, DoTestGet(key));
// Now purge memory.
@@ -287,23 +287,23 @@ TEST_F(LocalStorageContextMojoTest, OpeningWrappersPurgesInactiveWrappers) {
auto value = StdStringToUint8Vector("value");
// Write some data to the DB.
- mojom::LevelDBWrapperPtr wrapper;
+ blink::mojom::StorageAreaPtr area;
context()->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
base::RunLoop().RunUntilIdle();
// Clear all the data from the backing database.
EXPECT_FALSE(mock_data().empty());
clear_mock_data();
- // Now open many new wrappers (for different origins) to trigger clean up.
+ // Now open many new areas (for different origins) to trigger clean up.
for (int i = 1; i <= 100; ++i) {
context()->OpenLocalStorage(url::Origin::Create(GURL(base::StringPrintf(
"http://example.com:%d", i))),
- MakeRequest(&wrapper));
- wrapper.reset();
+ MakeRequest(&area));
+ area.reset();
}
// And make sure caches were actually cleared.
@@ -346,15 +346,15 @@ TEST_F(LocalStorageContextMojoTest, GetStorageUsage_Data) {
base::Time before_write = base::Time::Now();
- mojom::LevelDBWrapperPtr wrapper;
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key1, value, base::nullopt, "source", base::DoNothing());
- wrapper->Put(key2, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ blink::mojom::StorageAreaPtr area;
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->Put(key1, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key2, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
- context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key2, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ context()->OpenLocalStorage(origin2, MakeRequest(&area));
+ area->Put(key2, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
// GetStorageUsage only includes committed data, but still returns all origins
// that used localstorage with zero size.
@@ -393,16 +393,16 @@ TEST_F(LocalStorageContextMojoTest, MetaDataClearedOnDelete) {
auto key = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
- mojom::LevelDBWrapperPtr wrapper;
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
- context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Delete(key, value, "source", base::DoNothing());
- wrapper.reset();
+ blink::mojom::StorageAreaPtr area;
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
+ context()->OpenLocalStorage(origin2, MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->Delete(key, value, "source", base::DoNothing());
+ area.reset();
// Make sure all data gets committed to disk.
base::RunLoop().RunUntilIdle();
@@ -426,17 +426,17 @@ TEST_F(LocalStorageContextMojoTest, MetaDataClearedOnDeleteAll) {
auto key = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
- mojom::LevelDBWrapperPtr wrapper;
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
- context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ blink::mojom::StorageAreaPtr area;
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
+ context()->OpenLocalStorage(origin2, MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->DeleteAll("source", base::DoNothing());
- wrapper.reset();
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->DeleteAll("source", base::DoNothing());
+ area.reset();
// Make sure all data gets committed to disk.
base::RunLoop().RunUntilIdle();
@@ -471,14 +471,14 @@ TEST_F(LocalStorageContextMojoTest, DeleteStorageWithoutConnection) {
auto key = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
- mojom::LevelDBWrapperPtr wrapper;
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ blink::mojom::StorageAreaPtr area;
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
- context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ context()->OpenLocalStorage(origin2, MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
// Make sure all data gets committed to disk.
base::RunLoop().RunUntilIdle();
@@ -506,22 +506,22 @@ TEST_F(LocalStorageContextMojoTest, DeleteStorageNotifiesWrapper) {
auto key = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
- mojom::LevelDBWrapperPtr wrapper;
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ blink::mojom::StorageAreaPtr area;
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
- context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ context()->OpenLocalStorage(origin2, MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
// Make sure all data gets committed to disk.
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(mock_data().empty());
TestLevelDBObserver observer;
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->AddObserver(observer.Bind());
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->AddObserver(observer.Bind());
base::RunLoop().RunUntilIdle();
context()->DeleteStorage(origin1, base::DoNothing());
@@ -550,24 +550,24 @@ TEST_F(LocalStorageContextMojoTest, DeleteStorageWithPendingWrites) {
auto key = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
- mojom::LevelDBWrapperPtr wrapper;
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ blink::mojom::StorageAreaPtr area;
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
- context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ context()->OpenLocalStorage(origin2, MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
// Make sure all data gets committed to disk.
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(mock_data().empty());
TestLevelDBObserver observer;
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->AddObserver(observer.Bind());
- wrapper->Put(StdStringToUint8Vector("key2"), value, base::nullopt, "source",
- base::DoNothing());
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->AddObserver(observer.Bind());
+ area->Put(StdStringToUint8Vector("key2"), value, base::nullopt, "source",
+ base::DoNothing());
base::RunLoop().RunUntilIdle();
context()->DeleteStorage(origin1, base::DoNothing());
@@ -613,27 +613,27 @@ TEST_F(LocalStorageContextMojoTest, Migration) {
EXPECT_TRUE(base::PathExists(old_db_path));
// Opening origin2 and accessing its data should not migrate anything.
- mojom::LevelDBWrapperPtr wrapper;
- context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- mojom::LevelDBWrapperPtr dummy_wrapper; // To make sure values are cached.
- context()->OpenLocalStorage(origin2, MakeRequest(&dummy_wrapper));
- wrapper->Get(std::vector<uint8_t>(), base::DoNothing());
- wrapper.reset();
- dummy_wrapper.reset();
+ blink::mojom::StorageAreaPtr area;
+ context()->OpenLocalStorage(origin2, MakeRequest(&area));
+ blink::mojom::StorageAreaPtr dummy_area; // To make sure values are cached.
+ context()->OpenLocalStorage(origin2, MakeRequest(&dummy_area));
+ area->Get(std::vector<uint8_t>(), base::DoNothing());
+ area.reset();
+ dummy_area.reset();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(mock_data().empty());
// Opening origin1 and accessing its data should migrate its storage.
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- context()->OpenLocalStorage(origin1, MakeRequest(&dummy_wrapper));
- wrapper->Get(std::vector<uint8_t>(), base::DoNothing());
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ context()->OpenLocalStorage(origin1, MakeRequest(&dummy_area));
+ area->Get(std::vector<uint8_t>(), base::DoNothing());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(mock_data().empty());
{
std::vector<uint8_t> result;
bool success = test::GetSync(
- wrapper.get(), LocalStorageContextMojo::MigrateString(key), &result);
+ area.get(), LocalStorageContextMojo::MigrateString(key), &result);
EXPECT_TRUE(success);
EXPECT_EQ(LocalStorageContextMojo::MigrateString(value), result);
}
@@ -641,7 +641,7 @@ TEST_F(LocalStorageContextMojoTest, Migration) {
{
std::vector<uint8_t> result;
bool success = test::GetSync(
- wrapper.get(), LocalStorageContextMojo::MigrateString(key2), &result);
+ area.get(), LocalStorageContextMojo::MigrateString(key2), &result);
EXPECT_TRUE(success);
EXPECT_EQ(LocalStorageContextMojo::MigrateString(value), result);
}
@@ -677,23 +677,23 @@ TEST_F(LocalStorageContextMojoTest, FixUp) {
EncodeKeyAsUTF16("http://foobar.com", base::ASCIIToUTF16("foo")),
"value3");
- mojom::LevelDBWrapperPtr wrapper;
- mojom::LevelDBWrapperPtr dummy_wrapper; // To make sure values are cached.
+ blink::mojom::StorageAreaPtr area;
+ blink::mojom::StorageAreaPtr dummy_area; // To make sure values are cached.
context()->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper));
+ MakeRequest(&area));
context()->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&dummy_wrapper));
+ MakeRequest(&dummy_area));
{
std::vector<uint8_t> result;
bool success = test::GetSync(
- wrapper.get(), leveldb::StdStringToUint8Vector("\x01key"), &result);
+ area.get(), leveldb::StdStringToUint8Vector("\x01key"), &result);
EXPECT_TRUE(success);
EXPECT_EQ(leveldb::StdStringToUint8Vector("value1"), result);
}
{
std::vector<uint8_t> result;
- bool success = test::GetSync(wrapper.get(),
+ bool success = test::GetSync(area.get(),
leveldb::StdStringToUint8Vector("\x01"
"foo"),
&result);
@@ -717,15 +717,15 @@ TEST_F(LocalStorageContextMojoTest, ShutdownClearsData) {
auto key2 = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
- mojom::LevelDBWrapperPtr wrapper;
- context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key1, value, base::nullopt, "source", base::DoNothing());
- wrapper->Put(key2, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ blink::mojom::StorageAreaPtr area;
+ context()->OpenLocalStorage(origin1, MakeRequest(&area));
+ area->Put(key1, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key2, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
- context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key2, value, base::nullopt, "source", base::DoNothing());
- wrapper.reset();
+ context()->OpenLocalStorage(origin2, MakeRequest(&area));
+ area->Put(key2, value, base::nullopt, "source", base::DoNothing());
+ area.reset();
// Make sure all data gets committed to the DB.
base::RunLoop().RunUntilIdle();
@@ -756,36 +756,36 @@ class LocalStorageContextMojoTestWithService
void DoTestPut(LocalStorageContextMojo* context,
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value) {
- mojom::LevelDBWrapperPtr wrapper;
+ blink::mojom::StorageAreaPtr area;
bool success = false;
base::RunLoop run_loop;
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper));
- wrapper->Put(key, value, base::nullopt, "source",
- test::MakeSuccessCallback(run_loop.QuitClosure(), &success));
+ MakeRequest(&area));
+ area->Put(key, value, base::nullopt, "source",
+ test::MakeSuccessCallback(run_loop.QuitClosure(), &success));
run_loop.Run();
EXPECT_TRUE(success);
- wrapper.reset();
- base::RunLoop().RunUntilIdle();
+ area.reset();
+ RunUntilIdle();
}
bool DoTestGet(LocalStorageContextMojo* context,
const std::vector<uint8_t>& key,
std::vector<uint8_t>* result) {
- mojom::LevelDBWrapperPtr wrapper;
+ blink::mojom::StorageAreaPtr area;
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper));
+ MakeRequest(&area));
base::RunLoop run_loop;
- std::vector<content::mojom::KeyValuePtr> data;
- leveldb::mojom::DatabaseError status;
+ std::vector<blink::mojom::KeyValuePtr> data;
+ bool success = false;
bool done = false;
- wrapper->GetAll(
+ area->GetAll(
test::GetAllCallback::CreateAndBind(&done, run_loop.QuitClosure()),
- test::MakeGetAllCallback(&status, &data));
+ test::MakeGetAllCallback(&success, &data));
run_loop.Run();
EXPECT_TRUE(done);
- EXPECT_EQ(status, leveldb::mojom::DatabaseError::OK);
+ EXPECT_TRUE(success);
for (auto& entry : data) {
if (key == entry->key) {
@@ -805,6 +805,15 @@ class LocalStorageContextMojoTestWithService
}
private:
+ // testing::Test:
+ void TearDown() override {
+ // Some of these tests close message pipes which serve as master interfaces
+ // to other associated interfaces; this in turn schedules tasks to invoke
+ // the associated interfaces' error handlers, and local storage code relies
+ // on those handlers running in order to avoid memory leaks at shutdown.
+ RunUntilIdle();
+ }
+
DISALLOW_COPY_AND_ASSIGN(LocalStorageContextMojoTestWithService);
};
@@ -815,9 +824,9 @@ TEST_F(LocalStorageContextMojoTestWithService, InMemory) {
auto key = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
- mojom::LevelDBWrapperPtr wrapper;
+ blink::mojom::StorageAreaPtr area;
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper));
+ MakeRequest(&area));
DoTestPut(context, key, value);
std::vector<uint8_t> result;
EXPECT_TRUE(DoTestGet(context, key, &result));
@@ -825,7 +834,7 @@ TEST_F(LocalStorageContextMojoTestWithService, InMemory) {
context->ShutdownAndDelete();
context = nullptr;
- base::RunLoop().RunUntilIdle();
+ RunUntilIdle();
// Should not have created any files.
EXPECT_TRUE(FirstEntryInDir().empty());
@@ -845,9 +854,9 @@ TEST_F(LocalStorageContextMojoTestWithService, InMemoryInvalidPath) {
auto key = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
- mojom::LevelDBWrapperPtr wrapper;
+ blink::mojom::StorageAreaPtr area;
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper));
+ MakeRequest(&area));
DoTestPut(context, key, value);
std::vector<uint8_t> result;
@@ -856,7 +865,7 @@ TEST_F(LocalStorageContextMojoTestWithService, InMemoryInvalidPath) {
context->ShutdownAndDelete();
context = nullptr;
- base::RunLoop().RunUntilIdle();
+ RunUntilIdle();
// Should not have created any files.
EXPECT_TRUE(FirstEntryInDir().empty());
@@ -877,7 +886,7 @@ TEST_F(LocalStorageContextMojoTestWithService, OnDisk) {
context->ShutdownAndDelete();
context = nullptr;
- base::RunLoop().RunUntilIdle();
+ RunUntilIdle();
// Should have created files.
EXPECT_EQ(test_path, FirstEntryInDir().BaseName());
@@ -908,7 +917,7 @@ TEST_F(LocalStorageContextMojoTestWithService, InvalidVersionOnDisk) {
context->ShutdownAndDelete();
context = nullptr;
- base::RunLoop().RunUntilIdle();
+ RunUntilIdle();
{
// Mess up version number in database.
@@ -933,7 +942,7 @@ TEST_F(LocalStorageContextMojoTestWithService, InvalidVersionOnDisk) {
context->ShutdownAndDelete();
context = nullptr;
- base::RunLoop().RunUntilIdle();
+ RunUntilIdle();
// Data should have been preserved now.
context = new LocalStorageContextMojo(base::ThreadTaskRunnerHandle::Get(),
@@ -961,9 +970,7 @@ TEST_F(LocalStorageContextMojoTestWithService, CorruptionOnDisk) {
context->ShutdownAndDelete();
context = nullptr;
- base::RunLoop().RunUntilIdle();
- // Also flush Task Scheduler tasks to make sure the leveldb is fully closed.
- content::RunAllTasksUntilIdle();
+ RunUntilIdle();
// Delete manifest files to mess up opening DB.
base::FilePath db_path =
@@ -986,7 +993,7 @@ TEST_F(LocalStorageContextMojoTestWithService, CorruptionOnDisk) {
context->ShutdownAndDelete();
context = nullptr;
- base::RunLoop().RunUntilIdle();
+ RunUntilIdle();
// Data should have been preserved now.
context = new LocalStorageContextMojo(base::ThreadTaskRunnerHandle::Get(),
@@ -1019,26 +1026,26 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
// Open three connections to the database. Two to the same origin, and a third
// to a different origin.
- mojom::LevelDBWrapperPtr wrapper1;
- mojom::LevelDBWrapperPtr wrapper2;
- mojom::LevelDBWrapperPtr wrapper3;
+ blink::mojom::StorageAreaPtr area1;
+ blink::mojom::StorageAreaPtr area2;
+ blink::mojom::StorageAreaPtr area3;
{
base::RunLoop loop;
mock_leveldb_service.SetOnOpenCallback(loop.QuitClosure());
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper1));
+ MakeRequest(&area1));
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper2));
+ MakeRequest(&area2));
context->OpenLocalStorage(url::Origin::Create(GURL("http://example.com")),
- MakeRequest(&wrapper3));
+ MakeRequest(&area3));
loop.Run();
}
// Add observers to the first two connections.
TestLevelDBObserver observer1;
- wrapper1->AddObserver(observer1.Bind());
+ area1->AddObserver(observer1.Bind());
TestLevelDBObserver observer2;
- wrapper2->AddObserver(observer2.Bind());
+ area2->AddObserver(observer2.Bind());
// Verify one attempt was made to open the database, and connect that request
// with a database implementation that always fails on write.
@@ -1060,22 +1067,22 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
// a lot of data on the first origin. This put operation should result in a
// pending commit that will get cancelled when the database connection is
// closed.
- wrapper3->Put(key, value, base::nullopt, "source",
- base::BindOnce([](bool success) { EXPECT_TRUE(success); }));
+ area3->Put(key, value, base::nullopt, "source",
+ base::BindOnce([](bool success) { EXPECT_TRUE(success); }));
// Repeatedly write data to the database, to trigger enough commit errors.
size_t values_written = 0;
- while (!wrapper1.encountered_error()) {
+ while (!area1.encountered_error()) {
base::RunLoop put_loop;
// Every write needs to be different to make sure there actually is a
// change to commit.
value[0]++;
- wrapper1.set_connection_error_handler(put_loop.QuitClosure());
- wrapper1->Put(key, value, base::nullopt, "source",
- base::BindLambdaForTesting([&](bool success) {
- EXPECT_TRUE(success);
- put_loop.Quit();
- }));
+ area1.set_connection_error_handler(put_loop.QuitClosure());
+ area1->Put(key, value, base::nullopt, "source",
+ base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
put_loop.RunUntilIdle();
values_written++;
// And we need to flush after every change. Otherwise changes get batched up
@@ -1092,24 +1099,24 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
// connection to the database to have been severed.
EXPECT_FALSE(mock_db);
- // The connection to the second wrapper should have closed as well.
- EXPECT_TRUE(wrapper2.encountered_error());
+ // The connection to the second area should have closed as well.
+ EXPECT_TRUE(area2.encountered_error());
// And the old database should have been destroyed.
EXPECT_EQ(1u, mock_leveldb_service.destroy_requests().size());
- // Reconnect wrapper1 to the database, and try to read a value.
+ // Reconnect area1 to the database, and try to read a value.
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper1));
+ MakeRequest(&area1));
base::RunLoop delete_loop;
bool success = true;
TestLevelDBObserver observer3;
- wrapper1->AddObserver(observer3.Bind());
- wrapper1->Delete(key, base::nullopt, "source",
- base::BindLambdaForTesting([&](bool success_in) {
- success = success_in;
- delete_loop.Quit();
- }));
+ area1->AddObserver(observer3.Bind());
+ area1->Delete(key, base::nullopt, "source",
+ base::BindLambdaForTesting([&](bool success_in) {
+ success = success_in;
+ delete_loop.Quit();
+ }));
// Wait for LocalStorageContextMojo to try to reconnect to the database, and
// connect that new request to a properly functioning database.
@@ -1122,11 +1129,11 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
std::move(reopen_request.callback).Run(leveldb::mojom::DatabaseError::OK);
mock_leveldb_service.open_requests().clear();
- // And deleting the value from the new wrapper should have failed (as the
+ // And deleting the value from the new area should have failed (as the
// database is empty).
delete_loop.Run();
EXPECT_EQ(0u, observer3.observations().size());
- wrapper1 = nullptr;
+ area1 = nullptr;
{
// Committing data should now work.
@@ -1168,12 +1175,12 @@ TEST_F(LocalStorageContextMojoTestWithService,
auto value = StdStringToUint8Vector("value");
// Open a connection to the database.
- mojom::LevelDBWrapperPtr wrapper;
+ blink::mojom::StorageAreaPtr area;
{
base::RunLoop loop;
mock_leveldb_service.SetOnOpenCallback(loop.QuitClosure());
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper));
+ MakeRequest(&area));
loop.Run();
}
@@ -1195,17 +1202,17 @@ TEST_F(LocalStorageContextMojoTestWithService,
// Repeatedly write data to the database, to trigger enough commit errors.
base::Optional<std::vector<uint8_t>> old_value;
- while (!wrapper.encountered_error()) {
+ while (!area.encountered_error()) {
base::RunLoop put_loop;
// Every write needs to be different to make sure there actually is a
// change to commit.
value[0]++;
- wrapper.set_connection_error_handler(put_loop.QuitClosure());
- wrapper->Put(key, value, old_value, "source",
- base::BindLambdaForTesting([&](bool success) {
- EXPECT_TRUE(success);
- put_loop.Quit();
- }));
+ area.set_connection_error_handler(put_loop.QuitClosure());
+ area->Put(key, value, old_value, "source",
+ base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
old_value = std::vector<uint8_t>(value);
put_loop.RunUntilIdle();
// And we need to flush after every change. Otherwise changes get batched up
@@ -1237,23 +1244,23 @@ TEST_F(LocalStorageContextMojoTestWithService,
// The old database should also have been destroyed.
EXPECT_EQ(1u, mock_leveldb_service.destroy_requests().size());
- // Reconnect a wrapper to the database, and repeatedly write data to it again.
+ // Reconnect a area to the database, and repeatedly write data to it again.
// This time all should just keep getting written, and commit errors are
// getting ignored.
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
- MakeRequest(&wrapper));
+ MakeRequest(&area));
old_value = base::nullopt;
for (int i = 0; i < 64; ++i) {
base::RunLoop put_loop;
// Every write needs to be different to make sure there actually is a
// change to commit.
value[0]++;
- wrapper.set_connection_error_handler(put_loop.QuitClosure());
- wrapper->Put(key, value, old_value, "source",
- base::BindLambdaForTesting([&](bool success) {
- EXPECT_TRUE(success);
- put_loop.Quit();
- }));
+ area.set_connection_error_handler(put_loop.QuitClosure());
+ area->Put(key, value, old_value, "source",
+ base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
put_loop.RunUntilIdle();
old_value = value;
// And we need to flush after every change. Otherwise changes get batched up
@@ -1267,7 +1274,7 @@ TEST_F(LocalStorageContextMojoTestWithService,
if (mock_db)
mock_db->FlushForTesting();
EXPECT_TRUE(mock_db);
- EXPECT_FALSE(wrapper.encountered_error());
+ EXPECT_FALSE(area.encountered_error());
}
} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.cc b/chromium/content/browser/dom_storage/session_storage_area_impl.cc
index 2e20a45d2c3..0ba8ed4b9a6 100644
--- a/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.cc
+++ b/chromium/content/browser/dom_storage/session_storage_area_impl.cc
@@ -2,9 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/dom_storage/session_storage_leveldb_wrapper.h"
+#include "content/browser/dom_storage/session_storage_area_impl.h"
#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "content/browser/dom_storage/session_storage_data_map.h"
#include "content/common/dom_storage/dom_storage_types.h"
@@ -12,7 +14,7 @@
namespace content {
-SessionStorageLevelDBWrapper::SessionStorageLevelDBWrapper(
+SessionStorageAreaImpl::SessionStorageAreaImpl(
SessionStorageMetadata::NamespaceEntry namespace_entry,
url::Origin origin,
scoped_refptr<SessionStorageDataMap> data_map,
@@ -23,41 +25,47 @@ SessionStorageLevelDBWrapper::SessionStorageLevelDBWrapper(
register_new_map_callback_(std::move(register_new_map_callback)),
binding_(this) {}
-SessionStorageLevelDBWrapper::~SessionStorageLevelDBWrapper() {
+SessionStorageAreaImpl::~SessionStorageAreaImpl() {
if (binding_.is_bound())
shared_data_map_->RemoveBindingReference();
}
-void SessionStorageLevelDBWrapper::Bind(
- mojom::LevelDBWrapperAssociatedRequest request) {
- DCHECK(!IsBound());
- shared_data_map_->AddBindingReference();
+void SessionStorageAreaImpl::Bind(
+ blink::mojom::StorageAreaAssociatedRequest request) {
+ if (IsBound()) {
+ binding_.Unbind();
+ } else {
+ shared_data_map_->AddBindingReference();
+ }
binding_.Bind(std::move(request));
- binding_.set_connection_error_handler(
- base::BindOnce(&SessionStorageLevelDBWrapper::OnConnectionError,
- base::Unretained(this)));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &SessionStorageAreaImpl::OnConnectionError, base::Unretained(this)));
}
-std::unique_ptr<SessionStorageLevelDBWrapper>
-SessionStorageLevelDBWrapper::Clone(
+std::unique_ptr<SessionStorageAreaImpl> SessionStorageAreaImpl::Clone(
SessionStorageMetadata::NamespaceEntry namespace_entry) {
DCHECK(namespace_entry_ != namespace_entry);
- return base::WrapUnique(new SessionStorageLevelDBWrapper(
+ return base::WrapUnique(new SessionStorageAreaImpl(
namespace_entry, origin_, shared_data_map_, register_new_map_callback_));
}
-// LevelDBWrapper:
-void SessionStorageLevelDBWrapper::AddObserver(
- mojom::LevelDBObserverAssociatedPtrInfo observer) {
- mojom::LevelDBObserverAssociatedPtr observer_ptr;
+void SessionStorageAreaImpl::NotifyObserversAllDeleted() {
+ observers_.ForAllPtrs([](blink::mojom::StorageAreaObserver* observer) {
+ // Renderer process expects |source| to always be two newline separated
+ // strings.
+ observer->AllDeleted("\n");
+ });
+}
+
+// blink::mojom::StorageArea:
+void SessionStorageAreaImpl::AddObserver(
+ blink::mojom::StorageAreaObserverAssociatedPtrInfo observer) {
+ blink::mojom::StorageAreaObserverAssociatedPtr observer_ptr;
observer_ptr.Bind(std::move(observer));
- mojo::InterfacePtrSetElementId ptr_id =
- shared_data_map_->level_db_wrapper()->AddObserver(
- std::move(observer_ptr));
- observer_ptrs_.push_back(ptr_id);
+ observers_.AddPtr(std::move(observer_ptr));
}
-void SessionStorageLevelDBWrapper::Put(
+void SessionStorageAreaImpl::Put(
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
const base::Optional<std::vector<uint8_t>>& client_old_value,
@@ -67,11 +75,11 @@ void SessionStorageLevelDBWrapper::Put(
DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
if (shared_data_map_->map_data()->ReferenceCount() > 1)
CreateNewMap(NewMapType::FORKED, base::nullopt);
- shared_data_map_->level_db_wrapper()->Put(key, value, client_old_value,
- source, std::move(callback));
+ shared_data_map_->storage_area()->Put(key, value, client_old_value, source,
+ std::move(callback));
}
-void SessionStorageLevelDBWrapper::Delete(
+void SessionStorageAreaImpl::Delete(
const std::vector<uint8_t>& key,
const base::Optional<std::vector<uint8_t>>& client_old_value,
const std::string& source,
@@ -80,40 +88,40 @@ void SessionStorageLevelDBWrapper::Delete(
DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
if (shared_data_map_->map_data()->ReferenceCount() > 1)
CreateNewMap(NewMapType::FORKED, base::nullopt);
- shared_data_map_->level_db_wrapper()->Delete(key, client_old_value, source,
- std::move(callback));
+ shared_data_map_->storage_area()->Delete(key, client_old_value, source,
+ std::move(callback));
}
-void SessionStorageLevelDBWrapper::DeleteAll(const std::string& source,
- DeleteAllCallback callback) {
- DCHECK(IsBound());
- DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
+void SessionStorageAreaImpl::DeleteAll(const std::string& source,
+ DeleteAllCallback callback) {
+ // Note: This can be called by the Clear Browsing Data flow, and thus doesn't
+ // have to be bound.
if (shared_data_map_->map_data()->ReferenceCount() > 1) {
CreateNewMap(NewMapType::EMPTY_FROM_DELETE_ALL, source);
std::move(callback).Run(true);
return;
}
- shared_data_map_->level_db_wrapper()->DeleteAll(source, std::move(callback));
+ shared_data_map_->storage_area()->DeleteAll(source, std::move(callback));
}
-void SessionStorageLevelDBWrapper::Get(const std::vector<uint8_t>& key,
- GetCallback callback) {
+void SessionStorageAreaImpl::Get(const std::vector<uint8_t>& key,
+ GetCallback callback) {
DCHECK(IsBound());
DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
- shared_data_map_->level_db_wrapper()->Get(key, std::move(callback));
+ shared_data_map_->storage_area()->Get(key, std::move(callback));
}
-void SessionStorageLevelDBWrapper::GetAll(
- mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo complete_callback,
+void SessionStorageAreaImpl::GetAll(
+ blink::mojom::StorageAreaGetAllCallbackAssociatedPtrInfo complete_callback,
GetAllCallback callback) {
DCHECK(IsBound());
DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
- shared_data_map_->level_db_wrapper()->GetAll(std::move(complete_callback),
- std::move(callback));
+ shared_data_map_->storage_area()->GetAll(std::move(complete_callback),
+ std::move(callback));
}
// Note: this can be called after invalidation of the |namespace_entry_|.
-void SessionStorageLevelDBWrapper::OnConnectionError() {
+void SessionStorageAreaImpl::OnConnectionError() {
shared_data_map_->RemoveBindingReference();
// Make sure we totally unbind the binding - this doesn't seem to happen
// automatically on connection error. The bound status is used in the
@@ -122,23 +130,16 @@ void SessionStorageLevelDBWrapper::OnConnectionError() {
binding_.Unbind();
}
-void SessionStorageLevelDBWrapper::CreateNewMap(
+void SessionStorageAreaImpl::CreateNewMap(
NewMapType map_type,
const base::Optional<std::string>& delete_all_source) {
- std::vector<mojom::LevelDBObserverAssociatedPtr> ptrs_to_move;
- for (const mojo::InterfacePtrSetElementId& ptr_id : observer_ptrs_) {
- DCHECK(shared_data_map_->level_db_wrapper()->HasObserver(ptr_id));
- ptrs_to_move.push_back(
- shared_data_map_->level_db_wrapper()->RemoveObserver(ptr_id));
- }
- observer_ptrs_.clear();
shared_data_map_->RemoveBindingReference();
switch (map_type) {
case NewMapType::FORKED:
shared_data_map_ = SessionStorageDataMap::CreateClone(
shared_data_map_->listener(),
register_new_map_callback_.Run(namespace_entry_, origin_),
- shared_data_map_->level_db_wrapper());
+ shared_data_map_->storage_area());
break;
case NewMapType::EMPTY_FROM_DELETE_ALL: {
// The code optimizes the 'delete all' for shared maps by just creating
@@ -147,19 +148,11 @@ void SessionStorageLevelDBWrapper::CreateNewMap(
shared_data_map_ = SessionStorageDataMap::Create(
shared_data_map_->listener(),
register_new_map_callback_.Run(namespace_entry_, origin_),
- shared_data_map_->level_db_wrapper()->database());
- for (auto& ptr : ptrs_to_move) {
- ptr->AllDeleted(delete_all_source.value_or("\n"));
- }
+ shared_data_map_->storage_area()->database());
break;
}
}
shared_data_map_->AddBindingReference();
-
- for (auto& observer_ptr : ptrs_to_move) {
- observer_ptrs_.push_back(shared_data_map_->level_db_wrapper()->AddObserver(
- std::move(observer_ptr)));
- }
}
} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.h b/chromium/content/browser/dom_storage/session_storage_area_impl.h
index 0a856c8b05a..0cd28db8403 100644
--- a/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.h
+++ b/chromium/content/browser/dom_storage/session_storage_area_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_DOM_STORAGE_SESSION_STORAGE_LEVELDB_WRAPPER_H_
-#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_LEVELDB_WRAPPER_H_
+#ifndef CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_AREA_IMPL_H_
+#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_AREA_IMPL_H_
#include <vector>
@@ -11,9 +11,8 @@
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "content/browser/dom_storage/session_storage_metadata.h"
-#include "content/browser/leveldb_wrapper_impl.h"
+#include "content/browser/dom_storage/storage_area_impl.h"
#include "content/common/content_export.h"
-#include "content/common/leveldb_wrapper.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/interface_ptr_set.h"
#include "url/origin.h"
@@ -22,7 +21,7 @@ namespace content {
class SessionStorageDataMap;
// This class provides session storage access to the renderer by binding to the
-// LevelDBWrapper mojom interface. It represents the data stored for a
+// StorageArea mojom interface. It represents the data stored for a
// namespace-origin area.
//
// This class delegates calls to SessionStorageDataMap objects, and can share
@@ -30,42 +29,48 @@ class SessionStorageDataMap;
// cloning (copy-on-write). This should be done through the |Clone()| method and
// not manually.
//
+// Unlike regular observers, adding an observer to this class only notifies when
+// the whole area is deleted manually (not by using DeleteAll on this binding).
+// This can happen when clearing browser data.
+//
// During forking, this class is responsible for dealing with moving its
-// observers from the SessionStorageDataMap's LevelDBWrapper to the new forked
-// SessionStorageDataMap's LevelDBWrapper.
-class CONTENT_EXPORT SessionStorageLevelDBWrapper
- : public mojom::LevelDBWrapper {
+// observers from the SessionStorageDataMap's StorageArea to the new forked
+// SessionStorageDataMap's StorageArea.
+class CONTENT_EXPORT SessionStorageAreaImpl : public blink::mojom::StorageArea {
public:
using RegisterNewAreaMap =
base::RepeatingCallback<scoped_refptr<SessionStorageMetadata::MapData>(
SessionStorageMetadata::NamespaceEntry namespace_entry,
const url::Origin& origin)>;
- // Creates a wrapper for the given |namespace_entry|-|origin| data area. All
- // LevelDBWrapper calls are delegated to the |data_map|. The
+ // Creates a area for the given |namespace_entry|-|origin| data area. All
+ // StorageArea calls are delegated to the |data_map|. The
// |register_new_map_callback| is called when a shared |data_map| needs to be
// forked for the copy-on-write behavior and a new map needs to be registered.
- SessionStorageLevelDBWrapper(
- SessionStorageMetadata::NamespaceEntry namespace_entry,
- url::Origin origin,
- scoped_refptr<SessionStorageDataMap> data_map,
- RegisterNewAreaMap register_new_map_callback);
- ~SessionStorageLevelDBWrapper() override;
+ SessionStorageAreaImpl(SessionStorageMetadata::NamespaceEntry namespace_entry,
+ url::Origin origin,
+ scoped_refptr<SessionStorageDataMap> data_map,
+ RegisterNewAreaMap register_new_map_callback);
+ ~SessionStorageAreaImpl() override;
// Creates a shallow copy clone for the new namespace entry.
// This doesn't change the refcount of the underlying map - that operation
// must be done using SessionStorageMetadata::RegisterShallowClonedNamespace.
- std::unique_ptr<SessionStorageLevelDBWrapper> Clone(
+ std::unique_ptr<SessionStorageAreaImpl> Clone(
SessionStorageMetadata::NamespaceEntry namespace_entry);
- void Bind(mojom::LevelDBWrapperAssociatedRequest request);
+ void Bind(blink::mojom::StorageAreaAssociatedRequest request);
bool IsBound() const { return binding_.is_bound(); }
SessionStorageDataMap* data_map() { return shared_data_map_.get(); }
- // LevelDBWrapper:
- void AddObserver(mojom::LevelDBObserverAssociatedPtrInfo observer) override;
+ // Notifies all observers that this area was deleted.
+ void NotifyObserversAllDeleted();
+
+ // blink::mojom::StorageArea:
+ void AddObserver(
+ blink::mojom::StorageAreaObserverAssociatedPtrInfo observer) override;
void Put(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
const base::Optional<std::vector<uint8_t>>& client_old_value,
@@ -78,9 +83,9 @@ class CONTENT_EXPORT SessionStorageLevelDBWrapper
void DeleteAll(const std::string& source,
DeleteAllCallback callback) override;
void Get(const std::vector<uint8_t>& key, GetCallback callback) override;
- void GetAll(
- mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo complete_callback,
- GetAllCallback callback) override;
+ void GetAll(blink::mojom::StorageAreaGetAllCallbackAssociatedPtrInfo
+ complete_callback,
+ GetAllCallback callback) override;
private:
void OnConnectionError();
@@ -95,12 +100,12 @@ class CONTENT_EXPORT SessionStorageLevelDBWrapper
scoped_refptr<SessionStorageDataMap> shared_data_map_;
RegisterNewAreaMap register_new_map_callback_;
- std::vector<mojo::InterfacePtrSetElementId> observer_ptrs_;
- mojo::AssociatedBinding<mojom::LevelDBWrapper> binding_;
+ mojo::AssociatedInterfacePtrSet<blink::mojom::StorageAreaObserver> observers_;
+ mojo::AssociatedBinding<blink::mojom::StorageArea> binding_;
- DISALLOW_COPY_AND_ASSIGN(SessionStorageLevelDBWrapper);
+ DISALLOW_COPY_AND_ASSIGN(SessionStorageAreaImpl);
};
} // namespace content
-#endif // CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_LEVELDB_WRAPPER_H_
+#endif // CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_AREA_IMPL_H_
diff --git a/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper_unittest.cc b/chromium/content/browser/dom_storage/session_storage_area_impl_unittest.cc
index 6f768e0a050..7fdc77561d6 100644
--- a/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper_unittest.cc
+++ b/chromium/content/browser/dom_storage/session_storage_area_impl_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/dom_storage/session_storage_leveldb_wrapper.h"
+#include "content/browser/dom_storage/session_storage_area_impl.h"
#include "base/barrier_closure.h"
#include "base/bind.h"
@@ -21,10 +21,10 @@
#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
#include "content/browser/dom_storage/session_storage_data_map.h"
#include "content/browser/dom_storage/session_storage_metadata.h"
+#include "content/browser/dom_storage/test/storage_area_test_util.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/fake_leveldb_database.h"
#include "content/test/gmock_util.h"
-#include "content/test/leveldb_wrapper_test_util.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/bindings/strong_binding_set.h"
@@ -61,9 +61,9 @@ class MockListener : public SessionStorageDataMap::Listener {
MOCK_METHOD1(OnCommitResult, void(DatabaseError error));
};
-class SessionStorageLevelDBWrapperTest : public testing::Test {
+class SessionStorageAreaImplTest : public testing::Test {
public:
- SessionStorageLevelDBWrapperTest()
+ SessionStorageAreaImplTest()
: test_namespace_id1_(base::GenerateGUID()),
test_namespace_id2_(base::GenerateGUID()),
test_origin1_(url::Origin::Create(GURL("https://host1.com:1/"))),
@@ -75,7 +75,7 @@ class SessionStorageLevelDBWrapperTest : public testing::Test {
std::make_unique<leveldb::LevelDBServiceImpl>(std::move(file_runner)));
leveldb_service_->OpenInMemory(
- base::nullopt, "SessionStorageLevelDBWrapperTestDatabase",
+ base::nullopt, "SessionStorageAreaImplTestDatabase",
mojo::MakeRequest(&leveldb_database_), base::DoNothing());
leveldb_database_->Put(StdStringToUint8Vector("map-0-key1"),
@@ -89,7 +89,7 @@ class SessionStorageLevelDBWrapperTest : public testing::Test {
DCHECK(map_id->KeyPrefix() == StdStringToUint8Vector("map-0-"));
leveldb_database_->Write(std::move(save_operations), base::DoNothing());
}
- ~SessionStorageLevelDBWrapperTest() override = default;
+ ~SessionStorageAreaImplTest() override = default;
scoped_refptr<SessionStorageMetadata::MapData> RegisterNewAreaMap(
SessionStorageMetadata::NamespaceEntry namespace_entry,
@@ -101,11 +101,9 @@ class SessionStorageLevelDBWrapperTest : public testing::Test {
return map_data;
}
- SessionStorageLevelDBWrapper::RegisterNewAreaMap
- GetRegisterNewAreaMapCallback() {
- return base::BindRepeating(
- &SessionStorageLevelDBWrapperTest::RegisterNewAreaMap,
- base::Unretained(this));
+ SessionStorageAreaImpl::RegisterNewAreaMap GetRegisterNewAreaMapCallback() {
+ return base::BindRepeating(&SessionStorageAreaImplTest::RegisterNewAreaMap,
+ base::Unretained(this));
}
protected:
@@ -122,12 +120,12 @@ class SessionStorageLevelDBWrapperTest : public testing::Test {
};
} // namespace
-TEST_F(SessionStorageLevelDBWrapperTest, BasicUsage) {
+TEST_F(SessionStorageAreaImplTest, BasicUsage) {
EXPECT_CALL(listener_,
OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
.Times(1);
- auto ss_leveldb_impl = std::make_unique<SessionStorageLevelDBWrapper>(
+ auto ss_leveldb_impl = std::make_unique<SessionStorageAreaImpl>(
metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_,
SessionStorageDataMap::Create(
&listener_,
@@ -136,28 +134,61 @@ TEST_F(SessionStorageLevelDBWrapperTest, BasicUsage) {
leveldb_database_.get()),
GetRegisterNewAreaMapCallback());
- mojom::LevelDBWrapperAssociatedPtr ss_leveldb;
+ blink::mojom::StorageAreaAssociatedPtr ss_leveldb;
ss_leveldb_impl->Bind(
mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb));
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(ss_leveldb.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(ss_leveldb.get(), &data));
ASSERT_EQ(1ul, data.size());
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
- StdStringToUint8Vector("data1"))));
+ data, blink::mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
.Times(1);
}
-TEST_F(SessionStorageLevelDBWrapperTest, Cloning) {
+TEST_F(SessionStorageAreaImplTest, DoubleBind) {
EXPECT_CALL(listener_,
OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
.Times(1);
- auto ss_leveldb_impl1 = std::make_unique<SessionStorageLevelDBWrapper>(
+ auto ss_leveldb_impl = std::make_unique<SessionStorageAreaImpl>(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_,
+ SessionStorageDataMap::Create(
+ &listener_,
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)
+ ->second[test_origin1_],
+ leveldb_database_.get()),
+ GetRegisterNewAreaMapCallback());
+
+ blink::mojom::StorageAreaAssociatedPtr ss_leveldb1;
+ base::RunLoop loop;
+ ss_leveldb_impl->Bind(
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb1));
+ ss_leveldb1.set_connection_error_handler(loop.QuitClosure());
+ // Check that we can bind twice and get data from the second binding.
+ blink::mojom::StorageAreaAssociatedPtr ss_leveldb2;
+ ss_leveldb_impl->Bind(
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb2));
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(ss_leveldb2.get(), &data));
+ ASSERT_EQ(1ul, data.size());
+
+ // Make sure the first binding was closed.
+ loop.Run();
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+}
+
+TEST_F(SessionStorageAreaImplTest, Cloning) {
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ auto ss_leveldb_impl1 = std::make_unique<SessionStorageAreaImpl>(
metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_,
SessionStorageDataMap::Create(
&listener_,
@@ -176,10 +207,10 @@ TEST_F(SessionStorageLevelDBWrapperTest, Cloning) {
auto ss_leveldb_impl2 = ss_leveldb_impl1->Clone(
metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_));
- mojom::LevelDBWrapperAssociatedPtr ss_leveldb1;
+ blink::mojom::StorageAreaAssociatedPtr ss_leveldb1;
ss_leveldb_impl1->Bind(
mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb1));
- mojom::LevelDBWrapperAssociatedPtr ss_leveldb2;
+ blink::mojom::StorageAreaAssociatedPtr ss_leveldb2;
ss_leveldb_impl2->Bind(
mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb2));
@@ -200,25 +231,23 @@ TEST_F(SessionStorageLevelDBWrapperTest, Cloning) {
EXPECT_NE(ss_leveldb_impl1->data_map(), ss_leveldb_impl2->data_map());
// Check map 1 data.
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(ss_leveldb1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(ss_leveldb1.get(), &data));
ASSERT_EQ(1ul, data.size());
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
- StdStringToUint8Vector("data1"))));
+ data, blink::mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
// Check map 2 data.
data.clear();
- status = test::GetAllSync(ss_leveldb2.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_TRUE(test::GetAllSync(ss_leveldb2.get(), &data));
ASSERT_EQ(2ul, data.size());
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
- StdStringToUint8Vector("data1"))));
+ data, blink::mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(StdStringToUint8Vector("key2"),
- StdStringToUint8Vector("data2"))));
+ data, blink::mojom::KeyValue::New(StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"))));
EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
.Times(1);
@@ -229,12 +258,12 @@ TEST_F(SessionStorageLevelDBWrapperTest, Cloning) {
ss_leveldb_impl2 = nullptr;
}
-TEST_F(SessionStorageLevelDBWrapperTest, ObserverTransfer) {
+TEST_F(SessionStorageAreaImplTest, NotifyAllDeleted) {
EXPECT_CALL(listener_,
OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
.Times(1);
- auto ss_leveldb_impl1 = std::make_unique<SessionStorageLevelDBWrapper>(
+ auto ss_leveldb_impl1 = std::make_unique<SessionStorageAreaImpl>(
metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_,
SessionStorageDataMap::Create(
&listener_,
@@ -243,77 +272,34 @@ TEST_F(SessionStorageLevelDBWrapperTest, ObserverTransfer) {
leveldb_database_.get()),
GetRegisterNewAreaMapCallback());
- // Create the mojo binding.
- mojom::LevelDBWrapperAssociatedPtr ss_leveldb1;
+ blink::mojom::StorageAreaAssociatedPtr ss_leveldb1;
ss_leveldb_impl1->Bind(
mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb1));
- // Create the observer, and attach it to the mojo bound implementation.
testing::StrictMock<test::MockLevelDBObserver> mock_observer;
- mojo::AssociatedBinding<mojom::LevelDBObserver> observer_binding(
+ mojo::AssociatedBinding<blink::mojom::StorageAreaObserver> observer_binding(
&mock_observer);
- mojom::LevelDBObserverAssociatedPtrInfo observer_ptr_info;
+ blink::mojom::StorageAreaObserverAssociatedPtrInfo observer_ptr_info;
observer_binding.Bind(mojo::MakeRequest(&observer_ptr_info));
ss_leveldb1->AddObserver(std::move(observer_ptr_info));
+ ss_leveldb1.FlushForTesting();
- // Perform a shallow clone.
- std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
- metadata_.RegisterShallowClonedNamespace(
- metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
- metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_),
- &save_operations);
- leveldb_database_->Write(std::move(save_operations), base::DoNothing());
- auto ss_leveldb_impl2 = ss_leveldb_impl1->Clone(
- metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_));
- mojom::LevelDBWrapperAssociatedPtr ss_leveldb2;
- ss_leveldb_impl2->Bind(
- mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb2));
-
- // Wait for our future commits to finish.
- base::RunLoop commit_waiters;
- auto barrier = base::BarrierClosure(3, commit_waiters.QuitClosure());
- EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK))
- .Times(3)
- .WillRepeatedly(base::test::RunClosure(barrier));
-
- // Do a change on the new interface. There should be no observation.
- EXPECT_CALL(listener_,
- OnDataMapCreation(StdStringToUint8Vector("1"), testing::_))
- .Times(1);
- EXPECT_TRUE(test::PutSync(ss_leveldb2.get(), StdStringToUint8Vector("key2"),
- StdStringToUint8Vector("data2"), base::nullopt,
- ""));
- ss_leveldb_impl2->data_map()->level_db_wrapper()->ScheduleImmediateCommit();
-
- // Do a change on the old interface.
- EXPECT_CALL(mock_observer,
- KeyChanged(StdStringToUint8Vector("key1"),
- StdStringToUint8Vector("data2"),
- StdStringToUint8Vector("data1"), "ss_leveldb1"))
- .Times(1);
- EXPECT_TRUE(test::PutSync(ss_leveldb1.get(), StdStringToUint8Vector("key1"),
- StdStringToUint8Vector("data2"),
- StdStringToUint8Vector("data1"), "ss_leveldb1"));
- ss_leveldb_impl1->data_map()->level_db_wrapper()->ScheduleImmediateCommit();
-
- // Wait for the commits.
- commit_waiters.Run();
+ base::RunLoop loop;
+ EXPECT_CALL(mock_observer, AllDeleted("\n"))
+ .WillOnce(base::test::RunClosure(loop.QuitClosure()));
+ ss_leveldb_impl1->NotifyObserversAllDeleted();
+ loop.Run();
EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
.Times(1);
- EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("1")))
- .Times(1);
-
- ss_leveldb_impl1 = nullptr;
- ss_leveldb_impl2 = nullptr;
}
-TEST_F(SessionStorageLevelDBWrapperTest, DeleteAllOnShared) {
+TEST_F(SessionStorageAreaImplTest, DeleteAllOnShared) {
EXPECT_CALL(listener_,
OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
.Times(1);
- auto ss_leveldb_impl1 = std::make_unique<SessionStorageLevelDBWrapper>(
+ auto ss_leveldb_impl1 = std::make_unique<SessionStorageAreaImpl>(
metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_,
SessionStorageDataMap::Create(
&listener_,
@@ -332,21 +318,23 @@ TEST_F(SessionStorageLevelDBWrapperTest, DeleteAllOnShared) {
auto ss_leveldb_impl2 = ss_leveldb_impl1->Clone(
metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_));
- mojom::LevelDBWrapperAssociatedPtr ss_leveldb1;
+ blink::mojom::StorageAreaAssociatedPtr ss_leveldb1;
ss_leveldb_impl1->Bind(
mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb1));
- mojom::LevelDBWrapperAssociatedPtr ss_leveldb2;
+ blink::mojom::StorageAreaAssociatedPtr ss_leveldb2;
ss_leveldb_impl2->Bind(
mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb2));
// Same maps are used.
EXPECT_EQ(ss_leveldb_impl1->data_map(), ss_leveldb_impl2->data_map());
- // Create the observer, attach to the first namespace.
+ // Create the observer, attach to the first namespace, and verify we don't see
+ // any changes (see SessionStorageAreaImpl class comment about when observers
+ // are called).
testing::StrictMock<test::MockLevelDBObserver> mock_observer;
- mojo::AssociatedBinding<mojom::LevelDBObserver> observer_binding(
+ mojo::AssociatedBinding<blink::mojom::StorageAreaObserver> observer_binding(
&mock_observer);
- mojom::LevelDBObserverAssociatedPtrInfo observer_ptr_info;
+ blink::mojom::StorageAreaObserverAssociatedPtrInfo observer_ptr_info;
observer_binding.Bind(mojo::MakeRequest(&observer_ptr_info));
ss_leveldb1->AddObserver(std::move(observer_ptr_info));
@@ -358,7 +346,6 @@ TEST_F(SessionStorageLevelDBWrapperTest, DeleteAllOnShared) {
// There should be no commits, as we don't actually have to change any data.
// |ss_leveldb_impl1| should just switch to a new, empty map.
EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK)).Times(0);
- EXPECT_CALL(mock_observer, AllDeleted("source")).Times(1);
EXPECT_TRUE(test::DeleteAllSync(ss_leveldb1.get(), "source"));
// The maps were forked on the above call.
@@ -373,4 +360,31 @@ TEST_F(SessionStorageLevelDBWrapperTest, DeleteAllOnShared) {
ss_leveldb_impl2 = nullptr;
}
+TEST_F(SessionStorageAreaImplTest, DeleteAllWithoutBinding) {
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ auto ss_leveldb_impl1 = std::make_unique<SessionStorageAreaImpl>(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_,
+ SessionStorageDataMap::Create(
+ &listener_,
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)
+ ->second[test_origin1_],
+ leveldb_database_.get()),
+ GetRegisterNewAreaMapCallback());
+
+ base::RunLoop loop;
+ EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK))
+ .WillOnce(base::test::RunClosure(loop.QuitClosure()));
+ EXPECT_TRUE(test::DeleteAllSync(ss_leveldb_impl1.get(), "source"));
+ ss_leveldb_impl1->data_map()->storage_area()->ScheduleImmediateCommit();
+ loop.Run();
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+
+ ss_leveldb_impl1 = nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_context_mojo.cc b/chromium/content/browser/dom_storage/session_storage_context_mojo.cc
index 0f4bf4aed6c..a3998a49115 100644
--- a/chromium/content/browser/dom_storage/session_storage_context_mojo.cc
+++ b/chromium/content/browser/dom_storage/session_storage_context_mojo.cc
@@ -22,9 +22,9 @@
#include "build/build_config.h"
#include "components/services/leveldb/public/cpp/util.h"
#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
-#include "content/browser/dom_storage/session_storage_leveldb_wrapper.h"
+#include "content/browser/dom_storage/session_storage_area_impl.h"
#include "content/browser/dom_storage/session_storage_namespace_impl_mojo.h"
-#include "content/browser/leveldb_wrapper_impl.h"
+#include "content/browser/dom_storage/storage_area_impl.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/session_storage_usage_info.h"
#include "content/public/common/content_features.h"
@@ -94,9 +94,11 @@ void RecordSessionStorageCachePurgedHistogram(
SessionStorageContextMojo::SessionStorageContextMojo(
scoped_refptr<base::SequencedTaskRunner> memory_dump_task_runner,
service_manager::Connector* connector,
- base::Optional<base::FilePath> local_partition_directory,
+ BackingMode backing_mode,
+ base::FilePath local_partition_directory,
std::string leveldb_name)
: connector_(connector ? connector->Clone() : nullptr),
+ backing_mode_(backing_mode),
partition_directory_path_(std::move(local_partition_directory)),
leveldb_name_(std::move(leveldb_name)),
memory_dump_id_(base::StringPrintf("SessionStorage/0x%" PRIXPTR,
@@ -119,7 +121,7 @@ SessionStorageContextMojo::~SessionStorageContextMojo() {
void SessionStorageContextMojo::OpenSessionStorage(
int process_id,
const std::string& namespace_id,
- mojom::SessionStorageNamespaceRequest request) {
+ blink::mojom::SessionStorageNamespaceRequest request) {
if (connection_state_ != CONNECTION_FINISHED) {
RunWhenConnected(
base::BindOnce(&SessionStorageContextMojo::OpenSessionStorage,
@@ -128,7 +130,10 @@ void SessionStorageContextMojo::OpenSessionStorage(
return;
}
auto found = namespaces_.find(namespace_id);
- DCHECK(found != namespaces_.end()) << namespace_id;
+ if (found == namespaces_.end()) {
+ mojo::ReportBadMessage("Namespace not found: " + namespace_id);
+ return;
+ }
if (!found->second->IsPopulated() &&
!found->second->waiting_on_clone_population()) {
@@ -137,11 +142,11 @@ void SessionStorageContextMojo::OpenSessionStorage(
data_maps_);
}
- PurgeUnusedWrappersIfNeeded();
+ PurgeUnusedAreasIfNeeded();
found->second->Bind(std::move(request), process_id);
- size_t total_cache_size, unused_wrapper_count;
- GetStatistics(&total_cache_size, &unused_wrapper_count);
+ size_t total_cache_size, unused_area_count;
+ GetStatistics(&total_cache_size, &unused_area_count);
// Track the total sessionStorage cache size.
UMA_HISTOGRAM_COUNTS_100000("SessionStorageContext.CacheSizeInKB",
total_cache_size / 1024);
@@ -158,15 +163,42 @@ void SessionStorageContextMojo::CreateSessionNamespace(
void SessionStorageContextMojo::CloneSessionNamespace(
const std::string& namespace_id_to_clone,
- const std::string& clone_namespace_id) {
- if (namespaces_.find(clone_namespace_id) != namespaces_.end())
+ const std::string& clone_namespace_id,
+ CloneType clone_type) {
+ if (namespaces_.find(clone_namespace_id) != namespaces_.end()) {
+ // Non-immediate commits expect to be paired with a |Clone| from the mojo
+ // namespace object. If that clone has already happened, then we don't need
+ // to do anything here.
+ // However, immediate commits happen without a |Clone| from the mojo
+ // namespace object, so there should never be a namespace already populated
+ // for an immediate clone.
+ DCHECK_NE(clone_type, CloneType::kImmediate);
return;
+ }
std::unique_ptr<SessionStorageNamespaceImplMojo> namespace_impl =
CreateSessionStorageNamespaceImplMojo(clone_namespace_id);
- namespace_impl->SetWaitingForClonePopulation();
- namespaces_.emplace(
- std::make_pair(clone_namespace_id, std::move(namespace_impl)));
+ switch (clone_type) {
+ case CloneType::kImmediate: {
+ auto clone_from_ns = namespaces_.find(namespace_id_to_clone);
+ // If the namespace doesn't exist or it's not populated yet, just create
+ // an empty session storage.
+ if (clone_from_ns == namespaces_.end() ||
+ !clone_from_ns->second->IsPopulated()) {
+ break;
+ }
+ clone_from_ns->second->Clone(clone_namespace_id);
+ return;
+ }
+ case CloneType::kWaitForCloneOnNamespace:
+ namespace_impl->SetWaitingForClonePopulation();
+ break;
+ default:
+ NOTREACHED();
+ }
+ namespaces_.emplace(std::piecewise_construct,
+ std::forward_as_tuple(clone_namespace_id),
+ std::forward_as_tuple(std::move(namespace_impl)));
}
void SessionStorageContextMojo::DeleteSessionNamespace(
@@ -193,7 +225,7 @@ void SessionStorageContextMojo::Flush() {
return;
}
for (const auto& it : data_maps_)
- it.second->level_db_wrapper()->ScheduleImmediateCommit();
+ it.second->storage_area()->ScheduleImmediateCommit();
}
void SessionStorageContextMojo::GetStorageUsage(
@@ -229,7 +261,9 @@ void SessionStorageContextMojo::DeleteStorage(const url::Origin& origin,
return;
}
auto found = namespaces_.find(namespace_id);
- if (found != namespaces_.end()) {
+ if (found != namespaces_.end() &&
+ (found->second->IsPopulated() ||
+ found->second->waiting_on_clone_population())) {
found->second->RemoveOriginData(origin);
} else {
// If we don't have the namespace loaded, then we can delete it all
@@ -255,47 +289,47 @@ void SessionStorageContextMojo::ShutdownAndDelete() {
// Flush any uncommitted data.
for (const auto& it : data_maps_) {
- auto* wrapper = it.second->level_db_wrapper();
+ auto* area = it.second->storage_area();
LOCAL_HISTOGRAM_BOOLEAN(
"SessionStorageContext.ShutdownAndDelete.MaybeDroppedChanges",
- wrapper->has_pending_load_tasks());
- wrapper->ScheduleImmediateCommit();
+ area->has_pending_load_tasks());
+ area->ScheduleImmediateCommit();
// TODO(dmurph): Monitor the above histogram, and if dropping changes is
// common then handle that here.
- wrapper->CancelAllPendingRequests();
+ area->CancelAllPendingRequests();
}
OnShutdownComplete(leveldb::mojom::DatabaseError::OK);
}
void SessionStorageContextMojo::PurgeMemory() {
- size_t total_cache_size, unused_wrapper_count;
- GetStatistics(&total_cache_size, &unused_wrapper_count);
+ size_t total_cache_size, unused_area_count;
+ GetStatistics(&total_cache_size, &unused_area_count);
- // Purge all wrappers that don't have bindings.
- for (auto it = namespaces_.begin(); it != namespaces_.end();) {
- if (!it->second->IsBound()) {
- it = namespaces_.erase(it);
- continue;
- }
- it->second->PurgeUnboundWrappers();
+ // Purge all areas that don't have bindings.
+ for (const auto& namespace_pair : namespaces_) {
+ namespace_pair.second->PurgeUnboundAreas();
+ }
+ // Purge memory from bound maps.
+ for (const auto& data_map_pair : data_maps_) {
+ data_map_pair.second->storage_area()->PurgeMemory();
}
// Track the size of cache purged.
size_t final_total_cache_size;
- GetStatistics(&final_total_cache_size, &unused_wrapper_count);
+ GetStatistics(&final_total_cache_size, &unused_area_count);
size_t purged_size_kib = (total_cache_size - final_total_cache_size) / 1024;
RecordSessionStorageCachePurgedHistogram(
SessionStorageCachePurgeReason::kAggressivePurgeTriggered,
purged_size_kib);
}
-void SessionStorageContextMojo::PurgeUnusedWrappersIfNeeded() {
- size_t total_cache_size, unused_wrapper_count;
- GetStatistics(&total_cache_size, &unused_wrapper_count);
+void SessionStorageContextMojo::PurgeUnusedAreasIfNeeded() {
+ size_t total_cache_size, unused_area_count;
+ GetStatistics(&total_cache_size, &unused_area_count);
// Nothing to purge.
- if (!unused_wrapper_count)
+ if (!unused_area_count)
return;
SessionStorageCachePurgeReason purge_reason =
@@ -311,18 +345,15 @@ void SessionStorageContextMojo::PurgeUnusedWrappersIfNeeded() {
if (purge_reason == SessionStorageCachePurgeReason::kNotNeeded)
return;
- // Purge all wrappers that don't have bindings.
- for (auto it = namespaces_.begin(); it != namespaces_.end();) {
- if (!it->second->IsBound())
- it = namespaces_.erase(it);
+ // Purge all areas that don't have bindings.
+ for (const auto& namespace_pair : namespaces_) {
+ namespace_pair.second->PurgeUnboundAreas();
}
size_t final_total_cache_size;
- GetStatistics(&final_total_cache_size, &unused_wrapper_count);
+ GetStatistics(&final_total_cache_size, &unused_area_count);
size_t purged_size_kib = (total_cache_size - final_total_cache_size) / 1024;
- RecordSessionStorageCachePurgedHistogram(
- SessionStorageCachePurgeReason::kAggressivePurgeTriggered,
- purged_size_kib);
+ RecordSessionStorageCachePurgedHistogram(purge_reason, purged_size_kib);
}
void SessionStorageContextMojo::ScavengeUnusedNamespaces(
@@ -381,8 +412,8 @@ bool SessionStorageContextMojo::OnMemoryDump(
if (args.level_of_detail ==
base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
- size_t total_cache_size, unused_wrapper_count;
- GetStatistics(&total_cache_size, &unused_wrapper_count);
+ size_t total_cache_size, unused_area_count;
+ GetStatistics(&total_cache_size, &unused_area_count);
auto* mad = pmd->CreateAllocatorDump(context_name + "/cache_size");
mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
@@ -400,10 +431,10 @@ bool SessionStorageContextMojo::OnMemoryDump(
if (!std::isalnum(url[index]))
url[index] = '_';
}
- std::string wrapper_dump_name = base::StringPrintf(
+ std::string area_dump_name = base::StringPrintf(
"%s/%s/0x%" PRIXPTR, context_name.c_str(), url.c_str(),
- reinterpret_cast<uintptr_t>(it.second->level_db_wrapper()));
- it.second->level_db_wrapper()->OnMemoryDump(wrapper_dump_name, pmd);
+ reinterpret_cast<uintptr_t>(it.second->storage_area()));
+ it.second->storage_area()->OnMemoryDump(area_dump_name, pmd);
}
return true;
}
@@ -442,8 +473,8 @@ void SessionStorageContextMojo::OnCommitResult(
}
tried_to_recover_from_commit_errors_ = true;
- // Deleting LevelDBWrappers in here could cause more commits (and commit
- // errors), but those commits won't reach OnCommitResult because the wrapper
+ // Deleting StorageAreas in here could cause more commits (and commit
+ // errors), but those commits won't reach OnCommitResult because the area
// will have been deleted before the commit finishes.
DeleteAndRecreateDatabase(
"SessionStorageContext.OpenResultAfterCommitErrors");
@@ -488,6 +519,17 @@ void SessionStorageContextMojo::RegisterShallowClonedNamespace(
const std::string& new_namespace_id,
const SessionStorageNamespaceImplMojo::OriginAreas& clone_from_areas) {
std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
+
+ bool found = false;
+ auto it = namespaces_.find(new_namespace_id);
+ if (it != namespaces_.end()) {
+ found = true;
+ if (it->second->IsPopulated()) {
+ mojo::ReportBadMessage("Cannot clone to already populated namespace");
+ return;
+ }
+ }
+
SessionStorageMetadata::NamespaceEntry namespace_entry =
metadata_.GetOrCreateNamespaceEntry(new_namespace_id);
metadata_.RegisterShallowClonedNamespace(source_namespace_entry,
@@ -496,8 +538,7 @@ void SessionStorageContextMojo::RegisterShallowClonedNamespace(
base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
base::Unretained(this)));
- auto it = namespaces_.find(new_namespace_id);
- if (it != namespaces_.end()) {
+ if (found) {
it->second->PopulateAsClone(database_.get(), namespace_entry,
clone_from_areas);
return;
@@ -506,8 +547,9 @@ void SessionStorageContextMojo::RegisterShallowClonedNamespace(
auto namespace_impl = CreateSessionStorageNamespaceImplMojo(new_namespace_id);
namespace_impl->PopulateAsClone(database_.get(), namespace_entry,
clone_from_areas);
- namespaces_.emplace(
- std::make_pair(new_namespace_id, std::move(namespace_impl)));
+ namespaces_.emplace(std::piecewise_construct,
+ std::forward_as_tuple(new_namespace_id),
+ std::forward_as_tuple(std::move(namespace_impl)));
}
std::unique_ptr<SessionStorageNamespaceImplMojo>
@@ -517,7 +559,7 @@ SessionStorageContextMojo::CreateSessionStorageNamespaceImplMojo(
add_namespace_callback = base::BindRepeating(
&SessionStorageContextMojo::RegisterShallowClonedNamespace,
base::Unretained(this));
- SessionStorageLevelDBWrapper::RegisterNewAreaMap map_id_callback =
+ SessionStorageAreaImpl::RegisterNewAreaMap map_id_callback =
base::BindRepeating(&SessionStorageContextMojo::RegisterNewAreaMap,
base::Unretained(this));
@@ -537,21 +579,25 @@ void SessionStorageContextMojo::DoDatabaseDelete(
}
void SessionStorageContextMojo::RunWhenConnected(base::OnceClosure callback) {
- DCHECK_NE(connection_state_, CONNECTION_SHUTDOWN);
-
- // If we don't have a filesystem_connection_, we'll need to establish one.
- if (connection_state_ == NO_CONNECTION) {
- connection_state_ = CONNECTION_IN_PROGRESS;
- InitiateConnection();
- }
-
- if (connection_state_ == CONNECTION_IN_PROGRESS) {
- // Queue this OpenSessionStorage call for when we have a level db pointer.
- on_database_opened_callbacks_.push_back(std::move(callback));
- return;
+ switch (connection_state_) {
+ case NO_CONNECTION:
+ // If we don't have a filesystem_connection_, we'll need to establish one.
+ connection_state_ = CONNECTION_IN_PROGRESS;
+ on_database_opened_callbacks_.push_back(std::move(callback));
+ InitiateConnection();
+ return;
+ case CONNECTION_IN_PROGRESS:
+ // Queue this OpenSessionStorage call for when we have a level db pointer.
+ on_database_opened_callbacks_.push_back(std::move(callback));
+ return;
+ case CONNECTION_SHUTDOWN:
+ NOTREACHED();
+ return;
+ case CONNECTION_FINISHED:
+ std::move(callback).Run();
+ return;
}
-
- std::move(callback).Run();
+ NOTREACHED();
}
void SessionStorageContextMojo::InitiateConnection(bool in_memory_only) {
@@ -563,12 +609,12 @@ void SessionStorageContextMojo::InitiateConnection(bool in_memory_only) {
return;
}
- if (partition_directory_path_ && !in_memory_only) {
+ if (backing_mode_ != BackingMode::kNoDisk && !in_memory_only) {
// We were given a subdirectory to write to. Get it and use a disk backed
// database.
connector_->BindInterface(file::mojom::kServiceName, &file_system_);
file_system_->GetSubDirectory(
- partition_directory_path_.value().AsUTF8Unsafe(),
+ partition_directory_path_.AsUTF8Unsafe(),
MakeRequest(&partition_directory_),
base::BindOnce(&SessionStorageContextMojo::OnDirectoryOpened,
weak_ptr_factory_.GetWeakPtr()));
@@ -585,7 +631,7 @@ void SessionStorageContextMojo::InitiateConnection(bool in_memory_only) {
void SessionStorageContextMojo::OnDirectoryOpened(base::File::Error err) {
if (err != base::File::FILE_OK) {
// We failed to open the directory; continue with startup so that we create
- // the |level_db_wrappers_|.
+ // the data maps.
UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.DirectoryOpenError", -err,
-base::File::FILE_ERROR_MAX);
LogDatabaseOpenResult(OpenResult::kDirectoryOpenFailed);
@@ -601,6 +647,14 @@ void SessionStorageContextMojo::OnDirectoryOpened(base::File::Error err) {
filesystem::mojom::DirectoryPtr partition_directory_clone;
partition_directory_->Clone(MakeRequest(&partition_directory_clone));
+ if (backing_mode_ == BackingMode::kClearDiskStateOnOpen) {
+ filesystem::mojom::DirectoryPtr partition_directory_clone_for_deletion;
+ partition_directory_->Clone(
+ MakeRequest(&partition_directory_clone_for_deletion));
+ leveldb_service_->Destroy(std::move(partition_directory_clone_for_deletion),
+ leveldb_name_, base::DoNothing());
+ }
+
leveldb_env::Options options;
options.create_if_missing = true;
options.max_open_files = 0; // use minimum
@@ -679,7 +733,6 @@ void SessionStorageContextMojo::OnGotDatabaseVersion(
"SessionStorageContext.OpenResultAfterReadVersionError");
return;
}
- connection_state_ = FETCHING_METADATA;
base::RepeatingClosure barrier = base::BarrierClosure(
2, base::BindOnce(&SessionStorageContextMojo::OnConnectionFinished,
@@ -706,7 +759,7 @@ void SessionStorageContextMojo::OnGotNamespaces(
std::vector<leveldb::mojom::BatchedOperationPtr> migration_operations,
leveldb::mojom::DatabaseError status,
std::vector<leveldb::mojom::KeyValuePtr> values) {
- DCHECK(connection_state_ == FETCHING_METADATA);
+ DCHECK_EQ(connection_state_, CONNECTION_IN_PROGRESS);
bool parsing_failure =
status == leveldb::mojom::DatabaseError::OK &&
!metadata_.ParseNamespaces(std::move(values), &migration_operations);
@@ -733,7 +786,7 @@ void SessionStorageContextMojo::OnGotNextMapId(
base::OnceClosure done,
leveldb::mojom::DatabaseError status,
const std::vector<uint8_t>& map_id) {
- DCHECK(connection_state_ == FETCHING_METADATA);
+ DCHECK_EQ(connection_state_, CONNECTION_IN_PROGRESS);
if (status == leveldb::mojom::DatabaseError::NOT_FOUND) {
std::move(done).Run();
return;
@@ -754,7 +807,7 @@ void SessionStorageContextMojo::OnGotNextMapId(
}
void SessionStorageContextMojo::OnConnectionFinished() {
- DCHECK(!database_ || connection_state_ == FETCHING_METADATA);
+ DCHECK(!database_ || connection_state_ == CONNECTION_IN_PROGRESS);
if (!database_) {
partition_directory_.reset();
file_system_.reset();
@@ -779,10 +832,10 @@ void SessionStorageContextMojo::OnConnectionFinished() {
void SessionStorageContextMojo::DeleteAndRecreateDatabase(
const char* histogram_name) {
- // We're about to set database_ to null, so delete the LevelDBWrappers
+ // We're about to set database_ to null, so delete the StorageAreas
// that might still be using the old database.
for (const auto& it : data_maps_)
- it.second->level_db_wrapper()->CancelAllPendingRequests();
+ it.second->storage_area()->CancelAllPendingRequests();
for (const auto& namespace_pair : namespaces_) {
namespace_pair.second->Reset();
@@ -790,7 +843,7 @@ void SessionStorageContextMojo::DeleteAndRecreateDatabase(
DCHECK(data_maps_.empty());
// Reset state to be in process of connecting. This will cause requests for
- // LevelDBWrappers to be queued until the connection is complete.
+ // StorageAreas to be queued until the connection is complete.
connection_state_ = CONNECTION_IN_PROGRESS;
commit_error_count_ = 0;
database_ = nullptr;
@@ -800,7 +853,7 @@ void SessionStorageContextMojo::DeleteAndRecreateDatabase(
// If tried to recreate database on disk already, try again but this time
// in memory.
- if (tried_to_recreate_during_open_ && !!partition_directory_path_) {
+ if (tried_to_recreate_during_open_ && backing_mode_ != BackingMode::kNoDisk) {
recreate_in_memory = true;
} else if (tried_to_recreate_during_open_) {
// Give up completely, run without any database.
@@ -849,13 +902,13 @@ void SessionStorageContextMojo::OnShutdownComplete(
}
void SessionStorageContextMojo::GetStatistics(size_t* total_cache_size,
- size_t* unused_wrapper_count) {
+ size_t* unused_area_count) {
*total_cache_size = 0;
- *unused_wrapper_count = 0;
+ *unused_area_count = 0;
for (const auto& it : data_maps_) {
- *total_cache_size += it.second->level_db_wrapper()->memory_used();
+ *total_cache_size += it.second->storage_area()->memory_used();
if (it.second->binding_count() == 0)
- (*unused_wrapper_count)++;
+ (*unused_area_count)++;
}
}
diff --git a/chromium/content/browser/dom_storage/session_storage_context_mojo.h b/chromium/content/browser/dom_storage/session_storage_context_mojo.h
index 6361d3a2bfd..9a4c3aa3d20 100644
--- a/chromium/content/browser/dom_storage/session_storage_context_mojo.h
+++ b/chromium/content/browser/dom_storage/session_storage_context_mojo.h
@@ -13,6 +13,7 @@
#include "base/callback_forward.h"
#include "base/files/file_path.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
@@ -21,10 +22,9 @@
#include "content/browser/dom_storage/session_storage_metadata.h"
#include "content/browser/dom_storage/session_storage_namespace_impl_mojo.h"
#include "content/common/content_export.h"
-#include "content/common/leveldb_wrapper.mojom.h"
-#include "content/common/storage_partition_service.mojom.h"
#include "content/public/browser/session_storage_usage_info.h"
#include "services/file/public/mojom/file_system.mojom.h"
+#include "third_party/blink/public/mojom/dom_storage/session_storage_namespace.mojom.h"
#include "url/origin.h"
namespace base {
@@ -50,19 +50,44 @@ class CONTENT_EXPORT SessionStorageContextMojo
using GetStorageUsageCallback =
base::OnceCallback<void(std::vector<SessionStorageUsageInfo>)>;
+ enum class CloneType {
+ // Expect a clone to come from the SessionStorageNamespace mojo object. This
+ // guarantees ordering with any writes from that namespace.
+ kWaitForCloneOnNamespace,
+ // There will not be a clone coming from the SessionStorageNamespace mojo
+ // object, so clone immediately.
+ kImmediate
+ };
+
+ enum class BackingMode {
+ // Use an in-memory leveldb database to store our state.
+ kNoDisk,
+ // Use disk for the leveldb database, but clear its contents before we open
+ // it. This is used for platforms like Android where the session restore
+ // code is never used, ScavengeUnusedNamespace is never called, and old
+ // session storage data will never be reused.
+ kClearDiskStateOnOpen,
+ // Use disk for the leveldb database, restore all saved namespaces from
+ // disk. This assumes that ScavengeUnusedNamespace will eventually be called
+ // to clean up unused namespaces on disk.
+ kRestoreDiskState
+ };
+
SessionStorageContextMojo(
scoped_refptr<base::SequencedTaskRunner> task_runner,
service_manager::Connector* connector,
- base::Optional<base::FilePath> local_partition_directory,
+ BackingMode backing_option,
+ base::FilePath local_partition_directory,
std::string leveldb_name);
void OpenSessionStorage(int process_id,
const std::string& namespace_id,
- mojom::SessionStorageNamespaceRequest request);
+ blink::mojom::SessionStorageNamespaceRequest request);
void CreateSessionNamespace(const std::string& namespace_id);
void CloneSessionNamespace(const std::string& namespace_id_to_clone,
- const std::string& clone_namespace_id);
+ const std::string& clone_namespace_id,
+ CloneType clone_type);
void DeleteSessionNamespace(const std::string& namespace_id,
bool should_persist);
@@ -84,8 +109,8 @@ class CONTENT_EXPORT SessionStorageContextMojo
// storage for a particular origin will reload the data from the database.
void PurgeMemory();
- // Clears unused leveldb wrappers, when thresholds are reached.
- void PurgeUnusedWrappersIfNeeded();
+ // Clears unused storage areas, when thresholds are reached.
+ void PurgeUnusedAreasIfNeeded();
// Any namespaces that have been loaded from disk and have not had a
// corresponding CreateSessionNamespace() call will be deleted. Called after
@@ -98,7 +123,7 @@ class CONTENT_EXPORT SessionStorageContextMojo
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
- // SessionStorageLevelDBWrapper::Listener implementation:
+ // SessionStorageAreaImpl::Listener implementation:
void OnDataMapCreation(const std::vector<uint8_t>& map_prefix,
SessionStorageDataMap* map) override;
void OnDataMapDestruction(const std::vector<uint8_t>& map_prefix) override;
@@ -116,6 +141,10 @@ class CONTENT_EXPORT SessionStorageContextMojo
const url::Origin& origin);
private:
+ friend class DOMStorageBrowserTest;
+ FRIEND_TEST_ALL_PREFIXES(SessionStorageContextMojoTest,
+ PurgeMemoryDoesNotCrashOrHang);
+
// Object deletion is done through |ShutdownAndDelete()|.
~SessionStorageContextMojo() override;
@@ -163,7 +192,7 @@ class CONTENT_EXPORT SessionStorageContextMojo
void OnShutdownComplete(leveldb::mojom::DatabaseError error);
- void GetStatistics(size_t* total_cache_size, size_t* unused_wrapper_count);
+ void GetStatistics(size_t* total_cache_size, size_t* unused_areas_count);
// These values are written to logs. New enum values can be added, but
// existing enums must never be renumbered or deleted and reused.
@@ -184,12 +213,12 @@ class CONTENT_EXPORT SessionStorageContextMojo
SessionStorageMetadata metadata_;
std::unique_ptr<service_manager::Connector> connector_;
- const base::Optional<base::FilePath> partition_directory_path_;
+ BackingMode backing_mode_;
+ base::FilePath partition_directory_path_;
std::string leveldb_name_;
enum ConnectionState {
NO_CONNECTION,
- FETCHING_METADATA,
CONNECTION_IN_PROGRESS,
CONNECTION_FINISHED,
CONNECTION_SHUTDOWN
diff --git a/chromium/content/browser/dom_storage/session_storage_context_mojo_unittest.cc b/chromium/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
index 1b9ee547d47..f09686f30e9 100644
--- a/chromium/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
+++ b/chromium/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
@@ -21,11 +21,12 @@
#include "content/browser/dom_storage/test/fake_leveldb_database_error_on_write.h"
#include "content/browser/dom_storage/test/fake_leveldb_service.h"
#include "content/browser/dom_storage/test/mojo_test_with_file_service.h"
+#include "content/browser/dom_storage/test/storage_area_test_util.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/session_storage_usage_info.h"
#include "content/public/common/content_features.h"
#include "content/public/test/test_utils.h"
-#include "content/test/leveldb_wrapper_test_util.h"
+#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "services/file/file_service.h"
#include "services/file/public/mojom/constants.mojom.h"
@@ -62,13 +63,27 @@ class SessionStorageContextMojoTest : public test::MojoTestWithFileService {
void SetUp() override {
features_.InitAndEnableFeature(features::kMojoSessionStorage);
+ mojo::core::SetDefaultProcessErrorCallback(base::BindRepeating(
+ &SessionStorageContextMojoTest::OnBadMessage, base::Unretained(this)));
+ }
+
+ void TearDown() override {
+ mojo::core::SetDefaultProcessErrorCallback(
+ mojo::core::ProcessErrorCallback());
+ }
+
+ void OnBadMessage(const std::string& reason) { bad_message_called_ = true; }
+
+ void SetBackingMode(SessionStorageContextMojo::BackingMode backing_mode) {
+ DCHECK(!context_);
+ backing_mode_ = backing_mode;
}
SessionStorageContextMojo* context() {
if (!context_) {
context_ = new SessionStorageContextMojo(
- base::SequencedTaskRunnerHandle::Get(), connector(), base::FilePath(),
- kSessionStorageDirectory);
+ base::SequencedTaskRunnerHandle::Get(), connector(), backing_mode_,
+ base::FilePath(), kSessionStorageDirectory);
}
return context_;
}
@@ -94,10 +109,10 @@ class SessionStorageContextMojoTest : public test::MojoTestWithFileService {
base::StringPiece value,
const std::string& source) {
context()->CreateSessionNamespace(namespace_id);
- mojom::SessionStorageNamespacePtr ss_namespace;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace;
context()->OpenSessionStorage(kTestProcessId, namespace_id,
mojo::MakeRequest(&ss_namespace));
- mojom::LevelDBWrapperAssociatedPtr leveldb;
+ blink::mojom::StorageAreaAssociatedPtr leveldb;
ss_namespace->OpenArea(origin, mojo::MakeRequest(&leveldb));
EXPECT_TRUE(test::PutSync(
leveldb.get(), leveldb::StringPieceToUint8Vector(key),
@@ -110,16 +125,15 @@ class SessionStorageContextMojoTest : public test::MojoTestWithFileService {
const url::Origin& origin,
base::StringPiece key) {
context()->CreateSessionNamespace(namespace_id);
- mojom::SessionStorageNamespacePtr ss_namespace;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace;
context()->OpenSessionStorage(kTestProcessId, namespace_id,
mojo::MakeRequest(&ss_namespace));
- mojom::LevelDBWrapperAssociatedPtr leveldb;
+ blink::mojom::StorageAreaAssociatedPtr leveldb;
ss_namespace->OpenArea(origin, mojo::MakeRequest(&leveldb));
// Use the GetAll interface because Gets are being removed.
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(leveldb.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb.get(), &data));
context()->DeleteSessionNamespace(namespace_id, true);
std::vector<uint8_t> key_as_bytes = leveldb::StringPieceToUint8Vector(key);
@@ -131,7 +145,12 @@ class SessionStorageContextMojoTest : public test::MojoTestWithFileService {
return base::nullopt;
}
+ protected:
+ bool bad_message_called_ = false;
+
private:
+ SessionStorageContextMojo::BackingMode backing_mode_ =
+ SessionStorageContextMojo::BackingMode::kRestoreDiskState;
base::test::ScopedFeatureList features_;
SessionStorageContextMojo* context_ = nullptr;
@@ -167,30 +186,31 @@ TEST_F(SessionStorageContextMojoTest, MigrationV0ToV1) {
context()->CreateSessionNamespace(namespace_id1);
context()->CreateSessionNamespace(namespace_id2);
- mojom::SessionStorageNamespacePtr ss_namespace1;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
mojo::MakeRequest(&ss_namespace1));
- mojom::SessionStorageNamespacePtr ss_namespace2;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace2;
context()->OpenSessionStorage(kTestProcessId, namespace_id2,
mojo::MakeRequest(&ss_namespace2));
- mojom::LevelDBWrapperAssociatedPtr leveldb_n2_o1;
- mojom::LevelDBWrapperAssociatedPtr leveldb_n2_o2;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o2;
ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
ss_namespace2->OpenArea(origin2, mojo::MakeRequest(&leveldb_n2_o2));
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(leveldb_n2_o1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_n2_o1.get(), &data));
// There should have been a migration to get rid of the "map-0-" refcount
// field.
EXPECT_EQ(2ul, data.size());
std::vector<uint8_t> key_as_vector =
StdStringToUint8Vector(base::UTF16ToUTF8(key));
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(key_as_vector, String16ToUint8Vector(value))));
+ data, blink::mojom::KeyValue::New(key_as_vector,
+ String16ToUint8Vector(value))));
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(key_as_vector, String16ToUint8Vector(value))));
+ data, blink::mojom::KeyValue::New(key_as_vector,
+ String16ToUint8Vector(value))));
}
TEST_F(SessionStorageContextMojoTest, StartupShutdownSave) {
@@ -198,17 +218,16 @@ TEST_F(SessionStorageContextMojoTest, StartupShutdownSave) {
url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
context()->CreateSessionNamespace(namespace_id1);
- mojom::SessionStorageNamespacePtr ss_namespace1;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
mojo::MakeRequest(&ss_namespace1));
- mojom::LevelDBWrapperAssociatedPtr leveldb_n1_o1;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
// Verify no data.
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(leveldb_n1_o1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
EXPECT_EQ(0ul, data.size());
// Put some data.
@@ -217,8 +236,7 @@ TEST_F(SessionStorageContextMojoTest, StartupShutdownSave) {
leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
// Verify data is there.
- status = test::GetAllSync(leveldb_n1_o1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
EXPECT_EQ(1ul, data.size());
// Delete the namespace and shutdown the context, BUT persist the namespace so
@@ -233,8 +251,7 @@ TEST_F(SessionStorageContextMojoTest, StartupShutdownSave) {
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
// The data from before should be here.
- status = test::GetAllSync(leveldb_n1_o1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
EXPECT_EQ(1ul, data.size());
// Delete the namespace and shutdown the context and do not persist the data.
@@ -247,26 +264,64 @@ TEST_F(SessionStorageContextMojoTest, StartupShutdownSave) {
mojo::MakeRequest(&ss_namespace1));
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
- // The data from before should be here.
- status = test::GetAllSync(leveldb_n1_o1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ // The data from before should not be here.
+ EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
EXPECT_EQ(0ul, data.size());
}
+TEST_F(SessionStorageContextMojoTest, CloneBeforeBrowserClone) {
+ std::string namespace_id1 = base::GenerateGUID();
+ std::string namespace_id2 = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+ context()->CreateSessionNamespace(namespace_id1);
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ // Put some data.
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
+
+ ss_namespace1->Clone(namespace_id2);
+ leveldb_n1_o1.FlushForTesting();
+
+ // Do the browser-side clone afterwards.
+ context()->CloneSessionNamespace(
+ namespace_id1, namespace_id2,
+ SessionStorageContextMojo::CloneType::kWaitForCloneOnNamespace);
+
+ // Open the second namespace.
+ blink::mojom::SessionStorageNamespacePtr ss_namespace2;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ mojo::MakeRequest(&ss_namespace2));
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
+ ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
+
+ // The data should be in namespace 2.
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_n2_o1.get(), &data));
+ EXPECT_EQ(1ul, data.size());
+}
+
TEST_F(SessionStorageContextMojoTest, Cloning) {
std::string namespace_id1 = base::GenerateGUID();
std::string namespace_id2 = base::GenerateGUID();
url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
context()->CreateSessionNamespace(namespace_id1);
- mojom::SessionStorageNamespacePtr ss_namespace1;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
mojo::MakeRequest(&ss_namespace1));
- mojom::LevelDBWrapperAssociatedPtr leveldb_n1_o1;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
// Context-triggered clone before the put. The clone doesn't actually count
// until a clone comes from the namespace.
- context()->CloneSessionNamespace(namespace_id1, namespace_id2);
+ context()->CloneSessionNamespace(
+ namespace_id1, namespace_id2,
+ SessionStorageContextMojo::CloneType::kWaitForCloneOnNamespace);
// Put some data.
EXPECT_TRUE(test::PutSync(
@@ -277,10 +332,10 @@ TEST_F(SessionStorageContextMojoTest, Cloning) {
leveldb_n1_o1.FlushForTesting();
// Open the second namespace.
- mojom::SessionStorageNamespacePtr ss_namespace2;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace2;
context()->OpenSessionStorage(kTestProcessId, namespace_id2,
mojo::MakeRequest(&ss_namespace2));
- mojom::LevelDBWrapperAssociatedPtr leveldb_n2_o1;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
// Delete the namespace and shutdown the context, BUT persist the namespace so
@@ -289,17 +344,15 @@ TEST_F(SessionStorageContextMojoTest, Cloning) {
context()->DeleteSessionNamespace(namespace_id1, true);
// The data from before should be in namespace 2.
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(leveldb_n2_o1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_n2_o1.get(), &data));
EXPECT_EQ(1ul, data.size());
// Put some data in namespace 2.
EXPECT_TRUE(test::PutSync(
leveldb_n2_o1.get(), leveldb::StringPieceToUint8Vector("key2"),
leveldb::StringPieceToUint8Vector("value2"), base::nullopt, "source1"));
- status = test::GetAllSync(leveldb_n2_o1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_TRUE(test::GetAllSync(leveldb_n2_o1.get(), &data));
EXPECT_EQ(2ul, data.size());
// Re-open namespace 1, check that we don't have the extra data.
@@ -309,11 +362,77 @@ TEST_F(SessionStorageContextMojoTest, Cloning) {
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
// We should only have the first value.
- status = test::GetAllSync(leveldb_n1_o1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
EXPECT_EQ(1ul, data.size());
}
+TEST_F(SessionStorageContextMojoTest, ImmediateCloning) {
+ std::string namespace_id1 = base::GenerateGUID();
+ std::string namespace_id2 = base::GenerateGUID();
+ std::string namespace_id3 = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+ context()->CreateSessionNamespace(namespace_id1);
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ // Immediate clone.
+ context()->CloneSessionNamespace(
+ namespace_id1, namespace_id2,
+ SessionStorageContextMojo::CloneType::kImmediate);
+
+ // Open the second namespace, ensure empty.
+ {
+ blink::mojom::SessionStorageNamespacePtr ss_namespace2;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ mojo::MakeRequest(&ss_namespace2));
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
+ ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_n2_o1.get(), &data));
+ EXPECT_EQ(0ul, data.size());
+ }
+
+ // Delete that namespace, copy again after a put.
+ context()->DeleteSessionNamespace(namespace_id2, false);
+
+ // Put some data.
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value2"), base::nullopt, "source1"));
+
+ context()->CloneSessionNamespace(
+ namespace_id1, namespace_id2,
+ SessionStorageContextMojo::CloneType::kImmediate);
+
+ // Open the second namespace, ensure populated
+ {
+ blink::mojom::SessionStorageNamespacePtr ss_namespace2;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ mojo::MakeRequest(&ss_namespace2));
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
+ ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_n2_o1.get(), &data));
+ EXPECT_EQ(1ul, data.size());
+ }
+
+ context()->DeleteSessionNamespace(namespace_id2, false);
+
+ // Verify that cloning from the namespace object will result in a bad message.
+ context()->CloneSessionNamespace(
+ namespace_id1, namespace_id2,
+ SessionStorageContextMojo::CloneType::kImmediate);
+
+ // This should cause a bad message.
+ ss_namespace1->Clone(namespace_id2);
+ leveldb_n1_o1.FlushForTesting();
+
+ EXPECT_TRUE(bad_message_called_);
+}
+
TEST_F(SessionStorageContextMojoTest, Scavenging) {
// Create our namespace, destroy our context and leave that namespace on disk,
// and verify that it is scavenged if we re-create the context without calling
@@ -327,6 +446,8 @@ TEST_F(SessionStorageContextMojoTest, Scavenging) {
// This scavenge call should NOT delete the namespace, as we just created it.
{
base::RunLoop loop;
+ // Cause the connection to start loading, so we start scavenging mid-load.
+ context()->Flush();
context()->ScavengeUnusedNamespaces(loop.QuitClosure());
loop.Run();
}
@@ -334,10 +455,10 @@ TEST_F(SessionStorageContextMojoTest, Scavenging) {
ShutdownContext();
context()->CreateSessionNamespace(namespace_id1);
- mojom::SessionStorageNamespacePtr ss_namespace1;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
mojo::MakeRequest(&ss_namespace1));
- mojom::LevelDBWrapperAssociatedPtr leveldb_n1_o1;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
EXPECT_TRUE(test::PutSync(
leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
@@ -371,9 +492,8 @@ TEST_F(SessionStorageContextMojoTest, Scavenging) {
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
mojo::MakeRequest(&ss_namespace1));
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(leveldb_n1_o1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
EXPECT_EQ(1ul, data.size());
// Shutting down the context without an explicit DeleteSessionNamespace should
@@ -391,8 +511,7 @@ TEST_F(SessionStorageContextMojoTest, Scavenging) {
context()->OpenSessionStorage(kTestProcessId, namespace_id1,
mojo::MakeRequest(&ss_namespace1));
ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
- status = test::GetAllSync(leveldb_n1_o1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
EXPECT_EQ(0ul, data.size());
}
@@ -488,29 +607,22 @@ TEST_F(SessionStorageContextMojoTest, RecreateOnCommitFailure) {
base::Unretained(&fake_leveldb_service))));
// Open three connections to the database.
- mojom::LevelDBWrapperAssociatedPtr wrapper1;
- mojom::LevelDBWrapperAssociatedPtr wrapper2;
- mojom::LevelDBWrapperAssociatedPtr wrapper3;
- mojom::SessionStorageNamespacePtr ss_namespace;
+ blink::mojom::StorageAreaAssociatedPtr area1;
+ blink::mojom::StorageAreaAssociatedPtr area2;
+ blink::mojom::StorageAreaAssociatedPtr area3;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace;
context()->CreateSessionNamespace(namespace_id);
{
base::RunLoop loop;
fake_leveldb_service.SetOnOpenCallback(loop.QuitClosure());
context()->OpenSessionStorage(kTestProcessId, namespace_id,
mojo::MakeRequest(&ss_namespace));
- ss_namespace->OpenArea(origin1, mojo::MakeRequest(&wrapper1));
- ss_namespace->OpenArea(origin2, mojo::MakeRequest(&wrapper2));
- ss_namespace->OpenArea(origin3, mojo::MakeRequest(&wrapper3));
+ ss_namespace->OpenArea(origin1, mojo::MakeRequest(&area1));
+ ss_namespace->OpenArea(origin2, mojo::MakeRequest(&area2));
+ ss_namespace->OpenArea(origin3, mojo::MakeRequest(&area3));
loop.Run();
}
- // Add observers to the first two connections.
- testing::StrictMock<test::MockLevelDBObserver> observer1;
- wrapper1->AddObserver(observer1.Bind());
- EXPECT_FALSE(wrapper1.encountered_error());
- testing::StrictMock<test::MockLevelDBObserver> observer3;
- wrapper3->AddObserver(observer3.Bind());
-
// Verify one attempt was made to open the database, and connect that request
// with a database implementation that always fails on write.
ASSERT_EQ(1u, fake_leveldb_service.open_requests().size());
@@ -533,42 +645,27 @@ TEST_F(SessionStorageContextMojoTest, RecreateOnCommitFailure) {
// pending commit that will get cancelled when the database connection is
// closed.
auto value = leveldb::StringPieceToUint8Vector("avalue");
- EXPECT_CALL(observer3, KeyAdded(leveldb::StringPieceToUint8Vector("w3key"),
- value, "source"))
- .Times(1);
- wrapper3->Put(leveldb::StringPieceToUint8Vector("w3key"), value,
- base::nullopt, "source",
- base::BindOnce([](bool success) { EXPECT_TRUE(success); }));
+ area3->Put(leveldb::StringPieceToUint8Vector("w3key"), value, base::nullopt,
+ "source",
+ base::BindOnce([](bool success) { EXPECT_TRUE(success); }));
// Repeatedly write data to the database, to trigger enough commit errors.
int i = 0;
- while (!wrapper1.encountered_error()) {
+ while (!area1.encountered_error()) {
++i;
base::RunLoop put_loop;
// Every write needs to be different to make sure there actually is a
// change to commit.
std::vector<uint8_t> old_value = value;
value[0]++;
- wrapper1.set_connection_error_handler(put_loop.QuitClosure());
-
- if (i == 1) {
- EXPECT_CALL(observer1, ShouldSendOldValueOnMutations(false)).Times(1);
- EXPECT_CALL(observer1, KeyAdded(leveldb::StringPieceToUint8Vector("key"),
- value, "source"))
- .Times(1);
- } else {
- EXPECT_CALL(observer1,
- KeyChanged(leveldb::StringPieceToUint8Vector("key"), value,
- old_value, "source"))
- .Times(1);
- }
- wrapper1->Put(leveldb::StringPieceToUint8Vector("key"), value,
- base::nullopt, "source",
- base::BindLambdaForTesting([&](bool success) {
- EXPECT_TRUE(success);
- put_loop.Quit();
- }));
- wrapper1.FlushForTesting();
+ area1.set_connection_error_handler(put_loop.QuitClosure());
+
+ area1->Put(leveldb::StringPieceToUint8Vector("key"), value, base::nullopt,
+ "source", base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
+ area1.FlushForTesting();
put_loop.RunUntilIdle();
// And we need to flush after every change. Otherwise changes get batched up
// and only one commit is done some time later.
@@ -583,27 +680,27 @@ TEST_F(SessionStorageContextMojoTest, RecreateOnCommitFailure) {
// connection to the database to have been severed.
EXPECT_FALSE(mock_db);
- // The connection to the second wrapper should have closed as well.
- EXPECT_TRUE(wrapper2.encountered_error());
+ // The connection to the second area should have closed as well.
+ EXPECT_TRUE(area2.encountered_error());
EXPECT_TRUE(ss_namespace.encountered_error());
// And the old database should have been destroyed.
EXPECT_EQ(1u, fake_leveldb_service.destroy_requests().size());
- // Reconnect wrapper1 to the database, and try to read a value.
+ // Reconnect area1 to the database, and try to read a value.
context()->OpenSessionStorage(kTestProcessId, namespace_id,
mojo::MakeRequest(&ss_namespace));
- ss_namespace->OpenArea(origin1, mojo::MakeRequest(&wrapper1));
+ ss_namespace->OpenArea(origin1, mojo::MakeRequest(&area1));
base::RunLoop delete_loop;
bool success = true;
test::MockLevelDBObserver observer4;
- wrapper1->AddObserver(observer4.Bind());
- wrapper1->Delete(leveldb::StringPieceToUint8Vector("key"), base::nullopt,
- "source", base::BindLambdaForTesting([&](bool success_in) {
- success = success_in;
- delete_loop.Quit();
- }));
+ area1->AddObserver(observer4.Bind());
+ area1->Delete(leveldb::StringPieceToUint8Vector("key"), base::nullopt,
+ "source", base::BindLambdaForTesting([&](bool success_in) {
+ success = success_in;
+ delete_loop.Quit();
+ }));
// Wait for LocalStorageContextMojo to try to reconnect to the database, and
// connect that new request to a properly functioning database.
@@ -616,10 +713,10 @@ TEST_F(SessionStorageContextMojoTest, RecreateOnCommitFailure) {
std::move(reopen_request.callback).Run(leveldb::mojom::DatabaseError::OK);
fake_leveldb_service.open_requests().clear();
- // And deleting the value from the new wrapper should have failed (as the
+ // And deleting the value from the new area should have failed (as the
// database is empty).
delete_loop.Run();
- wrapper1 = nullptr;
+ area1 = nullptr;
ss_namespace.reset();
context()->DeleteSessionNamespace(namespace_id, true);
@@ -647,15 +744,15 @@ TEST_F(SessionStorageContextMojoTest, DontRecreateOnRepeatedCommitFailure) {
std::map<std::vector<uint8_t>, std::vector<uint8_t>> test_data;
// Open three connections to the database.
- mojom::LevelDBWrapperAssociatedPtr wrapper;
- mojom::SessionStorageNamespacePtr ss_namespace;
+ blink::mojom::StorageAreaAssociatedPtr area;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace;
context()->CreateSessionNamespace(namespace_id);
{
base::RunLoop loop;
fake_leveldb_service.SetOnOpenCallback(loop.QuitClosure());
context()->OpenSessionStorage(kTestProcessId, namespace_id,
mojo::MakeRequest(&ss_namespace));
- ss_namespace->OpenArea(origin1, mojo::MakeRequest(&wrapper));
+ ss_namespace->OpenArea(origin1, mojo::MakeRequest(&area));
loop.Run();
}
@@ -678,17 +775,17 @@ TEST_F(SessionStorageContextMojoTest, DontRecreateOnRepeatedCommitFailure) {
// Repeatedly write data to the database, to trigger enough commit errors.
auto value = leveldb::StringPieceToUint8Vector("avalue");
base::Optional<std::vector<uint8_t>> old_value = base::nullopt;
- while (!wrapper.encountered_error()) {
+ while (!area.encountered_error()) {
base::RunLoop put_loop;
// Every write needs to be different to make sure there actually is a
// change to commit.
- wrapper.set_connection_error_handler(put_loop.QuitClosure());
- wrapper->Put(leveldb::StringPieceToUint8Vector("key"), value, old_value,
- "source", base::BindLambdaForTesting([&](bool success) {
- EXPECT_TRUE(success);
- put_loop.Quit();
- }));
- wrapper.FlushForTesting();
+ area.set_connection_error_handler(put_loop.QuitClosure());
+ area->Put(leveldb::StringPieceToUint8Vector("key"), value, old_value,
+ "source", base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
+ area.FlushForTesting();
put_loop.RunUntilIdle();
// And we need to flush after every change. Otherwise changes get batched up
// and only one commit is done some time later.
@@ -721,24 +818,24 @@ TEST_F(SessionStorageContextMojoTest, DontRecreateOnRepeatedCommitFailure) {
// The old database should also have been destroyed.
EXPECT_EQ(1u, fake_leveldb_service.destroy_requests().size());
- // Reconnect a wrapper to the database, and repeatedly write data to it again.
+ // Reconnect a area to the database, and repeatedly write data to it again.
// This time all should just keep getting written, and commit errors are
// getting ignored.
context()->OpenSessionStorage(kTestProcessId, namespace_id,
mojo::MakeRequest(&ss_namespace));
- ss_namespace->OpenArea(origin1, mojo::MakeRequest(&wrapper));
+ ss_namespace->OpenArea(origin1, mojo::MakeRequest(&area));
old_value = base::nullopt;
for (int i = 0; i < 64; ++i) {
base::RunLoop put_loop;
// Every write needs to be different to make sure there actually is a
// change to commit.
- wrapper.set_connection_error_handler(put_loop.QuitClosure());
- wrapper->Put(leveldb::StringPieceToUint8Vector("key"), value, old_value,
- "source", base::BindLambdaForTesting([&](bool success) {
- EXPECT_TRUE(success);
- put_loop.Quit();
- }));
- wrapper.FlushForTesting();
+ area.set_connection_error_handler(put_loop.QuitClosure());
+ area->Put(leveldb::StringPieceToUint8Vector("key"), value, old_value,
+ "source", base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
+ area.FlushForTesting();
put_loop.RunUntilIdle();
// And we need to flush after every change. Otherwise changes get batched up
// and only one commit is done some time later.
@@ -753,10 +850,233 @@ TEST_F(SessionStorageContextMojoTest, DontRecreateOnRepeatedCommitFailure) {
if (mock_db)
mock_db->FlushForTesting();
EXPECT_TRUE(mock_db);
- EXPECT_FALSE(wrapper.encountered_error());
+ EXPECT_FALSE(area.encountered_error());
context()->DeleteSessionNamespace(namespace_id, false);
}
+TEST_F(SessionStorageContextMojoTest, GetUsage) {
+ std::string namespace_id1 = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+ context()->CreateSessionNamespace(namespace_id1);
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ // Put some data.
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
+
+ base::RunLoop loop;
+ context()->GetStorageUsage(base::BindLambdaForTesting(
+ [&](std::vector<SessionStorageUsageInfo> usage) {
+ loop.Quit();
+ ASSERT_EQ(1u, usage.size());
+ EXPECT_EQ(origin1.GetURL(), usage[0].origin);
+ EXPECT_EQ(namespace_id1, usage[0].namespace_id);
+ }));
+ loop.Run();
+}
+
+TEST_F(SessionStorageContextMojoTest, DeleteStorage) {
+ std::string namespace_id1 = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+
+ // First, test deleting data for a namespace that is open.
+ context()->CreateSessionNamespace(namespace_id1);
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ // Put some data.
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
+
+ context()->DeleteStorage(origin1, namespace_id1);
+
+ std::vector<blink::mojom::KeyValuePtr> data;
+ ASSERT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
+ EXPECT_EQ(0ul, data.size());
+
+ // Next, test that it deletes the data even if there isn't a namespace open.
+ // Put some data.
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
+ // Delete the namespace and shutdown the context, BUT persist the namespace so
+ // it can be loaded again.
+ context()->DeleteSessionNamespace(namespace_id1, true);
+ ShutdownContext();
+
+ // This restarts the context, then deletes the storage.
+ context()->DeleteStorage(origin1, namespace_id1);
+
+ context()->CreateSessionNamespace(namespace_id1);
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+ data.clear();
+ EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
+ EXPECT_EQ(0ul, data.size());
+}
+
+TEST_F(SessionStorageContextMojoTest, PurgeInactiveWrappers) {
+ std::string namespace_id1 = base::GenerateGUID();
+ std::string namespace_id2 = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+
+ context()->CreateSessionNamespace(namespace_id1);
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ blink::mojom::StorageAreaAssociatedPtr leveldb;
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb));
+
+ // Put some data in both.
+ EXPECT_TRUE(test::PutSync(
+ leveldb.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
+ context()->FlushAreaForTesting(namespace_id1, origin1);
+
+ ss_namespace1.reset();
+ leveldb.reset();
+
+ // Clear all the data from the backing database.
+ base::RunLoop loop;
+ context()->DatabaseForTesting()->DeletePrefixed(
+ leveldb::StringPieceToUint8Vector("map"),
+ base::BindLambdaForTesting([&](DatabaseError status) {
+ loop.Quit();
+ EXPECT_EQ(DatabaseError::OK, status);
+ }));
+ loop.Run();
+
+ // Now open many new wrappers (for different origins) to trigger clean up.
+ for (int i = 1; i <= 100; ++i) {
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ blink::mojom::StorageAreaAssociatedPtr leveldb;
+ ss_namespace1->OpenArea(url::Origin::Create(GURL(base::StringPrintf(
+ "http://example.com:%d", i))),
+ mojo::MakeRequest(&leveldb));
+ base::RunLoop().RunUntilIdle();
+ ss_namespace1.reset();
+ leveldb.reset();
+ }
+
+ // And make sure caches were actually cleared.
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb));
+ std::vector<blink::mojom::KeyValuePtr> data;
+ ASSERT_TRUE(test::GetAllSync(leveldb.get(), &data));
+ EXPECT_EQ(0ul, data.size());
+}
+
+TEST_F(SessionStorageContextMojoTest, ClearDiskState) {
+ SetBackingMode(SessionStorageContextMojo::BackingMode::kClearDiskStateOnOpen);
+ std::string namespace_id1 = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+ context()->CreateSessionNamespace(namespace_id1);
+
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ // Verify no data.
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
+ EXPECT_EQ(0ul, data.size());
+
+ // Put some data.
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
+
+ // Delete the namespace and shutdown the context, BUT persist the namespace on
+ // disk.
+ context()->DeleteSessionNamespace(namespace_id1, true);
+ ShutdownContext();
+
+ // This will re-open the context, and load the persisted namespace, but it
+ // should have been deleted due to our backing mode.
+ context()->CreateSessionNamespace(namespace_id1);
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ // The data from before should not be here, because the context clears disk
+ // space on open.
+ EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
+ EXPECT_EQ(0ul, data.size());
+}
+
} // namespace
+
+TEST_F(SessionStorageContextMojoTest, PurgeMemoryDoesNotCrashOrHang) {
+ std::string namespace_id1 = base::GenerateGUID();
+ std::string namespace_id2 = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+
+ context()->CreateSessionNamespace(namespace_id1);
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ context()->CreateSessionNamespace(namespace_id2);
+ blink::mojom::SessionStorageNamespacePtr ss_namespace2;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ mojo::MakeRequest(&ss_namespace2));
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
+ ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
+
+ // Put some data in both.
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n2_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value2"), base::nullopt, "source1"));
+
+ context()->FlushAreaForTesting(namespace_id1, origin1);
+
+ leveldb_n2_o1.reset();
+ ss_namespace2.reset();
+
+ base::RunLoop().RunUntilIdle();
+
+ // Verify this doesn't crash or hang.
+ context()->PurgeMemory();
+
+ size_t memory_used = context()
+ ->namespaces_[namespace_id1]
+ ->origin_areas_[origin1]
+ ->data_map()
+ ->storage_area()
+ ->memory_used();
+ EXPECT_EQ(0ul, memory_used);
+
+ // Test the values is still there.
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
+ EXPECT_EQ(1ul, data.size());
+
+ base::Optional<std::vector<uint8_t>> opt_value2 =
+ DoTestGet(namespace_id2, origin1, "key1");
+ ASSERT_TRUE(opt_value2);
+ EXPECT_EQ(leveldb::StringPieceToUint8Vector("value2"), opt_value2.value());
+}
+
} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_data_map.cc b/chromium/content/browser/dom_storage/session_storage_data_map.cc
index 4580e195381..a2f0507de42 100644
--- a/chromium/content/browser/dom_storage/session_storage_data_map.cc
+++ b/chromium/content/browser/dom_storage/session_storage_data_map.cc
@@ -24,7 +24,7 @@ scoped_refptr<SessionStorageDataMap> SessionStorageDataMap::Create(
scoped_refptr<SessionStorageDataMap> SessionStorageDataMap::CreateClone(
Listener* listener,
scoped_refptr<SessionStorageMetadata::MapData> map_data,
- LevelDBWrapperImpl* clone_from) {
+ StorageAreaImpl* clone_from) {
return base::WrapRefCounted(
new SessionStorageDataMap(listener, std::move(map_data), clone_from));
}
@@ -44,11 +44,12 @@ SessionStorageDataMap::SessionStorageDataMap(
leveldb::mojom::LevelDBDatabase* database)
: listener_(listener),
map_data_(std::move(map_data)),
- wrapper_impl_(std::make_unique<LevelDBWrapperImpl>(database,
- map_data_->KeyPrefix(),
- this,
- GetOptions())),
- level_db_wrapper_ptr_(wrapper_impl_.get()) {
+ storage_area_impl_(
+ std::make_unique<StorageAreaImpl>(database,
+ map_data_->KeyPrefix(),
+ this,
+ GetOptions())),
+ storage_area_ptr_(storage_area_impl_.get()) {
DCHECK(listener_);
DCHECK(map_data_);
listener_->OnDataMapCreation(map_data_->MapNumberAsBytes(), this);
@@ -57,13 +58,13 @@ SessionStorageDataMap::SessionStorageDataMap(
SessionStorageDataMap::SessionStorageDataMap(
Listener* listener,
scoped_refptr<SessionStorageMetadata::MapData> map_data,
- LevelDBWrapperImpl* forking_from)
+ StorageAreaImpl* forking_from)
: listener_(listener),
map_data_(std::move(map_data)),
- wrapper_impl_(forking_from->ForkToNewPrefix(map_data_->KeyPrefix(),
- this,
- GetOptions())),
- level_db_wrapper_ptr_(wrapper_impl_.get()) {
+ storage_area_impl_(forking_from->ForkToNewPrefix(map_data_->KeyPrefix(),
+ this,
+ GetOptions())),
+ storage_area_ptr_(storage_area_impl_.get()) {
DCHECK(listener_);
DCHECK(map_data_);
listener_->OnDataMapCreation(map_data_->MapNumberAsBytes(), this);
@@ -81,11 +82,11 @@ void SessionStorageDataMap::RemoveBindingReference() {
// Don't delete ourselves, but do schedule an immediate commit. Possible
// deletion will happen under memory pressure or when another sessionstorage
// area is opened.
- level_db_wrapper()->ScheduleImmediateCommit();
+ storage_area()->ScheduleImmediateCommit();
}
// static
-LevelDBWrapperImpl::Options SessionStorageDataMap::GetOptions() {
+StorageAreaImpl::Options SessionStorageDataMap::GetOptions() {
// Delay for a moment after a value is set in anticipation
// of other values being set, so changes are batched.
constexpr const base::TimeDelta kCommitDefaultDelaySecs =
@@ -93,12 +94,12 @@ LevelDBWrapperImpl::Options SessionStorageDataMap::GetOptions() {
// To avoid excessive IO we apply limits to the amount of data being
// written and the frequency of writes.
- LevelDBWrapperImpl::Options options;
+ StorageAreaImpl::Options options;
options.max_size = kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance;
options.default_commit_delay = kCommitDefaultDelaySecs;
options.max_bytes_per_hour = kPerStorageAreaQuota;
options.max_commits_per_hour = 60;
- options.cache_mode = LevelDBWrapperImpl::CacheMode::KEYS_ONLY_WHEN_POSSIBLE;
+ options.cache_mode = StorageAreaImpl::CacheMode::KEYS_ONLY_WHEN_POSSIBLE;
return options;
}
diff --git a/chromium/content/browser/dom_storage/session_storage_data_map.h b/chromium/content/browser/dom_storage/session_storage_data_map.h
index b4f60811a9a..038652ffc96 100644
--- a/chromium/content/browser/dom_storage/session_storage_data_map.h
+++ b/chromium/content/browser/dom_storage/session_storage_data_map.h
@@ -12,25 +12,24 @@
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "content/browser/dom_storage/session_storage_metadata.h"
-#include "content/browser/leveldb_wrapper_impl.h"
+#include "content/browser/dom_storage/storage_area_impl.h"
#include "content/common/content_export.h"
-#include "content/common/leveldb_wrapper.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
namespace content {
-// Holds the LevelDBWrapper for a session storage data map. Every
+// Holds the StorageArea for a session storage data map. Every
// namespace-origin area has a data map. To support shallow copying of the data
// (copy-on-write), a single data map can be shared between multiple namespaces.
// Thus this class is refcounted. This class has a one-to-one relationship with
// the SessionStorageMetadata::MapData object, accessible from |map_data()|.
//
-// Neither this data map nor the inner LevelDBWrapper is bound to, as it needs
+// Neither this data map nor the inner StorageArea is bound to, as it needs
// to be shared between multiple connections if it is shallow-copied. However,
// it does allow it's user to keep track of the number of binding using
// |binding_count()|, |AddBindingReference()|, and |RemoveBindingReference()|.
class CONTENT_EXPORT SessionStorageDataMap final
- : public LevelDBWrapperImpl::Delegate,
+ : public StorageAreaImpl::Delegate,
public base::RefCounted<SessionStorageDataMap> {
public:
class CONTENT_EXPORT Listener {
@@ -50,11 +49,11 @@ class CONTENT_EXPORT SessionStorageDataMap final
static scoped_refptr<SessionStorageDataMap> CreateClone(
Listener* listener,
scoped_refptr<SessionStorageMetadata::MapData> map_data,
- LevelDBWrapperImpl* clone_from);
+ StorageAreaImpl* clone_from);
Listener* listener() const { return listener_; }
- LevelDBWrapperImpl* level_db_wrapper() { return level_db_wrapper_ptr_; }
+ StorageAreaImpl* storage_area() { return storage_area_ptr_; }
scoped_refptr<SessionStorageMetadata::MapData> map_data() {
return map_data_.get();
@@ -63,10 +62,10 @@ class CONTENT_EXPORT SessionStorageDataMap final
int binding_count() { return binding_count_; }
void AddBindingReference() { ++binding_count_; }
// When the binding count reaches 0, we schedule an immediate commit on our
- // wrapper, but we don't close the connection.
+ // area, but we don't close the connection.
void RemoveBindingReference();
- // Note: this is irrelevant, as the parent wrapper is handling binding.
+ // Note: this is irrelevant, as the parent area is handling binding.
void OnNoBindings() override {}
std::vector<leveldb::mojom::BatchedOperationPtr> PrepareToCommit() override;
@@ -83,21 +82,21 @@ class CONTENT_EXPORT SessionStorageDataMap final
SessionStorageDataMap(
Listener* listener,
scoped_refptr<SessionStorageMetadata::MapData> map_entry,
- LevelDBWrapperImpl* forking_from);
+ StorageAreaImpl* forking_from);
~SessionStorageDataMap() override;
- static LevelDBWrapperImpl::Options GetOptions();
+ static StorageAreaImpl::Options GetOptions();
Listener* listener_;
int binding_count_ = 0;
scoped_refptr<SessionStorageMetadata::MapData> map_data_;
- std::unique_ptr<LevelDBWrapperImpl> wrapper_impl_;
- // Holds the same value as |wrapper_impl_|. The reason for this is that
- // during destruction of the LevelDBWrapperImpl instance we might still get
- // called and need access to the LevelDBWrapperImpl instance. The
+ std::unique_ptr<StorageAreaImpl> storage_area_impl_;
+ // Holds the same value as |storage_area_impl_|. The reason for this is that
+ // during destruction of the StorageAreaImpl instance we might still get
+ // called and need access to the StorageAreaImpl instance. The
// unique_ptr could already be null, but this field should still be valid.
// TODO(dmurph): Change delegate ownership so this doesn't have to be done.
- LevelDBWrapperImpl* level_db_wrapper_ptr_;
+ StorageAreaImpl* storage_area_ptr_;
DISALLOW_COPY_AND_ASSIGN(SessionStorageDataMap);
};
diff --git a/chromium/content/browser/dom_storage/session_storage_data_map_unittest.cc b/chromium/content/browser/dom_storage/session_storage_data_map_unittest.cc
index 97af433c270..8797e0c9db1 100644
--- a/chromium/content/browser/dom_storage/session_storage_data_map_unittest.cc
+++ b/chromium/content/browser/dom_storage/session_storage_data_map_unittest.cc
@@ -33,27 +33,27 @@ class MockListener : public SessionStorageDataMap::Listener {
MOCK_METHOD1(OnCommitResult, void(leveldb::mojom::DatabaseError error));
};
-void GetAllDataCallback(leveldb::mojom::DatabaseError* status_out,
- std::vector<mojom::KeyValuePtr>* data_out,
- leveldb::mojom::DatabaseError status,
- std::vector<mojom::KeyValuePtr> data) {
- *status_out = status;
+void GetAllDataCallback(bool* success_out,
+ std::vector<blink::mojom::KeyValuePtr>* data_out,
+ bool success,
+ std::vector<blink::mojom::KeyValuePtr> data) {
+ *success_out = success;
*data_out = std::move(data);
}
-base::OnceCallback<void(leveldb::mojom::DatabaseError status,
- std::vector<mojom::KeyValuePtr> data)>
-MakeGetAllCallback(leveldb::mojom::DatabaseError* status_out,
- std::vector<mojom::KeyValuePtr>* data_out) {
- return base::BindOnce(&GetAllDataCallback, status_out, data_out);
+base::OnceCallback<void(bool success,
+ std::vector<blink::mojom::KeyValuePtr> data)>
+MakeGetAllCallback(bool* sucess_out,
+ std::vector<blink::mojom::KeyValuePtr>* data_out) {
+ return base::BindOnce(&GetAllDataCallback, sucess_out, data_out);
}
-class GetAllCallback : public mojom::LevelDBWrapperGetAllCallback {
+class GetAllCallback : public blink::mojom::StorageAreaGetAllCallback {
public:
- static mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo CreateAndBind(
+ static blink::mojom::StorageAreaGetAllCallbackAssociatedPtrInfo CreateAndBind(
bool* result,
base::OnceClosure callback) {
- mojom::LevelDBWrapperGetAllCallbackAssociatedPtr ptr;
+ blink::mojom::StorageAreaGetAllCallbackAssociatedPtr ptr;
auto request = mojo::MakeRequestAssociatedWithDedicatedPipe(&ptr);
mojo::MakeStrongAssociatedBinding(
base::WrapUnique(new GetAllCallback(result, std::move(callback))),
@@ -108,13 +108,13 @@ TEST_F(SessionStorageDataMapTest, BasicEmptyCreation) {
base::MakeRefCounted<SessionStorageMetadata::MapData>(1, test_origin_),
&database_);
- leveldb::mojom::DatabaseError status;
- std::vector<mojom::KeyValuePtr> data;
+ bool success;
+ std::vector<blink::mojom::KeyValuePtr> data;
bool done = false;
base::RunLoop loop;
- map->level_db_wrapper()->GetAll(
+ map->storage_area()->GetAll(
GetAllCallback::CreateAndBind(&done, loop.QuitClosure()),
- MakeGetAllCallback(&status, &data));
+ MakeGetAllCallback(&success, &data));
loop.Run();
EXPECT_TRUE(done);
@@ -152,15 +152,15 @@ TEST_F(SessionStorageDataMapTest, Clone) {
&listener_,
base::MakeRefCounted<SessionStorageMetadata::MapData>(2,
test_origin_),
- map1->level_db_wrapper());
+ map1->storage_area());
- leveldb::mojom::DatabaseError status;
- std::vector<mojom::KeyValuePtr> data;
+ bool success;
+ std::vector<blink::mojom::KeyValuePtr> data;
bool done = false;
base::RunLoop loop;
- map2->level_db_wrapper()->GetAll(
+ map2->storage_area()->GetAll(
GetAllCallback::CreateAndBind(&done, loop.QuitClosure()),
- MakeGetAllCallback(&status, &data));
+ MakeGetAllCallback(&success, &data));
loop.Run();
EXPECT_TRUE(done);
diff --git a/chromium/content/browser/dom_storage/session_storage_database.cc b/chromium/content/browser/dom_storage/session_storage_database.cc
index 8af5497c82c..cc9e839424a 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database.cc
@@ -19,6 +19,7 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "build/build_config.h"
+#include "content/browser/dom_storage/session_storage_metadata.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/leveldb_chrome.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
@@ -492,7 +493,24 @@ leveldb::Status SessionStorageDatabase::TryToOpen(
// delete the old database here before we open it.
leveldb::DestroyDB(db_name, options);
#endif
- return leveldb_env::OpenDB(options, db_name, db);
+ leveldb::Status s = leveldb_env::OpenDB(options, db_name, db);
+ if (!s.ok())
+ return s;
+
+ // If there is a version entry from the new implementation, treat the database
+ // as corrupt.
+ leveldb::Slice version_key =
+ leveldb::Slice(reinterpret_cast<const char*>(
+ SessionStorageMetadata::kDatabaseVersionBytes),
+ sizeof(SessionStorageMetadata::kDatabaseVersionBytes));
+ std::string dummy;
+ s = (*db)->Get(leveldb::ReadOptions(), version_key, &dummy);
+ if (s.IsNotFound())
+ return leveldb::Status::OK();
+
+ db->reset();
+ return leveldb::Status::Corruption(
+ "Cannot read a database that is a higher schema version.", dummy);
}
bool SessionStorageDatabase::IsOpen() const {
diff --git a/chromium/content/browser/dom_storage/session_storage_database_unittest.cc b/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
index ad590cad0df..af7de589318 100644
--- a/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
@@ -21,6 +21,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/dom_storage/session_storage_metadata.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
@@ -825,5 +826,24 @@ TEST_F(SessionStorageDatabaseTest, DeleteAllOrigins) {
CheckDatabaseConsistency();
}
+TEST_F(SessionStorageDatabaseTest, WipeDBOnNewVersion) {
+ // Write data for a namespace.
+ DOMStorageValuesMap data;
+ data[kKey1] = kValue1;
+ ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data));
+ CheckDatabaseConsistency();
+
+ leveldb::Slice version_key =
+ leveldb::Slice(reinterpret_cast<const char*>(
+ SessionStorageMetadata::kDatabaseVersionBytes),
+ sizeof(SessionStorageMetadata::kDatabaseVersionBytes));
+ db_->db()->Put(leveldb::WriteOptions(), version_key, "something");
+ ResetDatabase();
+
+ CheckDatabaseConsistency();
+ CheckEmptyDatabase();
+ data.clear();
+ CheckAreaData(kNamespace1, kOrigin1, data);
+}
} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_metadata.cc b/chromium/content/browser/dom_storage/session_storage_metadata.cc
index d129f92e127..515bbac0b12 100644
--- a/chromium/content/browser/dom_storage/session_storage_metadata.cc
+++ b/chromium/content/browser/dom_storage/session_storage_metadata.cc
@@ -300,7 +300,8 @@ void SessionStorageMetadata::RegisterShallowClonedNamespace(
source_namespace->second;
std::map<url::Origin, scoped_refptr<MapData>>& destination_origins =
destination_namespace->second;
- DCHECK_EQ(0ul, destination_origins.size());
+ DCHECK_EQ(0ul, destination_origins.size())
+ << "The destination already has data.";
save_operations->reserve(save_operations->size() + source_origins.size());
for (const auto& origin_map_pair : source_origins) {
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc b/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
index 484118b1826..81c1d91c755 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
@@ -60,7 +60,8 @@ scoped_refptr<SessionStorageNamespaceImpl>
SessionStorageNamespaceImpl::CloneFrom(
scoped_refptr<DOMStorageContextWrapper> context,
std::string namespace_id,
- const std::string& namespace_id_to_clone) {
+ const std::string& namespace_id_to_clone,
+ bool immediately) {
if (context->mojo_session_state()) {
DCHECK(base::FeatureList::IsEnabled(features::kMojoSessionStorage));
auto result = base::WrapRefCounted(
@@ -69,7 +70,11 @@ SessionStorageNamespaceImpl::CloneFrom(
FROM_HERE,
base::BindOnce(&SessionStorageContextMojo::CloneSessionNamespace,
base::Unretained(context->mojo_session_state()),
- namespace_id_to_clone, result->namespace_id_));
+ namespace_id_to_clone, result->namespace_id_,
+ immediately
+ ? SessionStorageContextMojo::CloneType::kImmediate
+ : SessionStorageContextMojo::CloneType::
+ kWaitForCloneOnNamespace));
return result;
}
scoped_refptr<DOMStorageContextImpl> context_impl = context->context();
@@ -96,7 +101,7 @@ bool SessionStorageNamespaceImpl::should_persist() const {
scoped_refptr<SessionStorageNamespaceImpl>
SessionStorageNamespaceImpl::Clone() {
return CloneFrom(context_wrapper_, AllocateSessionStorageNamespaceId(),
- namespace_id_);
+ namespace_id_, true);
}
bool SessionStorageNamespaceImpl::IsFromContext(
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl.h b/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
index 8278286e086..7f3de289774 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
@@ -34,16 +34,20 @@ class SessionStorageNamespaceImpl : public SessionStorageNamespace {
// If there is an existing SessionStorageNamespaceImpl with the given id in
// the DOMStorageContextWrapper, this will return that object. Otherwise this
// constructs a SessionStorageNamespaceImpl and assigns |namespace_id| to it.
- static scoped_refptr<SessionStorageNamespaceImpl> Create(
+ CONTENT_EXPORT static scoped_refptr<SessionStorageNamespaceImpl> Create(
scoped_refptr<DOMStorageContextWrapper> context,
std::string namespace_id);
// Constructs a |SessionStorageNamespaceImpl| with id |namespace_id| by
// cloning |namespace_to_clone|. Allocates it a new ID.
+ // Only set |immediately| to true to cause the clone to immediately happen,
+ // where there definitely will not be a |Clone| call from the
+ // SessionStorageNamespace mojo object.
static scoped_refptr<SessionStorageNamespaceImpl> CloneFrom(
scoped_refptr<DOMStorageContextWrapper> context,
std::string namespace_id,
- const std::string& namespace_id_to_clone);
+ const std::string& namespace_id_to_clone,
+ bool immediately = false);
DOMStorageContextWrapper* context() const { return context_wrapper_.get(); }
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc
index d02473e3d23..6bc8e13b918 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc
@@ -17,7 +17,7 @@ SessionStorageNamespaceImplMojo::SessionStorageNamespaceImplMojo(
std::string namespace_id,
SessionStorageDataMap::Listener* data_map_listener,
RegisterShallowClonedNamespace add_namespace_callback,
- SessionStorageLevelDBWrapper::RegisterNewAreaMap register_new_map_callback)
+ SessionStorageAreaImpl::RegisterNewAreaMap register_new_map_callback)
: namespace_id_(std::move(namespace_id)),
data_map_listener_(data_map_listener),
add_namespace_callback_(std::move(add_namespace_callback)),
@@ -49,7 +49,7 @@ void SessionStorageNamespaceImplMojo::PopulateFromMetadata(
} else {
data_map = base::WrapRefCounted(map_it->second);
}
- origin_areas_[pair.first] = std::make_unique<SessionStorageLevelDBWrapper>(
+ origin_areas_[pair.first] = std::make_unique<SessionStorageAreaImpl>(
namespace_entry_, pair.first, std::move(data_map),
register_new_map_callback_);
}
@@ -79,7 +79,6 @@ void SessionStorageNamespaceImplMojo::PopulateAsClone(
void SessionStorageNamespaceImplMojo::Reset() {
namespace_entry_ = SessionStorageMetadata::NamespaceEntry();
- process_id_ = ChildProcessHost::kInvalidUniqueID;
database_ = nullptr;
waiting_on_clone_population_ = false;
bind_waiting_on_clone_population_ = false;
@@ -90,7 +89,7 @@ void SessionStorageNamespaceImplMojo::Reset() {
}
void SessionStorageNamespaceImplMojo::Bind(
- mojom::SessionStorageNamespaceRequest request,
+ blink::mojom::SessionStorageNamespaceRequest request,
int process_id) {
if (waiting_on_clone_population_) {
bind_waiting_on_clone_population_ = true;
@@ -100,16 +99,17 @@ void SessionStorageNamespaceImplMojo::Bind(
return;
}
DCHECK(IsPopulated());
- process_id_ = process_id;
- bindings_.AddBinding(this, std::move(request));
+ bindings_.AddBinding(this, std::move(request), process_id);
bind_waiting_on_clone_population_ = false;
}
-void SessionStorageNamespaceImplMojo::PurgeUnboundWrappers() {
+void SessionStorageNamespaceImplMojo::PurgeUnboundAreas() {
auto it = origin_areas_.begin();
while (it != origin_areas_.end()) {
if (!it->second->IsBound())
it = origin_areas_.erase(it);
+ else
+ ++it;
}
}
@@ -128,32 +128,40 @@ void SessionStorageNamespaceImplMojo::RemoveOriginData(
// Renderer process expects |source| to always be two newline separated
// strings.
it->second->DeleteAll("\n", base::DoNothing());
- it->second->data_map()->level_db_wrapper()->ScheduleImmediateCommit();
+ it->second->NotifyObserversAllDeleted();
+ it->second->data_map()->storage_area()->ScheduleImmediateCommit();
}
void SessionStorageNamespaceImplMojo::OpenArea(
const url::Origin& origin,
- mojom::LevelDBWrapperAssociatedRequest database) {
+ blink::mojom::StorageAreaAssociatedRequest database) {
DCHECK(IsPopulated());
DCHECK(!bindings_.empty());
- DCHECK_NE(process_id_, ChildProcessHost::kInvalidUniqueID);
+ int process_id = bindings_.dispatch_context();
if (!ChildProcessSecurityPolicy::GetInstance()->CanAccessDataForOrigin(
- process_id_, origin.GetURL())) {
+ process_id, origin.GetURL())) {
bindings_.ReportBadMessage("Access denied for sessionStorage request");
return;
}
auto it = origin_areas_.find(origin);
if (it == origin_areas_.end()) {
+ scoped_refptr<SessionStorageMetadata::MapData> map_data;
+ // The area may have been purged due to lack of bindings, so check the
+ // metadata for the map.
+ auto map_it = namespace_entry_->second.find(origin);
+ if (map_it != namespace_entry_->second.end()) {
+ map_data = map_it->second;
+ } else {
+ map_data = register_new_map_callback_.Run(namespace_entry_, origin);
+ }
it = origin_areas_
.emplace(std::make_pair(
- origin, std::make_unique<SessionStorageLevelDBWrapper>(
- namespace_entry_, origin,
- SessionStorageDataMap::Create(
- data_map_listener_,
- register_new_map_callback_.Run(
- namespace_entry_, origin),
- database_),
- register_new_map_callback_)))
+ origin,
+ std::make_unique<SessionStorageAreaImpl>(
+ namespace_entry_, origin,
+ SessionStorageDataMap::Create(
+ data_map_listener_, std::move(map_data), database_),
+ register_new_map_callback_)))
.first;
}
it->second->Bind(std::move(database));
@@ -172,7 +180,7 @@ void SessionStorageNamespaceImplMojo::FlushOriginForTesting(
auto it = origin_areas_.find(origin);
if (it == origin_areas_.end())
return;
- it->second->data_map()->level_db_wrapper()->ScheduleImmediateCommit();
+ it->second->data_map()->storage_area()->ScheduleImmediateCommit();
}
} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
index 5936c469fc7..eb70ad8dde2 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
@@ -8,22 +8,21 @@
#include "base/callback.h"
#include "base/containers/flat_map.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
+#include "content/browser/dom_storage/session_storage_area_impl.h"
#include "content/browser/dom_storage/session_storage_data_map.h"
-#include "content/browser/dom_storage/session_storage_leveldb_wrapper.h"
#include "content/browser/dom_storage/session_storage_metadata.h"
-#include "content/common/leveldb_wrapper.mojom.h"
-#include "content/common/storage_partition_service.mojom.h"
-#include "content/public/common/child_process_host.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "third_party/blink/public/mojom/dom_storage/session_storage_namespace.mojom.h"
#include "url/origin.h"
namespace content {
// Implements the mojo interface SessionStorageNamespace. Stores data maps per
-// origin, which are accessible using the LevelDBWrapper interface with the
+// origin, which are accessible using the StorageArea interface with the
// |OpenArea| call. Supports cloning (shallow cloning with copy-on-write
// behavior) from another SessionStorageNamespaceImplMojo.
//
@@ -46,10 +45,10 @@ namespace content {
// create the cloned namespace and expect to manage it's lifetime that way, and
// this can happen before the first case, as they are on different task runners.
class CONTENT_EXPORT SessionStorageNamespaceImplMojo final
- : public mojom::SessionStorageNamespace {
+ : public blink::mojom::SessionStorageNamespace {
public:
using OriginAreas =
- std::map<url::Origin, std::unique_ptr<SessionStorageLevelDBWrapper>>;
+ std::map<url::Origin, std::unique_ptr<SessionStorageAreaImpl>>;
using RegisterShallowClonedNamespace = base::RepeatingCallback<void(
SessionStorageMetadata::NamespaceEntry source_namespace,
const std::string& destination_namespace,
@@ -60,14 +59,13 @@ class CONTENT_EXPORT SessionStorageNamespaceImplMojo final
// |data_map_listener| are given to any data maps constructed for this
// namespace. The |add_namespace_callback| is called when the |Clone| method
// is called by mojo. The |register_new_map_callback| is given to the the
- // SessionStorageLevelDBWrapper's, used per-origin, that are bound to in
+ // SessionStorageAreaImpl's, used per-origin, that are bound to in
// OpenArea.
SessionStorageNamespaceImplMojo(
std::string namespace_id,
SessionStorageDataMap::Listener* data_map_listener,
RegisterShallowClonedNamespace add_namespace_callback,
- SessionStorageLevelDBWrapper::RegisterNewAreaMap
- register_new_map_callback);
+ SessionStorageAreaImpl::RegisterNewAreaMap register_new_map_callback);
~SessionStorageNamespaceImplMojo() override;
@@ -108,17 +106,19 @@ class CONTENT_EXPORT SessionStorageNamespaceImplMojo final
// |SetWaitingForClonePopulation|. For the later case, |PopulateAsClone| must
// eventually be called before the SessionStorageNamespaceRequest can be
// bound.
- void Bind(mojom::SessionStorageNamespaceRequest request, int process_id);
+ void Bind(blink::mojom::SessionStorageNamespaceRequest request,
+ int process_id);
bool IsBound() const {
return !bindings_.empty() || bind_waiting_on_clone_population_;
}
- // Removes any LevelDBWrappers bound in |OpenArea| that are no longer bound.
- void PurgeUnboundWrappers();
+ // Removes any StorageAreas bound in |OpenArea| that are no longer bound.
+ void PurgeUnboundAreas();
// Removes data for the given origin from this namespace. If there is no data
- // map for that given origin, this does nothing.
+ // map for that given origin, this does nothing. Expects that this namespace
+ // is either populated or waiting for clone population.
void RemoveOriginData(const url::Origin& origin);
// SessionStorageNamespace:
@@ -126,7 +126,7 @@ class CONTENT_EXPORT SessionStorageNamespaceImplMojo final
// origin. Before connection, it checks to make sure the |process_id| given to
// the |Bind| method can access the given origin.
void OpenArea(const url::Origin& origin,
- mojom::LevelDBWrapperAssociatedRequest database) override;
+ blink::mojom::StorageAreaAssociatedRequest database) override;
// Simply calls the |add_namespace_callback_| callback with this namespace's
// data.
@@ -135,14 +135,16 @@ class CONTENT_EXPORT SessionStorageNamespaceImplMojo final
void FlushOriginForTesting(const url::Origin& origin);
private:
+ FRIEND_TEST_ALL_PREFIXES(SessionStorageContextMojoTest,
+ PurgeMemoryDoesNotCrashOrHang);
+
const std::string namespace_id_;
SessionStorageMetadata::NamespaceEntry namespace_entry_;
- int process_id_ = ChildProcessHost::kInvalidUniqueID;
leveldb::mojom::LevelDBDatabase* database_;
SessionStorageDataMap::Listener* data_map_listener_;
RegisterShallowClonedNamespace add_namespace_callback_;
- SessionStorageLevelDBWrapper::RegisterNewAreaMap register_new_map_callback_;
+ SessionStorageAreaImpl::RegisterNewAreaMap register_new_map_callback_;
bool waiting_on_clone_population_ = false;
bool bind_waiting_on_clone_population_ = false;
@@ -150,7 +152,8 @@ class CONTENT_EXPORT SessionStorageNamespaceImplMojo final
bool populated_ = false;
OriginAreas origin_areas_;
- mojo::BindingSet<mojom::SessionStorageNamespace> bindings_;
+ // The context is the process id.
+ mojo::BindingSet<blink::mojom::SessionStorageNamespace, int> bindings_;
};
} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
index 7ee00233e60..b813634fcf5 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
@@ -7,14 +7,15 @@
#include "base/guid.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
#include "components/services/leveldb/public/cpp/util.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/dom_storage/session_storage_data_map.h"
#include "content/browser/dom_storage/session_storage_metadata.h"
+#include "content/browser/dom_storage/test/storage_area_test_util.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/fake_leveldb_database.h"
-#include "content/test/leveldb_wrapper_test_util.h"
-#include "mojo/edk/embedder/embedder.h"
+#include "content/test/gmock_util.h"
+#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -77,7 +78,7 @@ class SessionStorageNamespaceImplMojoTest : public testing::Test {
security_policy->LockToOrigin(kTestProcessIdOrigin3,
test_origin3_.GetURL());
- mojo::edk::SetDefaultProcessErrorCallback(
+ mojo::core::SetDefaultProcessErrorCallback(
base::BindRepeating(&SessionStorageNamespaceImplMojoTest::OnBadMessage,
base::Unretained(this)));
}
@@ -90,8 +91,8 @@ class SessionStorageNamespaceImplMojoTest : public testing::Test {
security_policy->Remove(kTestProcessIdAllOrigins);
security_policy->Remove(kTestProcessIdOrigin3);
- mojo::edk::SetDefaultProcessErrorCallback(
- mojo::edk::ProcessErrorCallback());
+ mojo::core::SetDefaultProcessErrorCallback(
+ mojo::core::ProcessErrorCallback());
}
// Creates a SessionStorageNamespaceImplMojo, saves it in the namespaces_ map,
@@ -104,7 +105,7 @@ class SessionStorageNamespaceImplMojoTest : public testing::Test {
base::BindRepeating(&SessionStorageNamespaceImplMojoTest::
RegisterShallowClonedNamespace,
base::Unretained(this));
- SessionStorageLevelDBWrapper::RegisterNewAreaMap map_id_callback =
+ SessionStorageAreaImpl::RegisterNewAreaMap map_id_callback =
base::BindRepeating(
&SessionStorageNamespaceImplMojoTest::RegisterNewAreaMap,
base::Unretained(this));
@@ -150,7 +151,7 @@ class SessionStorageNamespaceImplMojoTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment task_environment_;
+ TestBrowserThreadBundle test_browser_thread_bundle_;
const std::string test_namespace_id1_;
const std::string test_namespace_id2_;
const url::Origin test_origin1_;
@@ -180,19 +181,18 @@ TEST_F(SessionStorageNamespaceImplMojoTest, MetadataLoad) {
&database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
- mojom::SessionStorageNamespacePtr ss_namespace;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace;
namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
- mojom::LevelDBWrapperAssociatedPtr leveldb_1;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_1;
ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(leveldb_1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_1.get(), &data));
EXPECT_EQ(1ul, data.size());
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
- StdStringToUint8Vector("data1"))));
+ data, blink::mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
.Times(1);
@@ -213,26 +213,25 @@ TEST_F(SessionStorageNamespaceImplMojoTest, MetadataLoadWithMapOperations) {
&database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
- mojom::SessionStorageNamespacePtr ss_namespace;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace;
namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
- mojom::LevelDBWrapperAssociatedPtr leveldb_1;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_1;
ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK)).Times(1);
test::PutSync(leveldb_1.get(), StdStringToUint8Vector("key2"),
StdStringToUint8Vector("data2"), base::nullopt, "");
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(leveldb_1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_1.get(), &data));
EXPECT_EQ(2ul, data.size());
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
- StdStringToUint8Vector("data1"))));
+ data, blink::mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(StdStringToUint8Vector("key2"),
- StdStringToUint8Vector("data2"))));
+ data, blink::mojom::KeyValue::New(StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"))));
EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
.Times(1);
@@ -254,7 +253,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, CloneBeforeBind) {
&database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
- mojom::SessionStorageNamespacePtr ss_namespace1;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
namespace_impl1->Bind(mojo::MakeRequest(&ss_namespace1),
kTestProcessIdOrigin1);
ss_namespace1->Clone(test_namespace_id2_);
@@ -262,10 +261,10 @@ TEST_F(SessionStorageNamespaceImplMojoTest, CloneBeforeBind) {
ASSERT_TRUE(namespace_impl2->IsPopulated());
- mojom::SessionStorageNamespacePtr ss_namespace2;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace2;
namespace_impl2->Bind(mojo::MakeRequest(&ss_namespace2),
kTestProcessIdOrigin1);
- mojom::LevelDBWrapperAssociatedPtr leveldb_2;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_2;
ss_namespace2->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_2));
// Do a put in the cloned namespace.
@@ -276,16 +275,15 @@ TEST_F(SessionStorageNamespaceImplMojoTest, CloneBeforeBind) {
test::PutSync(leveldb_2.get(), StdStringToUint8Vector("key2"),
StdStringToUint8Vector("data2"), base::nullopt, "");
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(leveldb_2.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_2.get(), &data));
EXPECT_EQ(2ul, data.size());
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
- StdStringToUint8Vector("data1"))));
+ data, blink::mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(StdStringToUint8Vector("key2"),
- StdStringToUint8Vector("data2"))));
+ data, blink::mojom::KeyValue::New(StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"))));
EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
.Times(1);
@@ -311,7 +309,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, CloneAfterBind) {
&database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
- mojom::SessionStorageNamespacePtr ss_namespace1;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace1;
namespace_impl1->Bind(mojo::MakeRequest(&ss_namespace1),
kTestProcessIdOrigin1);
@@ -322,11 +320,11 @@ TEST_F(SessionStorageNamespaceImplMojoTest, CloneAfterBind) {
OnDataMapCreation(StdStringToUint8Vector("1"), testing::_))
.Times(1);
// Get a new area.
- mojom::SessionStorageNamespacePtr ss_namespace2;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace2;
namespace_impl2->Bind(mojo::MakeRequest(&ss_namespace2),
kTestProcessIdAllOrigins);
- mojom::LevelDBWrapperAssociatedPtr leveldb_n2_o1;
- mojom::LevelDBWrapperAssociatedPtr leveldb_n2_o2;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o2;
ss_namespace2->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_n2_o1));
ss_namespace2->OpenArea(test_origin2_, mojo::MakeRequest(&leveldb_n2_o2));
@@ -341,21 +339,19 @@ TEST_F(SessionStorageNamespaceImplMojoTest, CloneAfterBind) {
test::PutSync(leveldb_n2_o2.get(), StdStringToUint8Vector("key2"),
StdStringToUint8Vector("data2"), base::nullopt, "");
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(leveldb_n2_o1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_n2_o1.get(), &data));
EXPECT_EQ(1ul, data.size());
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
- StdStringToUint8Vector("data1"))));
+ data, blink::mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
data.clear();
- status = test::GetAllSync(leveldb_n2_o2.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_TRUE(test::GetAllSync(leveldb_n2_o2.get(), &data));
EXPECT_EQ(1ul, data.size());
EXPECT_TRUE(base::ContainsValue(
- data, mojom::KeyValue::New(StdStringToUint8Vector("key2"),
- StdStringToUint8Vector("data2"))));
+ data, blink::mojom::KeyValue::New(StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"))));
EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
.Times(1);
@@ -376,21 +372,59 @@ TEST_F(SessionStorageNamespaceImplMojoTest, RemoveOriginData) {
&database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
- mojom::SessionStorageNamespacePtr ss_namespace;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace;
namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
- mojom::LevelDBWrapperAssociatedPtr leveldb_1;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_1;
ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
ss_namespace.FlushForTesting();
+ // Create an observer to make sure the deletion is observed.
+ testing::StrictMock<test::MockLevelDBObserver> mock_observer;
+ mojo::AssociatedBinding<blink::mojom::StorageAreaObserver> observer_binding(
+ &mock_observer);
+ blink::mojom::StorageAreaObserverAssociatedPtrInfo observer_ptr_info;
+ observer_binding.Bind(mojo::MakeRequest(&observer_ptr_info));
+ leveldb_1->AddObserver(std::move(observer_ptr_info));
+ leveldb_1.FlushForTesting();
+
+ base::RunLoop loop;
+ EXPECT_CALL(mock_observer, AllDeleted("\n"))
+ .WillOnce(base::test::RunClosure(loop.QuitClosure()));
+
EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK)).Times(1);
namespace_impl->RemoveOriginData(test_origin1_);
- std::vector<mojom::KeyValuePtr> data;
- DatabaseError status = test::GetAllSync(leveldb_1.get(), &data);
- EXPECT_EQ(DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(leveldb_1.get(), &data));
EXPECT_EQ(0ul, data.size());
+ // Check that the observer was notified.
+ loop.Run();
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ namespaces_.clear();
+}
+
+TEST_F(SessionStorageNamespaceImplMojoTest, RemoveOriginDataWithoutBinding) {
+ SessionStorageNamespaceImplMojo* namespace_impl =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id1_);
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ namespace_impl->PopulateFromMetadata(
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+
+ base::RunLoop loop;
+ EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK))
+ .WillOnce(base::test::RunClosure(loop.QuitClosure()));
+ namespace_impl->RemoveOriginData(test_origin1_);
+ loop.Run();
+
EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
.Times(1);
namespaces_.clear();
@@ -410,9 +444,9 @@ TEST_F(SessionStorageNamespaceImplMojoTest, ProcessLockedToOtherOrigin) {
&database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
- mojom::SessionStorageNamespacePtr ss_namespace;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace;
namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
- mojom::LevelDBWrapperAssociatedPtr leveldb_1;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_1;
ss_namespace->OpenArea(test_origin3_, mojo::MakeRequest(&leveldb_1));
ss_namespace.FlushForTesting();
EXPECT_TRUE(bad_message_called_);
@@ -423,7 +457,7 @@ TEST_F(SessionStorageNamespaceImplMojoTest, ProcessLockedToOtherOrigin) {
}
TEST_F(SessionStorageNamespaceImplMojoTest, PurgeUnused) {
- // Verifies that wrappers are kept alive after the area is unbound, and they
+ // Verifies that areas are kept alive after the area is unbound, and they
// are removed when PurgeUnboundWrappers() is called.
SessionStorageNamespaceImplMojo* namespace_impl =
CreateSessionStorageNamespaceImplMojo(test_namespace_id1_);
@@ -436,10 +470,10 @@ TEST_F(SessionStorageNamespaceImplMojoTest, PurgeUnused) {
&database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
- mojom::SessionStorageNamespacePtr ss_namespace;
+ blink::mojom::SessionStorageNamespacePtr ss_namespace;
namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
- mojom::LevelDBWrapperAssociatedPtr leveldb_1;
+ blink::mojom::StorageAreaAssociatedPtr leveldb_1;
ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
EXPECT_TRUE(namespace_impl->HasAreaForOrigin(test_origin1_));
@@ -448,11 +482,52 @@ TEST_F(SessionStorageNamespaceImplMojoTest, PurgeUnused) {
leveldb_1.reset();
EXPECT_TRUE(namespace_impl->HasAreaForOrigin(test_origin1_));
- namespace_impl->PurgeUnboundWrappers();
+ namespace_impl->PurgeUnboundAreas();
EXPECT_FALSE(namespace_impl->HasAreaForOrigin(test_origin1_));
namespaces_.clear();
}
+TEST_F(SessionStorageNamespaceImplMojoTest, NamespaceBindingPerOrigin) {
+ // Tries to open an area with a process that is locked to a different origin
+ // and verifies the bad message callback.
+ SessionStorageNamespaceImplMojo* namespace_impl =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id1_);
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ namespace_impl->PopulateFromMetadata(
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+
+ blink::mojom::SessionStorageNamespacePtr ss_namespace_o1;
+ namespace_impl->Bind(mojo::MakeRequest(&ss_namespace_o1),
+ kTestProcessIdOrigin1);
+ blink::mojom::StorageAreaAssociatedPtr leveldb_1;
+ ss_namespace_o1->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
+ ss_namespace_o1.FlushForTesting();
+ EXPECT_FALSE(bad_message_called_);
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("1"), testing::_))
+ .Times(1);
+
+ blink::mojom::SessionStorageNamespacePtr ss_namespace_o2;
+ namespace_impl->Bind(mojo::MakeRequest(&ss_namespace_o2),
+ kTestProcessIdOrigin3);
+ blink::mojom::StorageAreaAssociatedPtr leveldb_2;
+ ss_namespace_o2->OpenArea(test_origin3_, mojo::MakeRequest(&leveldb_2));
+ ss_namespace_o2.FlushForTesting();
+ EXPECT_FALSE(bad_message_called_);
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("1")))
+ .Times(1);
+ namespaces_.clear();
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/leveldb_wrapper_impl.cc b/chromium/content/browser/dom_storage/storage_area_impl.cc
index d3c5c994d71..63930ec6b94 100644
--- a/chromium/content/browser/leveldb_wrapper_impl.cc
+++ b/chromium/content/browser/dom_storage/storage_area_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/leveldb_wrapper_impl.h"
+#include "content/browser/dom_storage/storage_area_impl.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -20,33 +20,33 @@ using leveldb::mojom::BatchedOperationPtr;
using leveldb::mojom::DatabaseError;
} // namespace
-LevelDBWrapperImpl::Delegate::~Delegate() {}
+StorageAreaImpl::Delegate::~Delegate() {}
-void LevelDBWrapperImpl::Delegate::MigrateData(
+void StorageAreaImpl::Delegate::MigrateData(
base::OnceCallback<void(std::unique_ptr<ValueMap>)> callback) {
std::move(callback).Run(nullptr);
}
-std::vector<LevelDBWrapperImpl::Change> LevelDBWrapperImpl::Delegate::FixUpData(
+std::vector<StorageAreaImpl::Change> StorageAreaImpl::Delegate::FixUpData(
const ValueMap& data) {
return std::vector<Change>();
}
-void LevelDBWrapperImpl::Delegate::OnMapLoaded(DatabaseError) {}
+void StorageAreaImpl::Delegate::OnMapLoaded(DatabaseError) {}
-bool LevelDBWrapperImpl::s_aggressive_flushing_enabled_ = false;
+bool StorageAreaImpl::s_aggressive_flushing_enabled_ = false;
-LevelDBWrapperImpl::RateLimiter::RateLimiter(size_t desired_rate,
- base::TimeDelta time_quantum)
+StorageAreaImpl::RateLimiter::RateLimiter(size_t desired_rate,
+ base::TimeDelta time_quantum)
: rate_(desired_rate), samples_(0), time_quantum_(time_quantum) {
DCHECK_GT(desired_rate, 0ul);
}
-base::TimeDelta LevelDBWrapperImpl::RateLimiter::ComputeTimeNeeded() const {
+base::TimeDelta StorageAreaImpl::RateLimiter::ComputeTimeNeeded() const {
return time_quantum_ * (samples_ / rate_);
}
-base::TimeDelta LevelDBWrapperImpl::RateLimiter::ComputeDelayNeeded(
+base::TimeDelta StorageAreaImpl::RateLimiter::ComputeDelayNeeded(
const base::TimeDelta elapsed_time) const {
base::TimeDelta time_needed = ComputeTimeNeeded();
if (time_needed > elapsed_time)
@@ -54,24 +54,22 @@ base::TimeDelta LevelDBWrapperImpl::RateLimiter::ComputeDelayNeeded(
return base::TimeDelta();
}
-LevelDBWrapperImpl::CommitBatch::CommitBatch() : clear_all_first(false) {}
-LevelDBWrapperImpl::CommitBatch::~CommitBatch() {}
+StorageAreaImpl::CommitBatch::CommitBatch() : clear_all_first(false) {}
+StorageAreaImpl::CommitBatch::~CommitBatch() {}
-LevelDBWrapperImpl::LevelDBWrapperImpl(
- leveldb::mojom::LevelDBDatabase* database,
- const std::string& prefix,
- Delegate* delegate,
- const Options& options)
- : LevelDBWrapperImpl(database,
- leveldb::StdStringToUint8Vector(prefix),
- delegate,
- options) {}
-
-LevelDBWrapperImpl::LevelDBWrapperImpl(
- leveldb::mojom::LevelDBDatabase* database,
- std::vector<uint8_t> prefix,
- Delegate* delegate,
- const Options& options)
+StorageAreaImpl::StorageAreaImpl(leveldb::mojom::LevelDBDatabase* database,
+ const std::string& prefix,
+ Delegate* delegate,
+ const Options& options)
+ : StorageAreaImpl(database,
+ leveldb::StdStringToUint8Vector(prefix),
+ delegate,
+ options) {}
+
+StorageAreaImpl::StorageAreaImpl(leveldb::mojom::LevelDBDatabase* database,
+ std::vector<uint8_t> prefix,
+ Delegate* delegate,
+ const Options& options)
: prefix_(std::move(prefix)),
delegate_(delegate),
database_(database),
@@ -86,17 +84,17 @@ LevelDBWrapperImpl::LevelDBWrapperImpl(
commit_rate_limiter_(options.max_commits_per_hour,
base::TimeDelta::FromHours(1)),
weak_ptr_factory_(this) {
- bindings_.set_connection_error_handler(base::Bind(
- &LevelDBWrapperImpl::OnConnectionError, base::Unretained(this)));
+ bindings_.set_connection_error_handler(
+ base::Bind(&StorageAreaImpl::OnConnectionError, base::Unretained(this)));
}
-LevelDBWrapperImpl::~LevelDBWrapperImpl() {
+StorageAreaImpl::~StorageAreaImpl() {
DCHECK(!has_pending_load_tasks());
if (commit_batch_)
CommitChanges();
}
-void LevelDBWrapperImpl::Bind(mojom::LevelDBWrapperRequest request) {
+void StorageAreaImpl::Bind(blink::mojom::StorageAreaRequest request) {
bindings_.AddBinding(this, std::move(request));
// If the number of bindings is more than 1, then the |client_old_value| sent
// by the clients need not be valid due to races on updates from multiple
@@ -106,11 +104,11 @@ void LevelDBWrapperImpl::Bind(mojom::LevelDBWrapperRequest request) {
// reaching late.
if (cache_mode_ == CacheMode::KEYS_ONLY_WHEN_POSSIBLE &&
bindings_.size() > 1) {
- SetCacheMode(LevelDBWrapperImpl::CacheMode::KEYS_AND_VALUES);
+ SetCacheMode(CacheMode::KEYS_AND_VALUES);
}
}
-std::unique_ptr<LevelDBWrapperImpl> LevelDBWrapperImpl::ForkToNewPrefix(
+std::unique_ptr<StorageAreaImpl> StorageAreaImpl::ForkToNewPrefix(
const std::string& new_prefix,
Delegate* delegate,
const Options& options) {
@@ -118,36 +116,36 @@ std::unique_ptr<LevelDBWrapperImpl> LevelDBWrapperImpl::ForkToNewPrefix(
options);
}
-std::unique_ptr<LevelDBWrapperImpl> LevelDBWrapperImpl::ForkToNewPrefix(
+std::unique_ptr<StorageAreaImpl> StorageAreaImpl::ForkToNewPrefix(
std::vector<uint8_t> new_prefix,
Delegate* delegate,
const Options& options) {
- auto forked_wrapper = std::make_unique<LevelDBWrapperImpl>(
+ auto forked_area = std::make_unique<StorageAreaImpl>(
database_, std::move(new_prefix), delegate, options);
- forked_wrapper->map_state_ = MapState::LOADING_FROM_FORK;
+ forked_area->map_state_ = MapState::LOADING_FROM_FORK;
if (IsMapLoaded()) {
- DoForkOperation(forked_wrapper->weak_ptr_factory_.GetWeakPtr());
+ DoForkOperation(forked_area->weak_ptr_factory_.GetWeakPtr());
} else {
- LoadMap(base::BindOnce(&LevelDBWrapperImpl::DoForkOperation,
+ LoadMap(base::BindOnce(&StorageAreaImpl::DoForkOperation,
weak_ptr_factory_.GetWeakPtr(),
- forked_wrapper->weak_ptr_factory_.GetWeakPtr()));
+ forked_area->weak_ptr_factory_.GetWeakPtr()));
}
- return forked_wrapper;
+ return forked_area;
}
-void LevelDBWrapperImpl::CancelAllPendingRequests() {
+void StorageAreaImpl::CancelAllPendingRequests() {
on_load_complete_tasks_.clear();
}
-void LevelDBWrapperImpl::EnableAggressiveCommitDelay() {
+void StorageAreaImpl::EnableAggressiveCommitDelay() {
s_aggressive_flushing_enabled_ = true;
}
-void LevelDBWrapperImpl::ScheduleImmediateCommit() {
+void StorageAreaImpl::ScheduleImmediateCommit() {
if (!on_load_complete_tasks_.empty()) {
- LoadMap(base::BindOnce(&LevelDBWrapperImpl::ScheduleImmediateCommit,
+ LoadMap(base::BindOnce(&StorageAreaImpl::ScheduleImmediateCommit,
base::Unretained(this)));
return;
}
@@ -157,9 +155,8 @@ void LevelDBWrapperImpl::ScheduleImmediateCommit() {
CommitChanges();
}
-void LevelDBWrapperImpl::OnMemoryDump(
- const std::string& name,
- base::trace_event::ProcessMemoryDump* pmd) {
+void StorageAreaImpl::OnMemoryDump(const std::string& name,
+ base::trace_event::ProcessMemoryDump* pmd) {
if (!IsMapLoaded())
return;
@@ -197,7 +194,7 @@ void LevelDBWrapperImpl::OnMemoryDump(
pmd->AddSuballocation(map_mad->guid(), system_allocator_name);
}
-void LevelDBWrapperImpl::PurgeMemory() {
+void StorageAreaImpl::PurgeMemory() {
if (!IsMapLoaded() || // We're not using any memory.
commit_batch_ || // We leave things alone with changes pending.
!database_) { // Don't purge anything if we're not backed by a database.
@@ -205,44 +202,46 @@ void LevelDBWrapperImpl::PurgeMemory() {
}
map_state_ = MapState::UNLOADED;
+ memory_used_ = 0;
keys_only_map_.clear();
keys_values_map_.clear();
}
-void LevelDBWrapperImpl::SetCacheModeForTesting(CacheMode cache_mode) {
+void StorageAreaImpl::SetCacheModeForTesting(CacheMode cache_mode) {
SetCacheMode(cache_mode);
}
-mojo::InterfacePtrSetElementId LevelDBWrapperImpl::AddObserver(
- mojom::LevelDBObserverAssociatedPtr observer) {
+mojo::InterfacePtrSetElementId StorageAreaImpl::AddObserver(
+ blink::mojom::StorageAreaObserverAssociatedPtr observer) {
if (cache_mode_ == CacheMode::KEYS_AND_VALUES)
observer->ShouldSendOldValueOnMutations(false);
return observers_.AddPtr(std::move(observer));
}
-bool LevelDBWrapperImpl::HasObserver(mojo::InterfacePtrSetElementId id) {
+bool StorageAreaImpl::HasObserver(mojo::InterfacePtrSetElementId id) {
return observers_.HasPtr(id);
}
-mojom::LevelDBObserverAssociatedPtr LevelDBWrapperImpl::RemoveObserver(
+blink::mojom::StorageAreaObserverAssociatedPtr StorageAreaImpl::RemoveObserver(
mojo::InterfacePtrSetElementId id) {
return observers_.RemovePtr(id);
}
-void LevelDBWrapperImpl::AddObserver(
- mojom::LevelDBObserverAssociatedPtrInfo observer) {
- AddObserver(mojom::LevelDBObserverAssociatedPtr(std::move(observer)));
+void StorageAreaImpl::AddObserver(
+ blink::mojom::StorageAreaObserverAssociatedPtrInfo observer) {
+ AddObserver(
+ blink::mojom::StorageAreaObserverAssociatedPtr(std::move(observer)));
}
-void LevelDBWrapperImpl::Put(
+void StorageAreaImpl::Put(
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
const base::Optional<std::vector<uint8_t>>& client_old_value,
const std::string& source,
PutCallback callback) {
if (!IsMapLoaded() || IsMapUpgradeNeeded()) {
- LoadMap(base::BindOnce(&LevelDBWrapperImpl::Put, base::Unretained(this),
- key, value, client_old_value, source,
+ LoadMap(base::BindOnce(&StorageAreaImpl::Put, base::Unretained(this), key,
+ value, client_old_value, source,
std::move(callback)));
return;
}
@@ -268,7 +267,7 @@ void LevelDBWrapperImpl::Put(
// sent to clients will not contain old value. This is okay since
// currently the only observer to these notification is the client
// itself.
- DVLOG(1) << "Wrapper with prefix "
+ DVLOG(1) << "Storage area with prefix "
<< leveldb::Uint8VectorToStdString(prefix_)
<< ": past value has length of " << found->second << ", but:";
if (client_old_value) {
@@ -335,20 +334,20 @@ void LevelDBWrapperImpl::Put(
if (!old_value) {
// We added a new key/value pair.
observers_.ForAllPtrs(
- [&key, &value, &source](mojom::LevelDBObserver* observer) {
+ [&key, &value, &source](blink::mojom::StorageAreaObserver* observer) {
observer->KeyAdded(key, value, source);
});
} else {
// We changed the value for an existing key.
- observers_.ForAllPtrs(
- [&key, &value, &source, &old_value](mojom::LevelDBObserver* observer) {
- observer->KeyChanged(key, value, old_value.value(), source);
- });
+ observers_.ForAllPtrs([&key, &value, &source, &old_value](
+ blink::mojom::StorageAreaObserver* observer) {
+ observer->KeyChanged(key, value, old_value.value(), source);
+ });
}
std::move(callback).Run(true);
}
-void LevelDBWrapperImpl::Delete(
+void StorageAreaImpl::Delete(
const std::vector<uint8_t>& key,
const base::Optional<std::vector<uint8_t>>& client_old_value,
const std::string& source,
@@ -358,7 +357,7 @@ void LevelDBWrapperImpl::Delete(
// |client_old_value| can race. Thus any changes require checking for an
// upgrade.
if (!IsMapLoaded() || IsMapUpgradeNeeded()) {
- LoadMap(base::BindOnce(&LevelDBWrapperImpl::Delete, base::Unretained(this),
+ LoadMap(base::BindOnce(&StorageAreaImpl::Delete, base::Unretained(this),
key, client_old_value, source, std::move(callback)));
return;
}
@@ -381,7 +380,7 @@ void LevelDBWrapperImpl::Delete(
// then we still let the change go through. But the notification sent to
// clients will not contain old value. This is okay since currently the
// only observer to these notification is the client itself.
- DVLOG(1) << "Wrapper with prefix "
+ DVLOG(1) << "Storage area with prefix "
<< leveldb::Uint8VectorToStdString(prefix_)
<< ": past value has length of " << found->second << ", but:";
if (client_old_value) {
@@ -413,20 +412,19 @@ void LevelDBWrapperImpl::Delete(
}
observers_.ForAllPtrs(
- [&key, &source, &old_value](mojom::LevelDBObserver* observer) {
+ [&key, &source, &old_value](blink::mojom::StorageAreaObserver* observer) {
observer->KeyDeleted(key, old_value, source);
});
std::move(callback).Run(true);
}
-void LevelDBWrapperImpl::DeleteAll(const std::string& source,
- DeleteAllCallback callback) {
+void StorageAreaImpl::DeleteAll(const std::string& source,
+ DeleteAllCallback callback) {
// Don't check if a map upgrade is needed here and instead just create an
// empty map ourself.
if (!IsMapLoaded()) {
- LoadMap(base::BindOnce(&LevelDBWrapperImpl::DeleteAll,
- base::Unretained(this), source,
- std::move(callback)));
+ LoadMap(base::BindOnce(&StorageAreaImpl::DeleteAll, base::Unretained(this),
+ source, std::move(callback)));
return;
}
@@ -455,15 +453,14 @@ void LevelDBWrapperImpl::DeleteAll(const std::string& source,
storage_used_ = 0;
memory_used_ = 0;
- observers_.ForAllPtrs(
- [&source](mojom::LevelDBObserver* observer) {
- observer->AllDeleted(source);
- });
+ observers_.ForAllPtrs([&source](blink::mojom::StorageAreaObserver* observer) {
+ observer->AllDeleted(source);
+ });
std::move(callback).Run(true);
}
-void LevelDBWrapperImpl::Get(const std::vector<uint8_t>& key,
- GetCallback callback) {
+void StorageAreaImpl::Get(const std::vector<uint8_t>& key,
+ GetCallback callback) {
// TODO(ssid): Remove this method since it is not supported in only keys mode,
// crbug.com/764127.
if (cache_mode_ == CacheMode::KEYS_ONLY_WHEN_POSSIBLE) {
@@ -471,8 +468,8 @@ void LevelDBWrapperImpl::Get(const std::vector<uint8_t>& key,
return;
}
if (!IsMapLoaded() || IsMapUpgradeNeeded()) {
- LoadMap(base::BindOnce(&LevelDBWrapperImpl::Get, base::Unretained(this),
- key, std::move(callback)));
+ LoadMap(base::BindOnce(&StorageAreaImpl::Get, base::Unretained(this), key,
+ std::move(callback)));
return;
}
@@ -484,41 +481,42 @@ void LevelDBWrapperImpl::Get(const std::vector<uint8_t>& key,
std::move(callback).Run(true, found->second);
}
-void LevelDBWrapperImpl::GetAll(
- mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo complete_callback,
+void StorageAreaImpl::GetAll(
+ blink::mojom::StorageAreaGetAllCallbackAssociatedPtrInfo complete_callback,
GetAllCallback callback) {
// The map must always be loaded for the KEYS_ONLY_WHEN_POSSIBLE mode.
if (map_state_ != MapState::LOADED_KEYS_AND_VALUES) {
- LoadMap(base::BindOnce(&LevelDBWrapperImpl::GetAll, base::Unretained(this),
+ LoadMap(base::BindOnce(&StorageAreaImpl::GetAll, base::Unretained(this),
std::move(complete_callback), std::move(callback)));
return;
}
- std::vector<mojom::KeyValuePtr> all;
+ std::vector<blink::mojom::KeyValuePtr> all;
for (const auto& it : keys_values_map_) {
- mojom::KeyValuePtr kv = mojom::KeyValue::New();
+ auto kv = blink::mojom::KeyValue::New();
kv->key = it.first;
kv->value = it.second;
all.push_back(std::move(kv));
}
- std::move(callback).Run(DatabaseError::OK, std::move(all));
+ std::move(callback).Run(true, std::move(all));
if (complete_callback.is_valid()) {
- mojom::LevelDBWrapperGetAllCallbackAssociatedPtr complete_ptr;
+ blink::mojom::StorageAreaGetAllCallbackAssociatedPtr complete_ptr;
complete_ptr.Bind(std::move(complete_callback));
complete_ptr->Complete(true);
}
}
-void LevelDBWrapperImpl::SetCacheMode(CacheMode cache_mode) {
+void StorageAreaImpl::SetCacheMode(CacheMode cache_mode) {
if (cache_mode_ == cache_mode ||
(!database_ && cache_mode == CacheMode::KEYS_ONLY_WHEN_POSSIBLE)) {
return;
}
cache_mode_ = cache_mode;
bool should_send_values = cache_mode == CacheMode::KEYS_ONLY_WHEN_POSSIBLE;
- observers_.ForAllPtrs([should_send_values](mojom::LevelDBObserver* observer) {
- observer->ShouldSendOldValueOnMutations(should_send_values);
- });
+ observers_.ForAllPtrs(
+ [should_send_values](blink::mojom::StorageAreaObserver* observer) {
+ observer->ShouldSendOldValueOnMutations(should_send_values);
+ });
// If the |keys_only_map_| is loaded and desired state needs values, no point
// keeping around the map since the next change would require reload. On the
@@ -527,7 +525,7 @@ void LevelDBWrapperImpl::SetCacheMode(CacheMode cache_mode) {
UnloadMapIfPossible();
}
-void LevelDBWrapperImpl::OnConnectionError() {
+void StorageAreaImpl::OnConnectionError() {
if (!bindings_.empty())
return;
// If any tasks are waiting for load to complete, delay calling the
@@ -537,7 +535,7 @@ void LevelDBWrapperImpl::OnConnectionError() {
delegate_->OnNoBindings();
}
-void LevelDBWrapperImpl::LoadMap(base::OnceClosure completion_callback) {
+void StorageAreaImpl::LoadMap(base::OnceClosure completion_callback) {
DCHECK_NE(map_state_, MapState::LOADED_KEYS_AND_VALUES);
DCHECK(keys_values_map_.empty());
@@ -551,7 +549,7 @@ void LevelDBWrapperImpl::LoadMap(base::OnceClosure completion_callback) {
if (commit_batch_)
CommitChanges();
// Make sure the keys only map is not used when on load tasks are in queue.
- // The changes to the wrapper will be queued to on load tasks.
+ // The changes to the area will be queued to on load tasks.
keys_only_map_.clear();
map_state_ = MapState::UNLOADED;
}
@@ -571,20 +569,19 @@ void LevelDBWrapperImpl::LoadMap(base::OnceClosure completion_callback) {
}
database_->GetPrefixed(prefix_,
- base::BindOnce(&LevelDBWrapperImpl::OnMapLoaded,
+ base::BindOnce(&StorageAreaImpl::OnMapLoaded,
weak_ptr_factory_.GetWeakPtr()));
}
-void LevelDBWrapperImpl::OnMapLoaded(
+void StorageAreaImpl::OnMapLoaded(
DatabaseError status,
std::vector<leveldb::mojom::KeyValuePtr> data) {
DCHECK(keys_values_map_.empty());
DCHECK_EQ(map_state_, MapState::LOADING_FROM_DATABASE);
if (data.empty() && status == DatabaseError::OK) {
- delegate_->MigrateData(
- base::BindOnce(&LevelDBWrapperImpl::OnGotMigrationData,
- weak_ptr_factory_.GetWeakPtr()));
+ delegate_->MigrateData(base::BindOnce(&StorageAreaImpl::OnGotMigrationData,
+ weak_ptr_factory_.GetWeakPtr()));
return;
}
keys_only_map_.clear();
@@ -635,7 +632,7 @@ void LevelDBWrapperImpl::OnMapLoaded(
OnLoadComplete();
}
-void LevelDBWrapperImpl::OnGotMigrationData(std::unique_ptr<ValueMap> data) {
+void StorageAreaImpl::OnGotMigrationData(std::unique_ptr<ValueMap> data) {
keys_only_map_.clear();
keys_values_map_ = data ? std::move(*data) : ValueMap();
map_state_ = MapState::LOADED_KEYS_AND_VALUES;
@@ -652,7 +649,7 @@ void LevelDBWrapperImpl::OnGotMigrationData(std::unique_ptr<ValueMap> data) {
OnLoadComplete();
}
-void LevelDBWrapperImpl::CalculateStorageAndMemoryUsed() {
+void StorageAreaImpl::CalculateStorageAndMemoryUsed() {
memory_used_ = 0;
storage_used_ = 0;
@@ -666,7 +663,7 @@ void LevelDBWrapperImpl::CalculateStorageAndMemoryUsed() {
}
}
-void LevelDBWrapperImpl::OnLoadComplete() {
+void StorageAreaImpl::OnLoadComplete() {
DCHECK(IsMapLoaded());
std::vector<base::OnceClosure> tasks;
@@ -695,7 +692,7 @@ void LevelDBWrapperImpl::OnLoadComplete() {
delegate_->OnNoBindings();
}
-void LevelDBWrapperImpl::CreateCommitBatchIfNeeded() {
+void StorageAreaImpl::CreateCommitBatchIfNeeded() {
if (commit_batch_)
return;
DCHECK(database_);
@@ -703,11 +700,11 @@ void LevelDBWrapperImpl::CreateCommitBatchIfNeeded() {
commit_batch_.reset(new CommitBatch());
BrowserThread::PostAfterStartupTask(
FROM_HERE, base::ThreadTaskRunnerHandle::Get(),
- base::BindOnce(&LevelDBWrapperImpl::StartCommitTimer,
+ base::BindOnce(&StorageAreaImpl::StartCommitTimer,
weak_ptr_factory_.GetWeakPtr()));
}
-void LevelDBWrapperImpl::StartCommitTimer() {
+void StorageAreaImpl::StartCommitTimer() {
if (!commit_batch_)
return;
@@ -719,25 +716,27 @@ void LevelDBWrapperImpl::StartCommitTimer() {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
- base::BindOnce(&LevelDBWrapperImpl::CommitChanges,
+ base::BindOnce(&StorageAreaImpl::CommitChanges,
weak_ptr_factory_.GetWeakPtr()),
ComputeCommitDelay());
}
-base::TimeDelta LevelDBWrapperImpl::ComputeCommitDelay() const {
+base::TimeDelta StorageAreaImpl::ComputeCommitDelay() const {
if (s_aggressive_flushing_enabled_)
return base::TimeDelta::FromSeconds(1);
base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time_;
- base::TimeDelta delay = std::max(
- default_commit_delay_,
- std::max(commit_rate_limiter_.ComputeDelayNeeded(elapsed_time),
- data_rate_limiter_.ComputeDelayNeeded(elapsed_time)));
+ base::TimeDelta delay =
+ std::max(default_commit_delay_,
+ std::max(commit_rate_limiter_.ComputeDelayNeeded(elapsed_time),
+ data_rate_limiter_.ComputeDelayNeeded(elapsed_time)));
+ // TODO(mek): Rename histogram to match class name, or eliminate histogram
+ // entirely.
UMA_HISTOGRAM_LONG_TIMES("LevelDBWrapper.CommitDelay", delay);
return delay;
}
-void LevelDBWrapperImpl::CommitChanges() {
+void StorageAreaImpl::CommitChanges() {
// Note: commit_batch_ may be null if ScheduleImmediateCommit was called
// after a delayed commit task was scheduled.
if (!commit_batch_)
@@ -821,11 +820,11 @@ void LevelDBWrapperImpl::CommitChanges() {
// TODO(michaeln): Currently there is no guarantee LevelDBDatabaseImpl::Write
// will run during a clean shutdown. We need that to avoid dataloss.
database_->Write(std::move(operations),
- base::BindOnce(&LevelDBWrapperImpl::OnCommitComplete,
+ base::BindOnce(&StorageAreaImpl::OnCommitComplete,
weak_ptr_factory_.GetWeakPtr()));
}
-void LevelDBWrapperImpl::OnCommitComplete(DatabaseError error) {
+void StorageAreaImpl::OnCommitComplete(DatabaseError error) {
has_committed_data_ = true;
--commit_batches_in_flight_;
StartCommitTimer();
@@ -840,7 +839,7 @@ void LevelDBWrapperImpl::OnCommitComplete(DatabaseError error) {
delegate_->DidCommit(error);
}
-void LevelDBWrapperImpl::UnloadMapIfPossible() {
+void StorageAreaImpl::UnloadMapIfPossible() {
// Do not unload the map if:
// * The desired cache mode isn't key-only,
// * The map isn't a loaded key-value map,
@@ -876,9 +875,9 @@ void LevelDBWrapperImpl::UnloadMapIfPossible() {
CalculateStorageAndMemoryUsed();
}
-void LevelDBWrapperImpl::DoForkOperation(
- const base::WeakPtr<LevelDBWrapperImpl>& forked_wrapper) {
- if (!forked_wrapper)
+void StorageAreaImpl::DoForkOperation(
+ const base::WeakPtr<StorageAreaImpl>& forked_area) {
+ if (!forked_area)
return;
DCHECK(IsMapLoaded());
@@ -890,17 +889,17 @@ void LevelDBWrapperImpl::DoForkOperation(
if (has_changes_to_commit())
CommitChanges();
CreateCommitBatchIfNeeded();
- commit_batch_->copy_to_prefix = forked_wrapper->prefix_;
+ commit_batch_->copy_to_prefix = forked_area->prefix_;
CommitChanges();
}
- forked_wrapper->OnForkStateLoaded(database_ != nullptr, keys_values_map_,
- keys_only_map_);
+ forked_area->OnForkStateLoaded(database_ != nullptr, keys_values_map_,
+ keys_only_map_);
}
-void LevelDBWrapperImpl::OnForkStateLoaded(bool database_enabled,
- const ValueMap& value_map,
- const KeysOnlyMap& keys_only_map) {
+void StorageAreaImpl::OnForkStateLoaded(bool database_enabled,
+ const ValueMap& value_map,
+ const KeysOnlyMap& keys_only_map) {
// This callback can get either the value map or the key only map depending
// on parent operations and other things. So handle both.
if (!value_map.empty() || keys_only_map.empty()) {
diff --git a/chromium/content/browser/leveldb_wrapper_impl.h b/chromium/content/browser/dom_storage/storage_area_impl.h
index 79075941452..4fbea92351d 100644
--- a/chromium/content/browser/leveldb_wrapper_impl.h
+++ b/chromium/content/browser/dom_storage/storage_area_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_LEVELDB_WRAPPER_IMPL_H_
-#define CONTENT_BROWSER_LEVELDB_WRAPPER_IMPL_H_
+#ifndef CONTENT_BROWSER_DOM_STORAGE_STORAGE_AREA_IMPL_H_
+#define CONTENT_BROWSER_DOM_STORAGE_STORAGE_AREA_IMPL_H_
#include <map>
#include <memory>
@@ -15,23 +15,23 @@
#include "base/macros.h"
#include "base/optional.h"
#include "base/time/time.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
#include "content/common/content_export.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"
+#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
namespace base {
namespace trace_event {
class ProcessMemoryDump;
}
-}
+} // namespace base
namespace content {
// This is a wrapper around a leveldb::mojom::LevelDBDatabase. Multiple
-// interface
-// pointers can be bound to the same object. The wrapper adds a couple of
-// features not found directly in leveldb.
+// interface pointers can be bound to the same object. The wrapper adds a couple
+// of features not found directly in leveldb.
// 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.
@@ -40,7 +40,7 @@ namespace content {
// 4) Throttles requests to avoid overwhelming the disk.
//
// The wrapper supports two different caching modes.
-class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
+class CONTENT_EXPORT StorageAreaImpl : public blink::mojom::StorageArea {
public:
using ValueMap = std::map<std::vector<uint8_t>, std::vector<uint8_t>>;
using ValueMapCallback = base::OnceCallback<void(std::unique_ptr<ValueMap>)>;
@@ -89,34 +89,34 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
// |Delegate::OnNoBindings| will be called when this object has no more
// bindings and all pending modifications have been processed.
- LevelDBWrapperImpl(leveldb::mojom::LevelDBDatabase* database,
- const std::string& prefix,
- Delegate* delegate,
- const Options& options);
- LevelDBWrapperImpl(leveldb::mojom::LevelDBDatabase* database,
- std::vector<uint8_t> prefix,
- Delegate* delegate,
- const Options& options);
+ StorageAreaImpl(leveldb::mojom::LevelDBDatabase* database,
+ const std::string& prefix,
+ Delegate* delegate,
+ const Options& options);
+ StorageAreaImpl(leveldb::mojom::LevelDBDatabase* database,
+ std::vector<uint8_t> prefix,
+ Delegate* delegate,
+ const Options& options);
- ~LevelDBWrapperImpl() override;
+ ~StorageAreaImpl() override;
- void Bind(mojom::LevelDBWrapperRequest request);
+ void Bind(blink::mojom::StorageAreaRequest request);
// Forks, or copies, all data in this prefix to another prefix.
- // Note: this object (the parent) must stay alive until the forked wrapper
+ // Note: this object (the parent) must stay alive until the forked area
// has been loaded (see initialized()).
- std::unique_ptr<LevelDBWrapperImpl> ForkToNewPrefix(
+ std::unique_ptr<StorageAreaImpl> ForkToNewPrefix(
const std::string& new_prefix,
Delegate* delegate,
const Options& options);
- std::unique_ptr<LevelDBWrapperImpl> ForkToNewPrefix(
+ std::unique_ptr<StorageAreaImpl> ForkToNewPrefix(
std::vector<uint8_t> new_prefix,
Delegate* delegate,
const Options& options);
// Cancels all pending load tasks. Useful for emergency destructions. If the
- // wrapper is unloaded (initialized() returns false), this will DROP all
- // pending changes to the database, and any uninitialized wrappers created
+ // area is unloaded (initialized() returns false), this will DROP all
+ // pending changes to the database, and any uninitialized areas created
// through |ForkToNewPrefix| will stay BROKEN and unresponsive.
void CancelAllPendingRequests();
@@ -127,7 +127,7 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
bool empty() const { return storage_used_ == 0; }
- // If this wrapper is loaded and sending changes to the database.
+ // If this ares is loaded and sending changes to the database.
bool initialized() const { return IsMapLoaded(); }
CacheMode cache_mode() const { return cache_mode_; }
@@ -169,13 +169,14 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
// Returns a pointer ID for use with HasObserver and RemoveObserver.
mojo::InterfacePtrSetElementId AddObserver(
- mojom::LevelDBObserverAssociatedPtr observer);
+ blink::mojom::StorageAreaObserverAssociatedPtr observer);
bool HasObserver(mojo::InterfacePtrSetElementId id);
- mojom::LevelDBObserverAssociatedPtr RemoveObserver(
+ blink::mojom::StorageAreaObserverAssociatedPtr RemoveObserver(
mojo::InterfacePtrSetElementId id);
- // LevelDBWrapper:
- void AddObserver(mojom::LevelDBObserverAssociatedPtrInfo observer) override;
+ // blink::mojom::StorageArea:
+ void AddObserver(
+ blink::mojom::StorageAreaObserverAssociatedPtrInfo observer) override;
void Put(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
const base::Optional<std::vector<uint8_t>>& client_old_value,
@@ -188,16 +189,16 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
void DeleteAll(const std::string& source,
DeleteAllCallback callback) override;
void Get(const std::vector<uint8_t>& key, GetCallback callback) override;
- void GetAll(
- mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo complete_callback,
- GetAllCallback callback) override;
+ void GetAll(blink::mojom::StorageAreaGetAllCallbackAssociatedPtrInfo
+ complete_callback,
+ GetAllCallback callback) override;
private:
- FRIEND_TEST_ALL_PREFIXES(LevelDBWrapperImplTest, GetAllAfterSetCacheMode);
- FRIEND_TEST_ALL_PREFIXES(LevelDBWrapperImplTest,
+ FRIEND_TEST_ALL_PREFIXES(StorageAreaImplTest, GetAllAfterSetCacheMode);
+ FRIEND_TEST_ALL_PREFIXES(StorageAreaImplTest,
PutLoadsValuesAfterCacheModeUpgrade);
- FRIEND_TEST_ALL_PREFIXES(LevelDBWrapperImplTest, SetCacheModeConsistent);
- FRIEND_TEST_ALL_PREFIXES(LevelDBWrapperImplParamTest,
+ FRIEND_TEST_ALL_PREFIXES(StorageAreaImplTest, SetCacheModeConsistent);
+ FRIEND_TEST_ALL_PREFIXES(StorageAreaImplParamTest,
CommitOnDifferentCacheModes);
// Used to rate limit commits.
@@ -205,7 +206,7 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
public:
RateLimiter(size_t desired_rate, base::TimeDelta time_quantum);
- void add_samples(size_t samples) { samples_ += samples; }
+ void add_samples(size_t samples) { samples_ += samples; }
// Computes the total time needed to process the total samples seen
// at the desired rate.
@@ -243,7 +244,7 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
UNLOADED,
// Loading from the database connection.
LOADING_FROM_DATABASE,
- // Loading from another LevelDBWrapperImpl that we have forked from.
+ // Loading from another StorageAreaImpl that we have forked from.
LOADING_FROM_FORK,
LOADED_KEYS_ONLY,
LOADED_KEYS_AND_VALUES
@@ -254,7 +255,7 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
using ForkSourceEarlyDeathCallback =
base::OnceCallback<void(std::vector<uint8_t> source_prefix)>;
- // Changes the cache mode of the wrapper. If applicable, this will change the
+ // Changes the cache mode of the area. If applicable, this will change the
// internal storage type after the next commit. The keys-only mode can only
// be set only when there is one client binding. It automatically changes to
// keys-and-values mode when more than one binding exists.
@@ -303,14 +304,14 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
keys_values_map_.empty());
}
- void DoForkOperation(const base::WeakPtr<LevelDBWrapperImpl>& forked_wrapper);
+ void DoForkOperation(const base::WeakPtr<StorageAreaImpl>& forked_area);
void OnForkStateLoaded(bool database_enabled,
const ValueMap& map,
const KeysOnlyMap& key_only_map);
std::vector<uint8_t> prefix_;
- mojo::BindingSet<mojom::LevelDBWrapper> bindings_;
- mojo::AssociatedInterfacePtrSet<mojom::LevelDBObserver> observers_;
+ mojo::BindingSet<blink::mojom::StorageArea> bindings_;
+ mojo::AssociatedInterfacePtrSet<blink::mojom::StorageAreaObserver> observers_;
Delegate* delegate_;
leveldb::mojom::LevelDBDatabase* database_;
@@ -334,13 +335,13 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
bool has_committed_data_ = false;
std::unique_ptr<CommitBatch> commit_batch_;
- base::WeakPtrFactory<LevelDBWrapperImpl> weak_ptr_factory_;
+ base::WeakPtrFactory<StorageAreaImpl> weak_ptr_factory_;
static bool s_aggressive_flushing_enabled_;
- DISALLOW_COPY_AND_ASSIGN(LevelDBWrapperImpl);
+ DISALLOW_COPY_AND_ASSIGN(StorageAreaImpl);
};
} // namespace content
-#endif // CONTENT_BROWSER_LEVELDB_WRAPPER_IMPL_H_
+#endif // CONTENT_BROWSER_DOM_STORAGE_STORAGE_AREA_IMPL_H_
diff --git a/chromium/content/browser/leveldb_wrapper_impl_unittest.cc b/chromium/content/browser/dom_storage/storage_area_impl_unittest.cc
index ac80a72e4c4..4b0d1190af7 100644
--- a/chromium/content/browser/leveldb_wrapper_impl_unittest.cc
+++ b/chromium/content/browser/dom_storage/storage_area_impl_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/leveldb_wrapper_impl.h"
+#include "content/browser/dom_storage/storage_area_impl.h"
#include "base/atomic_ref_count.h"
#include "base/bind.h"
@@ -15,9 +15,9 @@
#include "base/threading/thread.h"
#include "components/services/leveldb/public/cpp/util.h"
#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
+#include "content/browser/dom_storage/test/storage_area_test_util.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/fake_leveldb_database.h"
-#include "content/test/leveldb_wrapper_test_util.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -29,7 +29,7 @@ namespace {
using test::MakeSuccessCallback;
using test::MakeGetAllCallback;
using test::GetAllCallback;
-using CacheMode = LevelDBWrapperImpl::CacheMode;
+using CacheMode = StorageAreaImpl::CacheMode;
using DatabaseError = leveldb::mojom::DatabaseError;
const char* kTestSource = "source";
@@ -90,7 +90,7 @@ class IncrementalBarrier {
DISALLOW_COPY_AND_ASSIGN(IncrementalBarrier);
};
-class MockDelegate : public LevelDBWrapperImpl::Delegate {
+class MockDelegate : public StorageAreaImpl::Delegate {
public:
MockDelegate() {}
~MockDelegate() override {}
@@ -106,13 +106,13 @@ class MockDelegate : public LevelDBWrapperImpl::Delegate {
std::move(committed_).Run();
}
void OnMapLoaded(DatabaseError error) override { map_load_count_++; }
- std::vector<LevelDBWrapperImpl::Change> FixUpData(
- const LevelDBWrapperImpl::ValueMap& data) override {
+ std::vector<StorageAreaImpl::Change> FixUpData(
+ const StorageAreaImpl::ValueMap& data) override {
return std::move(mock_changes_);
}
int map_load_count() const { return map_load_count_; }
- void set_mock_changes(std::vector<LevelDBWrapperImpl::Change> changes) {
+ void set_mock_changes(std::vector<StorageAreaImpl::Change> changes) {
mock_changes_ = std::move(changes);
}
@@ -122,7 +122,7 @@ class MockDelegate : public LevelDBWrapperImpl::Delegate {
private:
int map_load_count_ = 0;
- std::vector<LevelDBWrapperImpl::Change> mock_changes_;
+ std::vector<StorageAreaImpl::Change> mock_changes_;
base::OnceClosure committed_;
};
@@ -144,8 +144,8 @@ base::OnceCallback<void(bool, const std::vector<uint8_t>&)> MakeGetCallback(
value_out);
}
-LevelDBWrapperImpl::Options GetDefaultTestingOptions(CacheMode cache_mode) {
- LevelDBWrapperImpl::Options options;
+StorageAreaImpl::Options GetDefaultTestingOptions(CacheMode cache_mode) {
+ StorageAreaImpl::Options options;
options.max_size = kTestSizeLimit;
options.default_commit_delay = base::TimeDelta::FromSeconds(5);
options.max_bytes_per_hour = 10 * 1024 * 1024;
@@ -156,8 +156,8 @@ LevelDBWrapperImpl::Options GetDefaultTestingOptions(CacheMode cache_mode) {
} // namespace
-class LevelDBWrapperImplTest : public testing::Test,
- public mojom::LevelDBObserver {
+class StorageAreaImplTest : public testing::Test,
+ public blink::mojom::StorageAreaObserver {
public:
struct Observation {
enum { kAdd, kChange, kDelete, kDeleteAll, kSendOldValue } type;
@@ -168,26 +168,26 @@ class LevelDBWrapperImplTest : public testing::Test,
bool should_send_old_value;
};
- LevelDBWrapperImplTest() : db_(&mock_data_), observer_binding_(this) {
+ StorageAreaImplTest() : db_(&mock_data_), observer_binding_(this) {
auto request = mojo::MakeRequest(&level_db_database_ptr_);
db_.Bind(std::move(request));
- LevelDBWrapperImpl::Options options =
+ StorageAreaImpl::Options options =
GetDefaultTestingOptions(CacheMode::KEYS_ONLY_WHEN_POSSIBLE);
- level_db_wrapper_ = std::make_unique<LevelDBWrapperImpl>(
+ storage_area_ = std::make_unique<StorageAreaImpl>(
level_db_database_ptr_.get(), test_prefix_, &delegate_, options);
set_mock_data(test_prefix_ + test_key1_, test_value1_);
set_mock_data(test_prefix_ + test_key2_, test_value2_);
set_mock_data("123", "baddata");
- level_db_wrapper_->Bind(mojo::MakeRequest(&level_db_wrapper_ptr_));
- mojom::LevelDBObserverAssociatedPtrInfo ptr_info;
+ storage_area_->Bind(mojo::MakeRequest(&storage_area_ptr_));
+ blink::mojom::StorageAreaObserverAssociatedPtrInfo ptr_info;
observer_binding_.Bind(mojo::MakeRequest(&ptr_info));
- level_db_wrapper_ptr_->AddObserver(std::move(ptr_info));
+ storage_area_ptr_->AddObserver(std::move(ptr_info));
}
- ~LevelDBWrapperImplTest() override {}
+ ~StorageAreaImplTest() override {}
void set_mock_data(const std::string& key, const std::string& value) {
mock_data_[ToBytes(key)] = ToBytes(value);
@@ -208,58 +208,57 @@ class LevelDBWrapperImplTest : public testing::Test,
void clear_mock_data() { mock_data_.clear(); }
- mojom::LevelDBWrapper* wrapper() { return level_db_wrapper_ptr_.get(); }
- LevelDBWrapperImpl* wrapper_impl() { return level_db_wrapper_.get(); }
+ blink::mojom::StorageArea* storage_area() { return storage_area_ptr_.get(); }
+ StorageAreaImpl* storage_area_impl() { return storage_area_.get(); }
- void FlushWrapperBinding() { level_db_wrapper_ptr_.FlushForTesting(); }
+ void FlushAreaBinding() { storage_area_ptr_.FlushForTesting(); }
- bool GetSync(mojom::LevelDBWrapper* wrapper,
+ bool GetSync(blink::mojom::StorageArea* area,
const std::vector<uint8_t>& key,
std::vector<uint8_t>* result) {
bool success = false;
base::RunLoop loop;
- wrapper->Get(key, MakeGetCallback(loop.QuitClosure(), &success, result));
+ area->Get(key, MakeGetCallback(loop.QuitClosure(), &success, result));
loop.Run();
return success;
}
bool DeleteSync(
- mojom::LevelDBWrapper* wrapper,
+ blink::mojom::StorageArea* area,
const std::vector<uint8_t>& key,
const base::Optional<std::vector<uint8_t>>& client_old_value) {
- return test::DeleteSync(wrapper, key, client_old_value, test_source_);
+ return test::DeleteSync(area, key, client_old_value, test_source_);
}
- bool DeleteAllSync(mojom::LevelDBWrapper* wrapper) {
- return test::DeleteAllSync(wrapper, test_source_);
+ bool DeleteAllSync(blink::mojom::StorageArea* area) {
+ return test::DeleteAllSync(area, test_source_);
}
bool GetSync(const std::vector<uint8_t>& key, std::vector<uint8_t>* result) {
- return GetSync(wrapper(), key, result);
+ return GetSync(storage_area(), key, result);
}
bool PutSync(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
const base::Optional<std::vector<uint8_t>>& client_old_value,
std::string source = kTestSource) {
- return test::PutSync(wrapper(), key, value, client_old_value, source);
+ return test::PutSync(storage_area(), key, value, client_old_value, source);
}
bool DeleteSync(
const std::vector<uint8_t>& key,
const base::Optional<std::vector<uint8_t>>& client_old_value) {
- return DeleteSync(wrapper(), key, client_old_value);
+ return DeleteSync(storage_area(), key, client_old_value);
}
- bool DeleteAllSync() { return DeleteAllSync(wrapper()); }
+ bool DeleteAllSync() { return DeleteAllSync(storage_area()); }
- std::string GetSyncStrUsingGetAll(LevelDBWrapperImpl* wrapper_impl,
+ std::string GetSyncStrUsingGetAll(StorageAreaImpl* area_impl,
const std::string& key) {
- std::vector<mojom::KeyValuePtr> data;
- leveldb::mojom::DatabaseError status =
- test::GetAllSyncOnDedicatedPipe(wrapper_impl, &data);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ bool success = test::GetAllSyncOnDedicatedPipe(area_impl, &data);
- if (status != leveldb::mojom::DatabaseError::OK)
+ if (!success)
return "";
for (const auto& key_value : data) {
@@ -270,14 +269,13 @@ class LevelDBWrapperImplTest : public testing::Test,
return "";
}
- void BlockingCommit() { BlockingCommit(&delegate_, level_db_wrapper_.get()); }
+ void BlockingCommit() { BlockingCommit(&delegate_, storage_area_.get()); }
- void BlockingCommit(MockDelegate* delegate, LevelDBWrapperImpl* wrapper) {
- while (wrapper->has_pending_load_tasks() ||
- wrapper->has_changes_to_commit()) {
+ void BlockingCommit(MockDelegate* delegate, StorageAreaImpl* area) {
+ while (area->has_pending_load_tasks() || area->has_changes_to_commit()) {
base::RunLoop loop;
delegate->SetDidCommitCallback(loop.QuitClosure());
- wrapper->ScheduleImmediateCommit();
+ area->ScheduleImmediateCommit();
loop.Run();
}
}
@@ -344,28 +342,27 @@ class LevelDBWrapperImplTest : public testing::Test,
FakeLevelDBDatabase db_;
leveldb::mojom::LevelDBDatabasePtr level_db_database_ptr_;
MockDelegate delegate_;
- std::unique_ptr<LevelDBWrapperImpl> level_db_wrapper_;
- mojom::LevelDBWrapperPtr level_db_wrapper_ptr_;
- mojo::AssociatedBinding<mojom::LevelDBObserver> observer_binding_;
+ std::unique_ptr<StorageAreaImpl> storage_area_;
+ blink::mojom::StorageAreaPtr storage_area_ptr_;
+ mojo::AssociatedBinding<blink::mojom::StorageAreaObserver> observer_binding_;
std::vector<Observation> observations_;
bool should_record_send_old_value_observations_ = false;
};
-class LevelDBWrapperImplParamTest
- : public LevelDBWrapperImplTest,
- public testing::WithParamInterface<CacheMode> {
+class StorageAreaImplParamTest : public StorageAreaImplTest,
+ public testing::WithParamInterface<CacheMode> {
public:
- LevelDBWrapperImplParamTest() {}
- ~LevelDBWrapperImplParamTest() override {}
+ StorageAreaImplParamTest() {}
+ ~StorageAreaImplParamTest() override {}
};
-INSTANTIATE_TEST_CASE_P(LevelDBWrapperImplTest,
- LevelDBWrapperImplParamTest,
+INSTANTIATE_TEST_CASE_P(StorageAreaImplTest,
+ StorageAreaImplParamTest,
testing::Values(CacheMode::KEYS_ONLY_WHEN_POSSIBLE,
CacheMode::KEYS_AND_VALUES));
-TEST_F(LevelDBWrapperImplTest, GetLoadedFromMap) {
- wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
+TEST_F(StorageAreaImplTest, GetLoadedFromMap) {
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
std::vector<uint8_t> result;
EXPECT_TRUE(GetSync(test_key2_bytes_, &result));
EXPECT_EQ(test_value2_bytes_, result);
@@ -373,8 +370,8 @@ TEST_F(LevelDBWrapperImplTest, GetLoadedFromMap) {
EXPECT_FALSE(GetSync(ToBytes("x"), &result));
}
-TEST_F(LevelDBWrapperImplTest, GetFromPutOverwrite) {
- wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
+TEST_F(StorageAreaImplTest, GetFromPutOverwrite) {
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
std::vector<uint8_t> key = test_key2_bytes_;
std::vector<uint8_t> value = ToBytes("foo");
@@ -384,9 +381,10 @@ TEST_F(LevelDBWrapperImplTest, GetFromPutOverwrite) {
bool get_success = false;
{
IncrementalBarrier barrier(loop.QuitClosure());
- wrapper()->Put(key, value, test_value2_bytes_, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success));
- wrapper()->Get(key, MakeGetCallback(barrier.Get(), &get_success, &result));
+ storage_area()->Put(key, value, test_value2_bytes_, test_source_,
+ MakeSuccessCallback(barrier.Get(), &put_success));
+ storage_area()->Get(key,
+ MakeGetCallback(barrier.Get(), &get_success, &result));
}
loop.Run();
@@ -396,8 +394,8 @@ TEST_F(LevelDBWrapperImplTest, GetFromPutOverwrite) {
EXPECT_EQ(value, result);
}
-TEST_F(LevelDBWrapperImplTest, GetFromPutNewKey) {
- wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
+TEST_F(StorageAreaImplTest, GetFromPutNewKey) {
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
std::vector<uint8_t> key = ToBytes("newkey");
std::vector<uint8_t> value = ToBytes("foo");
@@ -408,43 +406,42 @@ TEST_F(LevelDBWrapperImplTest, GetFromPutNewKey) {
EXPECT_EQ(value, result);
}
-TEST_F(LevelDBWrapperImplTest, PutLoadsValuesAfterCacheModeUpgrade) {
+TEST_F(StorageAreaImplTest, PutLoadsValuesAfterCacheModeUpgrade) {
std::vector<uint8_t> key = ToBytes("newkey");
std::vector<uint8_t> value1 = ToBytes("foo");
std::vector<uint8_t> value2 = ToBytes("bar");
- ASSERT_EQ(CacheMode::KEYS_ONLY_WHEN_POSSIBLE, wrapper_impl()->cache_mode());
+ ASSERT_EQ(CacheMode::KEYS_ONLY_WHEN_POSSIBLE,
+ storage_area_impl()->cache_mode());
// Do a put to load the key-only cache.
EXPECT_TRUE(PutSync(key, value1, base::nullopt));
BlockingCommit();
- EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY,
- wrapper_impl()->map_state_);
+ EXPECT_EQ(StorageAreaImpl::MapState::LOADED_KEYS_ONLY,
+ storage_area_impl()->map_state_);
// Change cache mode.
- wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
// Loading new map isn't necessary yet.
- EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY,
- wrapper_impl()->map_state_);
+ EXPECT_EQ(StorageAreaImpl::MapState::LOADED_KEYS_ONLY,
+ storage_area_impl()->map_state_);
// Do another put and check that the map has been upgraded
EXPECT_TRUE(PutSync(key, value2, value1));
- EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_AND_VALUES,
- wrapper_impl()->map_state_);
+ EXPECT_EQ(StorageAreaImpl::MapState::LOADED_KEYS_AND_VALUES,
+ storage_area_impl()->map_state_);
}
-TEST_P(LevelDBWrapperImplParamTest, GetAll) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, GetAll) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
- std::vector<mojom::KeyValuePtr> data;
- leveldb::mojom::DatabaseError status = test::GetAllSync(wrapper(), &data);
-
- EXPECT_EQ(leveldb::mojom::DatabaseError::OK, status);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(storage_area(), &data));
EXPECT_EQ(2u, data.size());
}
-TEST_P(LevelDBWrapperImplParamTest, CommitPutToDB) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, CommitPutToDB) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
std::string key1 = test_key2_;
std::string value1 = "foo";
std::string key2 = test_prefix_;
@@ -457,15 +454,15 @@ TEST_P(LevelDBWrapperImplParamTest, CommitPutToDB) {
{
IncrementalBarrier barrier(loop.QuitClosure());
- wrapper()->Put(ToBytes(key1), ToBytes(value1), test_value2_bytes_,
- test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success1));
- wrapper()->Put(ToBytes(key2), ToBytes("old value"), base::nullopt,
- test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success2));
- wrapper()->Put(ToBytes(key2), ToBytes(value2), ToBytes("old value"),
- test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success3));
+ storage_area()->Put(ToBytes(key1), ToBytes(value1), test_value2_bytes_,
+ test_source_,
+ MakeSuccessCallback(barrier.Get(), &put_success1));
+ storage_area()->Put(ToBytes(key2), ToBytes("old value"), base::nullopt,
+ test_source_,
+ MakeSuccessCallback(barrier.Get(), &put_success2));
+ storage_area()->Put(ToBytes(key2), ToBytes(value2), ToBytes("old value"),
+ test_source_,
+ MakeSuccessCallback(barrier.Get(), &put_success3));
}
loop.Run();
@@ -482,8 +479,8 @@ TEST_P(LevelDBWrapperImplParamTest, CommitPutToDB) {
EXPECT_EQ(value2, get_mock_data(test_prefix_ + key2));
}
-TEST_P(LevelDBWrapperImplParamTest, PutObservations) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, PutObservations) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
std::string key = "new_key";
std::string value1 = "foo";
std::string value2 = "data abc";
@@ -510,14 +507,14 @@ TEST_P(LevelDBWrapperImplParamTest, PutObservations) {
ASSERT_EQ(2u, observations().size());
}
-TEST_P(LevelDBWrapperImplParamTest, DeleteNonExistingKey) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, DeleteNonExistingKey) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
EXPECT_TRUE(DeleteSync(ToBytes("doesn't exist"), std::vector<uint8_t>()));
EXPECT_EQ(0u, observations().size());
}
-TEST_P(LevelDBWrapperImplParamTest, DeleteExistingKey) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, DeleteExistingKey) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
std::string key = "newkey";
std::string value = "foo";
set_mock_data(test_prefix_ + key, value);
@@ -535,8 +532,8 @@ TEST_P(LevelDBWrapperImplParamTest, DeleteExistingKey) {
EXPECT_FALSE(has_mock_data(test_prefix_ + key));
}
-TEST_P(LevelDBWrapperImplParamTest, DeleteAllWithoutLoadedMap) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, DeleteAllWithoutLoadedMap) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
std::string key = "newkey";
std::string value = "foo";
std::string dummy_key = "foobar";
@@ -564,8 +561,8 @@ TEST_P(LevelDBWrapperImplParamTest, DeleteAllWithoutLoadedMap) {
std::vector<uint8_t>(), base::nullopt));
}
-TEST_P(LevelDBWrapperImplParamTest, DeleteAllWithLoadedMap) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, DeleteAllWithLoadedMap) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
std::string key = "newkey";
std::string value = "foo";
std::string dummy_key = "foobar";
@@ -585,15 +582,15 @@ TEST_P(LevelDBWrapperImplParamTest, DeleteAllWithLoadedMap) {
EXPECT_TRUE(has_mock_data(dummy_key));
}
-TEST_P(LevelDBWrapperImplParamTest, DeleteAllWithPendingMapLoad) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, DeleteAllWithPendingMapLoad) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
std::string key = "newkey";
std::string value = "foo";
std::string dummy_key = "foobar";
set_mock_data(dummy_key, value);
- wrapper()->Put(ToBytes(key), ToBytes(value), base::nullopt, kTestSource,
- base::DoNothing());
+ storage_area()->Put(ToBytes(key), ToBytes(value), base::nullopt, kTestSource,
+ base::DoNothing());
EXPECT_TRUE(DeleteAllSync());
ASSERT_EQ(2u, observations().size());
@@ -607,17 +604,16 @@ TEST_P(LevelDBWrapperImplParamTest, DeleteAllWithPendingMapLoad) {
EXPECT_TRUE(has_mock_data(dummy_key));
}
-TEST_P(LevelDBWrapperImplParamTest, DeleteAllWithoutLoadedEmptyMap) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, DeleteAllWithoutLoadedEmptyMap) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
clear_mock_data();
EXPECT_TRUE(DeleteAllSync());
ASSERT_EQ(0u, observations().size());
}
-TEST_F(LevelDBWrapperImplParamTest, PutOverQuotaLargeValue) {
- wrapper_impl()->SetCacheModeForTesting(
- LevelDBWrapperImpl::CacheMode::KEYS_AND_VALUES);
+TEST_F(StorageAreaImplParamTest, PutOverQuotaLargeValue) {
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
std::vector<uint8_t> key = ToBytes("newkey");
std::vector<uint8_t> value(kTestSizeLimit, 4);
@@ -627,9 +623,8 @@ TEST_F(LevelDBWrapperImplParamTest, PutOverQuotaLargeValue) {
EXPECT_TRUE(PutSync(key, value, base::nullopt));
}
-TEST_F(LevelDBWrapperImplParamTest, PutOverQuotaLargeKey) {
- wrapper_impl()->SetCacheModeForTesting(
- LevelDBWrapperImpl::CacheMode::KEYS_AND_VALUES);
+TEST_F(StorageAreaImplParamTest, PutOverQuotaLargeKey) {
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
std::vector<uint8_t> key(kTestSizeLimit, 'a');
std::vector<uint8_t> value = ToBytes("newvalue");
@@ -639,9 +634,8 @@ TEST_F(LevelDBWrapperImplParamTest, PutOverQuotaLargeKey) {
EXPECT_TRUE(PutSync(key, value, base::nullopt));
}
-TEST_F(LevelDBWrapperImplParamTest, PutWhenAlreadyOverQuota) {
- wrapper_impl()->SetCacheModeForTesting(
- LevelDBWrapperImpl::CacheMode::KEYS_AND_VALUES);
+TEST_F(StorageAreaImplParamTest, PutWhenAlreadyOverQuota) {
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
std::string key = "largedata";
std::vector<uint8_t> value(kTestSizeLimit, 4);
std::vector<uint8_t> old_value = value;
@@ -674,9 +668,8 @@ TEST_F(LevelDBWrapperImplParamTest, PutWhenAlreadyOverQuota) {
EXPECT_FALSE(PutSync(ToBytes(key), value, old_value));
}
-TEST_F(LevelDBWrapperImplParamTest, PutWhenAlreadyOverQuotaBecauseOfLargeKey) {
- wrapper_impl()->SetCacheModeForTesting(
- LevelDBWrapperImpl::CacheMode::KEYS_AND_VALUES);
+TEST_F(StorageAreaImplParamTest, PutWhenAlreadyOverQuotaBecauseOfLargeKey) {
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
std::vector<uint8_t> key(kTestSizeLimit, 'x');
std::vector<uint8_t> value = ToBytes("value");
std::vector<uint8_t> old_value = value;
@@ -698,8 +691,8 @@ TEST_F(LevelDBWrapperImplParamTest, PutWhenAlreadyOverQuotaBecauseOfLargeKey) {
EXPECT_FALSE(PutSync(key, value, old_value));
}
-TEST_P(LevelDBWrapperImplParamTest, PutAfterPurgeMemory) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, PutAfterPurgeMemory) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
std::vector<uint8_t> result;
const auto key = test_key2_bytes_;
const auto value = test_value2_bytes_;
@@ -710,15 +703,15 @@ TEST_P(LevelDBWrapperImplParamTest, PutAfterPurgeMemory) {
EXPECT_TRUE(PutSync(key, value, value));
EXPECT_EQ(delegate()->map_load_count(), 1);
- wrapper_impl()->PurgeMemory();
+ storage_area_impl()->PurgeMemory();
// Now adding should still work, and load map again.
EXPECT_TRUE(PutSync(key, value, value));
EXPECT_EQ(delegate()->map_load_count(), 2);
}
-TEST_P(LevelDBWrapperImplParamTest, PurgeMemoryWithPendingChanges) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, PurgeMemoryWithPendingChanges) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
std::vector<uint8_t> key = test_key2_bytes_;
std::vector<uint8_t> value = ToBytes("foo");
EXPECT_TRUE(PutSync(key, value, test_value2_bytes_));
@@ -726,24 +719,23 @@ TEST_P(LevelDBWrapperImplParamTest, PurgeMemoryWithPendingChanges) {
// Purge memory, and read. Should not actually have purged, so should not have
// triggered a load.
- wrapper_impl()->PurgeMemory();
+ storage_area_impl()->PurgeMemory();
EXPECT_TRUE(PutSync(key, value, value));
EXPECT_EQ(delegate()->map_load_count(), 1);
}
-TEST_P(LevelDBWrapperImplParamTest, FixUpData) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
- std::vector<LevelDBWrapperImpl::Change> changes;
+TEST_P(StorageAreaImplParamTest, FixUpData) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
+ std::vector<StorageAreaImpl::Change> changes;
changes.push_back(std::make_pair(test_key1_bytes_, ToBytes("foo")));
changes.push_back(std::make_pair(test_key2_bytes_, base::nullopt));
changes.push_back(std::make_pair(test_prefix_bytes_, ToBytes("bla")));
delegate()->set_mock_changes(std::move(changes));
- std::vector<mojom::KeyValuePtr> data;
- leveldb::mojom::DatabaseError status = test::GetAllSync(wrapper(), &data);
+ std::vector<blink::mojom::KeyValuePtr> data;
+ EXPECT_TRUE(test::GetAllSync(storage_area(), &data));
- EXPECT_EQ(leveldb::mojom::DatabaseError::OK, status);
ASSERT_EQ(2u, data.size());
EXPECT_EQ(test_prefix_, ToString(data[0]->key));
EXPECT_EQ("bla", ToString(data[0]->value));
@@ -755,46 +747,46 @@ TEST_P(LevelDBWrapperImplParamTest, FixUpData) {
EXPECT_EQ("bla", get_mock_data(test_prefix_ + test_prefix_));
}
-TEST_F(LevelDBWrapperImplTest, SetOnlyKeysWithoutDatabase) {
+TEST_F(StorageAreaImplTest, SetOnlyKeysWithoutDatabase) {
std::vector<uint8_t> key = test_key2_bytes_;
std::vector<uint8_t> value = ToBytes("foo");
MockDelegate delegate;
- LevelDBWrapperImpl level_db_wrapper(
+ StorageAreaImpl storage_area(
nullptr, test_prefix_, &delegate,
GetDefaultTestingOptions(CacheMode::KEYS_ONLY_WHEN_POSSIBLE));
- mojom::LevelDBWrapperPtr level_db_wrapper_ptr;
- level_db_wrapper.Bind(mojo::MakeRequest(&level_db_wrapper_ptr));
+ blink::mojom::StorageAreaPtr storage_area_ptr;
+ storage_area.Bind(mojo::MakeRequest(&storage_area_ptr));
// Setting only keys mode is noop.
- level_db_wrapper.SetCacheModeForTesting(CacheMode::KEYS_ONLY_WHEN_POSSIBLE);
+ storage_area.SetCacheModeForTesting(CacheMode::KEYS_ONLY_WHEN_POSSIBLE);
- EXPECT_FALSE(level_db_wrapper.initialized());
- EXPECT_EQ(CacheMode::KEYS_AND_VALUES, level_db_wrapper.cache_mode());
+ EXPECT_FALSE(storage_area.initialized());
+ EXPECT_EQ(CacheMode::KEYS_AND_VALUES, storage_area.cache_mode());
// Put and Get can work synchronously without reload.
bool put_callback_called = false;
- level_db_wrapper.Put(key, value, base::nullopt, "source",
- base::BindOnce(
- [](bool* put_callback_called, bool success) {
- EXPECT_TRUE(success);
- *put_callback_called = true;
- },
- &put_callback_called));
+ storage_area.Put(key, value, base::nullopt, "source",
+ base::BindOnce(
+ [](bool* put_callback_called, bool success) {
+ EXPECT_TRUE(success);
+ *put_callback_called = true;
+ },
+ &put_callback_called));
EXPECT_TRUE(put_callback_called);
std::vector<uint8_t> expected_value;
- level_db_wrapper.Get(
- key, base::BindOnce(
- [](std::vector<uint8_t>* expected_value, bool success,
- const std::vector<uint8_t>& value) {
- EXPECT_TRUE(success);
- *expected_value = value;
- },
- &expected_value));
+ storage_area.Get(key,
+ base::BindOnce(
+ [](std::vector<uint8_t>* expected_value, bool success,
+ const std::vector<uint8_t>& value) {
+ EXPECT_TRUE(success);
+ *expected_value = value;
+ },
+ &expected_value));
EXPECT_EQ(expected_value, value);
}
-TEST_P(LevelDBWrapperImplParamTest, CommitOnDifferentCacheModes) {
- wrapper_impl()->SetCacheModeForTesting(GetParam());
+TEST_P(StorageAreaImplParamTest, CommitOnDifferentCacheModes) {
+ storage_area_impl()->SetCacheModeForTesting(GetParam());
std::vector<uint8_t> key = test_key2_bytes_;
std::vector<uint8_t> value = ToBytes("foo");
std::vector<uint8_t> value2 = ToBytes("foo2");
@@ -802,29 +794,29 @@ TEST_P(LevelDBWrapperImplParamTest, CommitOnDifferentCacheModes) {
// The initial map always has values, so a nullopt is fine for the old value.
ASSERT_TRUE(PutSync(key, value, base::nullopt));
- ASSERT_TRUE(wrapper_impl()->commit_batch_);
+ ASSERT_TRUE(storage_area_impl()->commit_batch_);
- // Wrapper stays in CacheMode::KEYS_AND_VALUES until the first commit has
+ // Area stays in CacheMode::KEYS_AND_VALUES until the first commit has
// succeeded.
- EXPECT_TRUE(wrapper_impl()->commit_batch_->changed_values.empty());
- auto* changes = &wrapper_impl()->commit_batch_->changed_keys;
+ EXPECT_TRUE(storage_area_impl()->commit_batch_->changed_values.empty());
+ auto* changes = &storage_area_impl()->commit_batch_->changed_keys;
ASSERT_EQ(1u, changes->size());
EXPECT_EQ(key, *changes->begin());
BlockingCommit();
ASSERT_TRUE(PutSync(key, value2, value));
- ASSERT_TRUE(wrapper_impl()->commit_batch_);
+ ASSERT_TRUE(storage_area_impl()->commit_batch_);
// Commit has occured, so the map type will diverge based on the cache mode.
if (GetParam() == CacheMode::KEYS_AND_VALUES) {
- EXPECT_TRUE(wrapper_impl()->commit_batch_->changed_values.empty());
- auto* changes = &wrapper_impl()->commit_batch_->changed_keys;
+ EXPECT_TRUE(storage_area_impl()->commit_batch_->changed_values.empty());
+ auto* changes = &storage_area_impl()->commit_batch_->changed_keys;
ASSERT_EQ(1u, changes->size());
EXPECT_EQ(key, *changes->begin());
} else {
- EXPECT_TRUE(wrapper_impl()->commit_batch_->changed_keys.empty());
- auto* changes = &wrapper_impl()->commit_batch_->changed_values;
+ EXPECT_TRUE(storage_area_impl()->commit_batch_->changed_keys.empty());
+ auto* changes = &storage_area_impl()->commit_batch_->changed_values;
ASSERT_EQ(1u, changes->size());
auto it = changes->begin();
EXPECT_EQ(key, it->first);
@@ -835,21 +827,21 @@ TEST_P(LevelDBWrapperImplParamTest, CommitOnDifferentCacheModes) {
EXPECT_EQ("foo2", get_mock_data(test_prefix_ + test_key2_));
if (GetParam() == CacheMode::KEYS_AND_VALUES)
- EXPECT_EQ(2u, wrapper_impl()->keys_values_map_.size());
+ EXPECT_EQ(2u, storage_area_impl()->keys_values_map_.size());
else
- EXPECT_EQ(2u, wrapper_impl()->keys_only_map_.size());
+ EXPECT_EQ(2u, storage_area_impl()->keys_only_map_.size());
ASSERT_TRUE(PutSync(key, value2, value2));
- EXPECT_FALSE(wrapper_impl()->commit_batch_);
+ EXPECT_FALSE(storage_area_impl()->commit_batch_);
ASSERT_TRUE(PutSync(key, value3, value2));
- ASSERT_TRUE(wrapper_impl()->commit_batch_);
+ ASSERT_TRUE(storage_area_impl()->commit_batch_);
if (GetParam() == CacheMode::KEYS_AND_VALUES) {
- auto* changes = &wrapper_impl()->commit_batch_->changed_keys;
+ auto* changes = &storage_area_impl()->commit_batch_->changed_keys;
EXPECT_EQ(1u, changes->size());
auto it = changes->find(key);
ASSERT_NE(it, changes->end());
} else {
- auto* changes = &wrapper_impl()->commit_batch_->changed_values;
+ auto* changes = &storage_area_impl()->commit_batch_->changed_values;
EXPECT_EQ(1u, changes->size());
auto it = changes->find(key);
ASSERT_NE(it, changes->end());
@@ -857,13 +849,13 @@ TEST_P(LevelDBWrapperImplParamTest, CommitOnDifferentCacheModes) {
}
clear_mock_data();
- EXPECT_TRUE(wrapper_impl()->has_changes_to_commit());
+ EXPECT_TRUE(storage_area_impl()->has_changes_to_commit());
BlockingCommit();
EXPECT_EQ("foobar", get_mock_data(test_prefix_ + test_key2_));
- EXPECT_FALSE(wrapper_impl()->has_changes_to_commit());
+ EXPECT_FALSE(storage_area_impl()->has_changes_to_commit());
}
-TEST_F(LevelDBWrapperImplTest, GetAllWhenCacheOnlyKeys) {
+TEST_F(StorageAreaImplTest, GetAllWhenCacheOnlyKeys) {
std::vector<uint8_t> key = test_key2_bytes_;
std::vector<uint8_t> value = ToBytes("foo");
std::vector<uint8_t> value2 = ToBytes("foobar");
@@ -872,10 +864,10 @@ TEST_F(LevelDBWrapperImplTest, GetAllWhenCacheOnlyKeys) {
ASSERT_TRUE(PutSync(key, value, base::nullopt));
BlockingCommit();
ASSERT_TRUE(PutSync(key, value2, value));
- EXPECT_TRUE(wrapper_impl()->has_changes_to_commit());
+ EXPECT_TRUE(storage_area_impl()->has_changes_to_commit());
- leveldb::mojom::DatabaseError status;
- std::vector<mojom::KeyValuePtr> data;
+ bool get_all_success = false;
+ std::vector<blink::mojom::KeyValuePtr> data;
bool result = false;
base::RunLoop loop;
@@ -885,14 +877,15 @@ TEST_F(LevelDBWrapperImplTest, GetAllWhenCacheOnlyKeys) {
{
IncrementalBarrier barrier(loop.QuitClosure());
- wrapper()->Put(key, value, value2, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_result1));
+ storage_area()->Put(key, value, value2, test_source_,
+ MakeSuccessCallback(barrier.Get(), &put_result1));
- wrapper()->GetAll(GetAllCallback::CreateAndBind(&result, barrier.Get()),
- MakeGetAllCallback(&status, &data));
- wrapper()->Put(key, value2, value, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_result2));
- FlushWrapperBinding();
+ storage_area()->GetAll(
+ GetAllCallback::CreateAndBind(&result, barrier.Get()),
+ MakeGetAllCallback(&get_all_success, &data));
+ storage_area()->Put(key, value2, value, test_source_,
+ MakeSuccessCallback(barrier.Get(), &put_result2));
+ FlushAreaBinding();
}
// GetAll triggers a commit when it's switching map types.
@@ -907,24 +900,24 @@ TEST_F(LevelDBWrapperImplTest, GetAllWhenCacheOnlyKeys) {
EXPECT_TRUE(put_result1);
EXPECT_EQ(2u, data.size());
- EXPECT_TRUE(
- data[1]->Equals(mojom::KeyValue(test_key1_bytes_, test_value1_bytes_)))
+ EXPECT_TRUE(data[1]->Equals(
+ blink::mojom::KeyValue(test_key1_bytes_, test_value1_bytes_)))
<< ToString(data[1]->value) << " vs expected " << test_value1_;
- EXPECT_TRUE(data[0]->Equals(mojom::KeyValue(key, value)))
+ EXPECT_TRUE(data[0]->Equals(blink::mojom::KeyValue(key, value)))
<< ToString(data[0]->value) << " vs expected " << ToString(value);
- EXPECT_EQ(leveldb::mojom::DatabaseError::OK, status);
+ EXPECT_TRUE(get_all_success);
// The last "put" isn't committed yet.
EXPECT_EQ("foo", get_mock_data(test_prefix_ + test_key2_));
- ASSERT_TRUE(wrapper_impl()->has_changes_to_commit());
+ ASSERT_TRUE(storage_area_impl()->has_changes_to_commit());
BlockingCommit();
EXPECT_EQ("foobar", get_mock_data(test_prefix_ + test_key2_));
}
-TEST_F(LevelDBWrapperImplTest, GetAllAfterSetCacheMode) {
+TEST_F(StorageAreaImplTest, GetAllAfterSetCacheMode) {
std::vector<uint8_t> key = test_key2_bytes_;
std::vector<uint8_t> value = ToBytes("foo");
std::vector<uint8_t> value2 = ToBytes("foobar");
@@ -932,55 +925,54 @@ TEST_F(LevelDBWrapperImplTest, GetAllAfterSetCacheMode) {
// Go to load state only keys.
ASSERT_TRUE(PutSync(key, value, base::nullopt));
BlockingCommit();
- EXPECT_TRUE(wrapper_impl()->map_state_ ==
- LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY);
+ EXPECT_TRUE(storage_area_impl()->map_state_ ==
+ StorageAreaImpl::MapState::LOADED_KEYS_ONLY);
ASSERT_TRUE(PutSync(key, value2, value));
- EXPECT_TRUE(wrapper_impl()->has_changes_to_commit());
+ EXPECT_TRUE(storage_area_impl()->has_changes_to_commit());
- wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
// Cache isn't cleared when commit batch exists.
- EXPECT_TRUE(wrapper_impl()->map_state_ ==
- LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY);
+ EXPECT_TRUE(storage_area_impl()->map_state_ ==
+ StorageAreaImpl::MapState::LOADED_KEYS_ONLY);
base::RunLoop loop;
bool put_success = false;
- leveldb::mojom::DatabaseError status;
- std::vector<mojom::KeyValuePtr> data;
+ std::vector<blink::mojom::KeyValuePtr> data;
bool get_all_success = false;
+ bool get_all_callback_success = false;
bool delete_success = false;
{
IncrementalBarrier barrier(loop.QuitClosure());
- wrapper()->Put(key, value, value2, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success));
+ storage_area()->Put(key, value, value2, test_source_,
+ MakeSuccessCallback(barrier.Get(), &put_success));
// Put task triggers database upgrade, so there are no more changes
// to commit.
- FlushWrapperBinding();
- EXPECT_FALSE(wrapper_impl()->has_changes_to_commit());
- EXPECT_TRUE(wrapper_impl()->has_pending_load_tasks());
+ FlushAreaBinding();
+ EXPECT_FALSE(storage_area_impl()->has_changes_to_commit());
+ EXPECT_TRUE(storage_area_impl()->has_pending_load_tasks());
- wrapper()->GetAll(
+ storage_area()->GetAll(
GetAllCallback::CreateAndBind(&get_all_success, barrier.Get()),
- MakeGetAllCallback(&status, &data));
+ MakeGetAllCallback(&get_all_callback_success, &data));
// This Delete() should not affect the value returned by GetAll().
- wrapper()->Delete(key, value, test_source_,
- MakeSuccessCallback(barrier.Get(), &delete_success));
+ storage_area()->Delete(key, value, test_source_,
+ MakeSuccessCallback(barrier.Get(), &delete_success));
}
loop.Run();
EXPECT_EQ(2u, data.size());
- EXPECT_TRUE(
- data[1]->Equals(mojom::KeyValue(test_key1_bytes_, test_value1_bytes_)))
+ EXPECT_TRUE(data[1]->Equals(
+ blink::mojom::KeyValue(test_key1_bytes_, test_value1_bytes_)))
<< ToString(data[1]->value) << " vs expected " << test_value1_;
- EXPECT_TRUE(data[0]->Equals(mojom::KeyValue(key, value)))
+ EXPECT_TRUE(data[0]->Equals(blink::mojom::KeyValue(key, value)))
<< ToString(data[0]->value) << " vs expected " << ToString(value2);
- EXPECT_EQ(leveldb::mojom::DatabaseError::OK, status);
-
+ EXPECT_TRUE(get_all_callback_success);
EXPECT_TRUE(put_success);
EXPECT_TRUE(get_all_success);
EXPECT_TRUE(delete_success);
@@ -989,74 +981,77 @@ TEST_F(LevelDBWrapperImplTest, GetAllAfterSetCacheMode) {
// map should be loading.
EXPECT_EQ("foobar", get_mock_data(test_prefix_ + test_key2_));
- ASSERT_TRUE(wrapper_impl()->has_changes_to_commit());
+ ASSERT_TRUE(storage_area_impl()->has_changes_to_commit());
BlockingCommit();
EXPECT_FALSE(has_mock_data(test_prefix_ + test_key2_));
}
-TEST_F(LevelDBWrapperImplTest, SetCacheModeConsistent) {
+TEST_F(StorageAreaImplTest, SetCacheModeConsistent) {
std::vector<uint8_t> key = test_key2_bytes_;
std::vector<uint8_t> value = ToBytes("foo");
std::vector<uint8_t> value2 = ToBytes("foobar");
- EXPECT_FALSE(wrapper_impl()->IsMapLoaded());
- EXPECT_TRUE(wrapper_impl()->cache_mode() ==
+ EXPECT_FALSE(storage_area_impl()->IsMapLoaded());
+ EXPECT_TRUE(storage_area_impl()->cache_mode() ==
CacheMode::KEYS_ONLY_WHEN_POSSIBLE);
- // Clear the database before the wrapper loads data.
+ // Clear the database before the area loads data.
clear_mock_data();
EXPECT_TRUE(PutSync(key, value, base::nullopt));
- EXPECT_TRUE(wrapper_impl()->has_changes_to_commit());
+ EXPECT_TRUE(storage_area_impl()->has_changes_to_commit());
BlockingCommit();
EXPECT_TRUE(PutSync(key, value2, value));
- EXPECT_TRUE(wrapper_impl()->has_changes_to_commit());
+ EXPECT_TRUE(storage_area_impl()->has_changes_to_commit());
// Setting cache mode does not reload the cache till it is required.
- wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
- EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY,
- wrapper_impl()->map_state_);
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
+ EXPECT_EQ(StorageAreaImpl::MapState::LOADED_KEYS_ONLY,
+ storage_area_impl()->map_state_);
// Put operation should change the mode.
EXPECT_TRUE(PutSync(key, value, value2));
- EXPECT_TRUE(wrapper_impl()->has_changes_to_commit());
- EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_AND_VALUES,
- wrapper_impl()->map_state_);
+ EXPECT_TRUE(storage_area_impl()->has_changes_to_commit());
+ EXPECT_EQ(StorageAreaImpl::MapState::LOADED_KEYS_AND_VALUES,
+ storage_area_impl()->map_state_);
std::vector<uint8_t> result;
EXPECT_TRUE(GetSync(key, &result));
EXPECT_EQ(value, result);
- EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_AND_VALUES,
- wrapper_impl()->map_state_);
+ EXPECT_EQ(StorageAreaImpl::MapState::LOADED_KEYS_AND_VALUES,
+ storage_area_impl()->map_state_);
BlockingCommit();
// Test that the map will unload correctly
EXPECT_TRUE(PutSync(key, value2, value));
- wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_ONLY_WHEN_POSSIBLE);
- EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY,
- wrapper_impl()->map_state_);
+ storage_area_impl()->SetCacheModeForTesting(
+ CacheMode::KEYS_ONLY_WHEN_POSSIBLE);
+ EXPECT_EQ(StorageAreaImpl::MapState::LOADED_KEYS_ONLY,
+ storage_area_impl()->map_state_);
BlockingCommit();
- EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY,
- wrapper_impl()->map_state_);
+ EXPECT_EQ(StorageAreaImpl::MapState::LOADED_KEYS_ONLY,
+ storage_area_impl()->map_state_);
// Test the map will unload right away when there are no changes.
- wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
EXPECT_TRUE(GetSync(key, &result));
- EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_AND_VALUES,
- wrapper_impl()->map_state_);
- wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_ONLY_WHEN_POSSIBLE);
- EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY,
- wrapper_impl()->map_state_);
+ EXPECT_EQ(StorageAreaImpl::MapState::LOADED_KEYS_AND_VALUES,
+ storage_area_impl()->map_state_);
+ storage_area_impl()->SetCacheModeForTesting(
+ CacheMode::KEYS_ONLY_WHEN_POSSIBLE);
+ EXPECT_EQ(StorageAreaImpl::MapState::LOADED_KEYS_ONLY,
+ storage_area_impl()->map_state_);
}
-TEST_F(LevelDBWrapperImplTest, SendOldValueObservations) {
+TEST_F(StorageAreaImplTest, SendOldValueObservations) {
should_record_send_old_value_observations(true);
- wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
+ storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
// Flush tasks on mojo thread to observe callback.
EXPECT_TRUE(DeleteSync(ToBytes("doesn't exist"), base::nullopt));
- wrapper_impl()->SetCacheModeForTesting(CacheMode::KEYS_ONLY_WHEN_POSSIBLE);
+ storage_area_impl()->SetCacheModeForTesting(
+ CacheMode::KEYS_ONLY_WHEN_POSSIBLE);
// Flush tasks on mojo thread to observe callback.
EXPECT_TRUE(DeleteSync(ToBytes("doesn't exist"), base::nullopt));
@@ -1067,13 +1062,13 @@ TEST_F(LevelDBWrapperImplTest, SendOldValueObservations) {
EXPECT_TRUE(observations()[1].should_send_old_value);
}
-TEST_P(LevelDBWrapperImplParamTest, PrefixForking) {
+TEST_P(StorageAreaImplParamTest, PrefixForking) {
std::string value3 = "value3";
std::string value4 = "value4";
std::string value5 = "value5";
// In order to test the interaction between forking and mojo calls where
- // forking can happen in between a request and reply to the wrapper mojo
+ // forking can happen in between a request and reply to the area mojo
// service, all calls are done on the 'impl' object itself.
// Operations in the same run cycle:
@@ -1083,11 +1078,11 @@ TEST_P(LevelDBWrapperImplParamTest, PrefixForking) {
// Put on fork 1
// Put on original
// Fork 3 created from original
- std::unique_ptr<LevelDBWrapperImpl> fork1;
+ std::unique_ptr<StorageAreaImpl> fork1;
MockDelegate fork1_delegate;
- std::unique_ptr<LevelDBWrapperImpl> fork2;
+ std::unique_ptr<StorageAreaImpl> fork2;
MockDelegate fork2_delegate;
- std::unique_ptr<LevelDBWrapperImpl> fork3;
+ std::unique_ptr<StorageAreaImpl> fork3;
MockDelegate fork3_delegate;
auto options = GetDefaultTestingOptions(GetParam());
@@ -1099,8 +1094,8 @@ TEST_P(LevelDBWrapperImplParamTest, PrefixForking) {
IncrementalBarrier barrier(loop.QuitClosure());
// Create fork 1.
- fork1 = wrapper_impl()->ForkToNewPrefix(test_copy_prefix1_, &fork1_delegate,
- options);
+ fork1 = storage_area_impl()->ForkToNewPrefix(test_copy_prefix1_,
+ &fork1_delegate, options);
// Do a put on fork 1 and create fork 2.
// Note - these are 'skipping' the mojo layer, which is why the fork isn't
@@ -1113,10 +1108,10 @@ TEST_P(LevelDBWrapperImplParamTest, PrefixForking) {
MakeSuccessCallback(barrier.Get(), &put_success2));
// Do a put on original and create fork 3, which is key-only.
- wrapper_impl()->Put(test_key1_bytes_, ToBytes(value3), test_value1_bytes_,
- test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success3));
- fork3 = wrapper_impl()->ForkToNewPrefix(
+ storage_area_impl()->Put(test_key1_bytes_, ToBytes(value3),
+ test_value1_bytes_, test_source_,
+ MakeSuccessCallback(barrier.Get(), &put_success3));
+ fork3 = storage_area_impl()->ForkToNewPrefix(
test_copy_prefix3_, &fork3_delegate,
GetDefaultTestingOptions(CacheMode::KEYS_ONLY_WHEN_POSSIBLE));
}
@@ -1126,17 +1121,18 @@ TEST_P(LevelDBWrapperImplParamTest, PrefixForking) {
EXPECT_TRUE(fork2.get());
EXPECT_TRUE(fork3.get());
- EXPECT_EQ(value3, GetSyncStrUsingGetAll(wrapper_impl(), test_key1_));
+ EXPECT_EQ(value3, GetSyncStrUsingGetAll(storage_area_impl(), test_key1_));
EXPECT_EQ(test_value1_, GetSyncStrUsingGetAll(fork1.get(), test_key1_));
EXPECT_EQ(test_value1_, GetSyncStrUsingGetAll(fork2.get(), test_key1_));
EXPECT_EQ(value3, GetSyncStrUsingGetAll(fork3.get(), test_key1_));
- EXPECT_EQ(test_value2_, GetSyncStrUsingGetAll(wrapper_impl(), test_key2_));
+ EXPECT_EQ(test_value2_,
+ GetSyncStrUsingGetAll(storage_area_impl(), test_key2_));
EXPECT_EQ(value5, GetSyncStrUsingGetAll(fork1.get(), test_key2_));
EXPECT_EQ(value4, GetSyncStrUsingGetAll(fork2.get(), test_key2_));
EXPECT_EQ(test_value2_, GetSyncStrUsingGetAll(fork3.get(), test_key2_));
- BlockingCommit(delegate(), wrapper_impl());
+ BlockingCommit(delegate(), storage_area_impl());
BlockingCommit(&fork1_delegate, fork1.get());
// test_key1_ values.
@@ -1152,7 +1148,7 @@ TEST_P(LevelDBWrapperImplParamTest, PrefixForking) {
EXPECT_EQ(test_value2_, get_mock_data(test_copy_prefix3_ + test_key2_));
}
-TEST_P(LevelDBWrapperImplParamTest, PrefixForkAfterLoad) {
+TEST_P(StorageAreaImplParamTest, PrefixForkAfterLoad) {
const std::string kValue = "foo";
const std::vector<uint8_t> kValueVec = ToBytes(kValue);
@@ -1161,14 +1157,14 @@ TEST_P(LevelDBWrapperImplParamTest, PrefixForkAfterLoad) {
// Execute the fork.
MockDelegate fork1_delegate;
- std::unique_ptr<LevelDBWrapperImpl> fork1 =
- wrapper_impl()->ForkToNewPrefix(test_copy_prefix1_, &fork1_delegate,
- GetDefaultTestingOptions(GetParam()));
+ std::unique_ptr<StorageAreaImpl> fork1 = storage_area_impl()->ForkToNewPrefix(
+ test_copy_prefix1_, &fork1_delegate,
+ GetDefaultTestingOptions(GetParam()));
// Check our forked state.
EXPECT_EQ(kValue, GetSyncStrUsingGetAll(fork1.get(), test_key1_));
- BlockingCommit(delegate(), wrapper_impl());
+ BlockingCommit(delegate(), storage_area_impl());
EXPECT_EQ(kValue, get_mock_data(test_copy_prefix1_ + test_key1_));
}
@@ -1186,38 +1182,38 @@ struct FuzzState {
};
} // namespace
-TEST_F(LevelDBWrapperImplTest, PrefixForkingPsuedoFuzzer) {
+TEST_F(StorageAreaImplTest, PrefixForkingPsuedoFuzzer) {
const std::string kKey1 = "key1";
const std::vector<uint8_t> kKey1Vec = ToBytes(kKey1);
const std::string kKey2 = "key2";
const std::vector<uint8_t> kKey2Vec = ToBytes(kKey2);
- const int kTotalWrappers = 1000;
+ const int kTotalAreas = 1000;
// This tests tries to throw all possible enumartions of operations and
- // forking at wrappers. The purpose is to hit all edge cases possible to
+ // forking at areas. The purpose is to hit all edge cases possible to
// expose any loading bugs.
- std::vector<FuzzState> states(kTotalWrappers);
- std::vector<std::unique_ptr<LevelDBWrapperImpl>> wrappers(kTotalWrappers);
- std::vector<MockDelegate> delegates(kTotalWrappers);
+ std::vector<FuzzState> states(kTotalAreas);
+ std::vector<std::unique_ptr<StorageAreaImpl>> areas(kTotalAreas);
+ std::vector<MockDelegate> delegates(kTotalAreas);
std::list<bool> successes;
int curr_prefix = 0;
base::RunLoop loop;
{
IncrementalBarrier barrier(loop.QuitClosure());
- for (int64_t i = 0; i < kTotalWrappers; i++) {
+ for (int64_t i = 0; i < kTotalAreas; i++) {
FuzzState& state = states[i];
- if (!wrappers[i]) {
- wrappers[i] = wrapper_impl()->ForkToNewPrefix(
+ if (!areas[i]) {
+ areas[i] = storage_area_impl()->ForkToNewPrefix(
GetNewPrefix(&curr_prefix), &delegates[i],
GetDefaultTestingOptions(CacheMode::KEYS_ONLY_WHEN_POSSIBLE));
}
int64_t forks = i;
- if ((i % 5 == 0 || i % 6 == 0) && forks + 1 < kTotalWrappers) {
+ if ((i % 5 == 0 || i % 6 == 0) && forks + 1 < kTotalAreas) {
forks++;
states[forks] = state;
- wrappers[forks] = wrappers[i]->ForkToNewPrefix(
+ areas[forks] = areas[i]->ForkToNewPrefix(
GetNewPrefix(&curr_prefix), &delegates[forks],
GetDefaultTestingOptions(CacheMode::KEYS_AND_VALUES));
}
@@ -1225,42 +1221,41 @@ TEST_F(LevelDBWrapperImplTest, PrefixForkingPsuedoFuzzer) {
FuzzState old_state = state;
state.val1 = base::nullopt;
successes.push_back(false);
- wrappers[i]->Delete(
- kKey1Vec, old_state.val1, test_source_,
- MakeSuccessCallback(barrier.Get(), &successes.back()));
+ areas[i]->Delete(kKey1Vec, old_state.val1, test_source_,
+ MakeSuccessCallback(barrier.Get(), &successes.back()));
}
if (i % 4 == 0) {
FuzzState old_state = state;
state.val2 = base::make_optional<std::vector<uint8_t>>(
{static_cast<uint8_t>(i)});
successes.push_back(false);
- wrappers[i]->Put(kKey2Vec, state.val2.value(), old_state.val2,
- test_source_,
- MakeSuccessCallback(barrier.Get(), &successes.back()));
+ areas[i]->Put(kKey2Vec, state.val2.value(), old_state.val2,
+ test_source_,
+ MakeSuccessCallback(barrier.Get(), &successes.back()));
}
if (i % 3 == 0) {
FuzzState old_state = state;
state.val1 = base::make_optional<std::vector<uint8_t>>(
{static_cast<uint8_t>(i + 5)});
successes.push_back(false);
- wrappers[i]->Put(kKey1Vec, state.val1.value(), old_state.val1,
- test_source_,
- MakeSuccessCallback(barrier.Get(), &successes.back()));
+ areas[i]->Put(kKey1Vec, state.val1.value(), old_state.val1,
+ test_source_,
+ MakeSuccessCallback(barrier.Get(), &successes.back()));
}
if (i % 11 == 0) {
state.val1 = base::nullopt;
state.val2 = base::nullopt;
successes.push_back(false);
- wrappers[i]->DeleteAll(
+ areas[i]->DeleteAll(
test_source_,
MakeSuccessCallback(barrier.Get(), &successes.back()));
}
- if (i % 2 == 0 && forks + 1 < kTotalWrappers) {
+ if (i % 2 == 0 && forks + 1 < kTotalAreas) {
CacheMode mode = i % 3 == 0 ? CacheMode::KEYS_AND_VALUES
: CacheMode::KEYS_ONLY_WHEN_POSSIBLE;
forks++;
states[forks] = state;
- wrappers[forks] = wrappers[i]->ForkToNewPrefix(
+ areas[forks] = areas[i]->ForkToNewPrefix(
GetNewPrefix(&curr_prefix), &delegates[forks],
GetDefaultTestingOptions(mode));
}
@@ -1269,23 +1264,23 @@ TEST_F(LevelDBWrapperImplTest, PrefixForkingPsuedoFuzzer) {
state.val1 = base::make_optional<std::vector<uint8_t>>(
{static_cast<uint8_t>(i + 9)});
successes.push_back(false);
- wrappers[i]->Put(kKey1Vec, state.val1.value(), old_state.val1,
- test_source_,
- MakeSuccessCallback(barrier.Get(), &successes.back()));
+ areas[i]->Put(kKey1Vec, state.val1.value(), old_state.val1,
+ test_source_,
+ MakeSuccessCallback(barrier.Get(), &successes.back()));
}
}
}
loop.Run();
// This section checks that we get the correct values when we query the
- // wrappers (which may or may not be maintaining their own cache).
- for (size_t i = 0; i < kTotalWrappers; i++) {
+ // areas (which may or may not be maintaining their own cache).
+ for (size_t i = 0; i < kTotalAreas; i++) {
FuzzState& state = states[i];
std::vector<uint8_t> result;
- // Note: this will cause all keys-only wrappers to commit.
- std::string result1 = GetSyncStrUsingGetAll(wrappers[i].get(), kKey1);
- std::string result2 = GetSyncStrUsingGetAll(wrappers[i].get(), kKey2);
+ // Note: this will cause all keys-only areas to commit.
+ std::string result1 = GetSyncStrUsingGetAll(areas[i].get(), kKey1);
+ std::string result2 = GetSyncStrUsingGetAll(areas[i].get(), kKey2);
EXPECT_EQ(!!state.val1, !result1.empty()) << i;
if (state.val1)
EXPECT_EQ(state.val1.value(), ToBytes(result1));
@@ -1294,24 +1289,24 @@ TEST_F(LevelDBWrapperImplTest, PrefixForkingPsuedoFuzzer) {
EXPECT_EQ(state.val2.value(), ToBytes(result2)) << i;
}
- // This section verifies that all wrappers have committed their changes to
+ // This section verifies that all areas have committed their changes to
// the database.
- ASSERT_EQ(wrappers.size(), delegates.size());
- size_t half = kTotalWrappers / 2;
+ ASSERT_EQ(areas.size(), delegates.size());
+ size_t half = kTotalAreas / 2;
for (size_t i = 0; i < half; i++) {
- BlockingCommit(&delegates[i], wrappers[i].get());
+ BlockingCommit(&delegates[i], areas[i].get());
}
- for (size_t i = kTotalWrappers - 1; i >= half; i--) {
- BlockingCommit(&delegates[i], wrappers[i].get());
+ for (size_t i = kTotalAreas - 1; i >= half; i--) {
+ BlockingCommit(&delegates[i], areas[i].get());
}
- // This section checks the data in the database itself to verify all wrappers
+ // This section checks the data in the database itself to verify all areas
// committed changes correctly.
- for (size_t i = 0; i < kTotalWrappers; ++i) {
+ for (size_t i = 0; i < kTotalAreas; ++i) {
FuzzState& state = states[i];
- std::vector<uint8_t> prefix = wrappers[i]->prefix();
+ std::vector<uint8_t> prefix = areas[i]->prefix();
std::string key1 = ToString(prefix) + kKey1;
std::string key2 = ToString(prefix) + kKey2;
EXPECT_EQ(!!state.val1, has_mock_data(key1));
@@ -1321,7 +1316,7 @@ TEST_F(LevelDBWrapperImplTest, PrefixForkingPsuedoFuzzer) {
if (state.val2)
EXPECT_EQ(ToString(state.val2.value()), get_mock_data(key2));
- EXPECT_FALSE(wrappers[i]->has_pending_load_tasks()) << i;
+ EXPECT_FALSE(areas[i]->has_pending_load_tasks()) << i;
}
}
diff --git a/chromium/content/browser/download/blob_download_url_loader_factory_getter.cc b/chromium/content/browser/download/blob_download_url_loader_factory_getter.cc
deleted file mode 100644
index d5d418186a1..00000000000
--- a/chromium/content/browser/download/blob_download_url_loader_factory_getter.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/download/blob_download_url_loader_factory_getter.h"
-
-#include "components/download/public/common/download_task_runner.h"
-#include "content/browser/url_loader_factory_getter.h"
-#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "storage/browser/blob/blob_data_handle.h"
-#include "storage/browser/blob/blob_url_loader_factory.h"
-
-namespace content {
-
-BlobDownloadURLLoaderFactoryGetter::BlobDownloadURLLoaderFactoryGetter(
- const GURL& url,
- std::unique_ptr<storage::BlobDataHandle> blob_data_handle)
- : url_(url), blob_data_handle_(std::move(blob_data_handle)) {
- DCHECK(url.SchemeIs(url::kBlobScheme));
-}
-
-BlobDownloadURLLoaderFactoryGetter::~BlobDownloadURLLoaderFactoryGetter() =
- default;
-
-scoped_refptr<network::SharedURLLoaderFactory>
-BlobDownloadURLLoaderFactoryGetter::GetURLLoaderFactory() {
- DCHECK(download::GetIOTaskRunner());
- DCHECK(download::GetIOTaskRunner()->BelongsToCurrentThread());
- network::mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info;
- storage::BlobURLLoaderFactory::Create(
- std::move(blob_data_handle_), url_,
- mojo::MakeRequest(&url_loader_factory_ptr_info));
- return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
- std::move(url_loader_factory_ptr_info));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/download/blob_download_url_loader_factory_getter.h b/chromium/content/browser/download/blob_download_url_loader_factory_getter.h
deleted file mode 100644
index 10938f46c42..00000000000
--- a/chromium/content/browser/download/blob_download_url_loader_factory_getter.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2018 The Chromium Authors. All 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_DOWNLOAD_BLOB_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
-#define CONTENT_BROWSER_DOWNLOAD_BLOB_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
-
-#include "components/download/public/common/download_url_loader_factory_getter.h"
-#include "url/gurl.h"
-
-namespace storage {
-class BlobDataHandle;
-}
-
-namespace content {
-
-// Class for retrieving the URLLoaderFactory for a blob URL.
-class BlobDownloadURLLoaderFactoryGetter
- : public download::DownloadURLLoaderFactoryGetter {
- public:
- BlobDownloadURLLoaderFactoryGetter(
- const GURL& url,
- std::unique_ptr<storage::BlobDataHandle> blob_data_handle);
-
- // download::DownloadURLLoaderFactoryGetter implementation.
- scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
-
- protected:
- ~BlobDownloadURLLoaderFactoryGetter() override;
-
- private:
- GURL url_;
- std::unique_ptr<storage::BlobDataHandle> blob_data_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(BlobDownloadURLLoaderFactoryGetter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DOWNLOAD_BLOB_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc
index 1cae12047b7..58882960352 100644
--- a/chromium/content/browser/download/download_browsertest.cc
+++ b/chromium/content/browser/download/download_browsertest.cc
@@ -43,6 +43,7 @@
#include "content/public/browser/download_request_utils.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/webplugininfo.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -67,6 +68,8 @@
#include "ppapi/buildflags/buildflags.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/platform/web_mouse_event.h"
#include "url/gurl.h"
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -231,7 +234,7 @@ class DownloadFileWithDelayFactory : public download::DownloadFileFactory {
private:
std::vector<base::Closure> rename_callbacks_;
- bool waiting_;
+ base::OnceClosure stop_waiting_;
base::WeakPtrFactory<DownloadFileWithDelayFactory> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory);
@@ -288,8 +291,7 @@ void DownloadFileWithDelay::RenameCallbackWrapper(
}
DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
- : waiting_(false),
- weak_ptr_factory_(this) {}
+ : weak_ptr_factory_(this) {}
DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}
@@ -307,8 +309,8 @@ download::DownloadFile* DownloadFileWithDelayFactory::CreateFile(
void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
rename_callbacks_.push_back(std::move(callback));
- if (waiting_)
- base::RunLoop::QuitCurrentWhenIdleDeprecated();
+ if (stop_waiting_)
+ std::move(stop_waiting_).Run();
}
void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
@@ -321,9 +323,9 @@ void DownloadFileWithDelayFactory::WaitForSomeCallback() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (rename_callbacks_.empty()) {
- waiting_ = true;
- RunMessageLoop();
- waiting_ = false;
+ base::RunLoop run_loop;
+ stop_waiting_ = run_loop.QuitClosure();
+ run_loop.Run();
}
}
@@ -366,11 +368,12 @@ class CountingDownloadFile : public download::DownloadFileImpl {
// until data is returned.
static int GetNumberActiveFilesFromFileThread() {
int result = -1;
+ base::RunLoop run_loop;
download::GetDownloadTaskRunner()->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&CountingDownloadFile::GetNumberActiveFiles, &result),
- base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
- base::RunLoop().Run();
+ run_loop.QuitClosure());
+ run_loop.Run();
DCHECK_NE(-1, result);
return result;
}
@@ -2893,10 +2896,9 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
}
-// A filename suggestion specified via a @download attribute should be effective
-// if the final download URL is in the same origin as the initial download URL.
-// Test that this holds even if there are cross origin redirects in the middle
-// of the redirect chain.
+// A filename suggestion specified via a @download attribute should not be
+// effective if there are cross origin redirects in the middle of the redirect
+// chain.
IN_PROC_BROWSER_TEST_F(DownloadContentTest,
DownloadAttributeSameOriginRedirect) {
net::EmbeddedTestServer origin_one;
@@ -2939,12 +2941,135 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
ASSERT_EQ(1u, downloads.size());
- EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"),
+ EXPECT_EQ(FILE_PATH_LITERAL("download"),
downloads[0]->GetTargetFilePath().BaseName().value());
ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
}
+// A file type that Blink can handle should not be downloaded if there are cross
+// origin redirects in the middle of the redirect chain.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest,
+ DownloadAttributeSameOriginRedirectNavigation) {
+ net::EmbeddedTestServer origin_one;
+ net::EmbeddedTestServer origin_two;
+ ASSERT_TRUE(origin_one.InitializeAndListen());
+ ASSERT_TRUE(origin_two.InitializeAndListen());
+
+ // The download-attribute.html page contains an anchor element whose href is
+ // set to the value of the query parameter (specified as |target| in the URL
+ // below). The suggested filename for the anchor is 'suggested-filename'. When
+ // the page is loaded, a script simulates a click on the anchor, triggering a
+ // download of the target URL.
+ //
+ // We construct two test servers; origin_one and origin_two. Once started, the
+ // server URLs will differ by the port number. Therefore they will be in
+ // different origins.
+ GURL download_url = origin_one.GetURL("/ping");
+ GURL referrer_url = origin_one.GetURL(
+ std::string("/download-attribute.html?target=") + download_url.spec());
+ origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
+
+ // <origin_one>/download-attribute.html initiates a download of
+ // <origin_one>/ping, which redirects to <origin_two>/download. The latter
+ // serves an HTML document.
+ origin_one.RegisterRequestHandler(
+ CreateRedirectHandler("/ping", origin_two.GetURL("/download")));
+ origin_two.RegisterRequestHandler(
+ CreateBasicResponseHandler("/download", net::HTTP_OK, base::StringPairs(),
+ "text/html", "<title>hello</title>"));
+
+ origin_one.StartAcceptingConnections();
+ origin_two.StartAcceptingConnections();
+
+ base::string16 expected_title(base::UTF8ToUTF16("hello"));
+ TitleWatcher observer(shell()->web_contents(), expected_title);
+ NavigateToURL(shell(), referrer_url);
+ ASSERT_EQ(expected_title, observer.WaitAndGetTitle());
+
+ std::vector<download::DownloadItem*> downloads;
+ DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
+ ASSERT_EQ(0u, downloads.size());
+
+ ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
+ ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
+}
+
+// A download initiated by the user via alt-click on a link should download,
+// even when redirected cross origin.
+//
+// Alt-click doesn't make sense on Android, and download a HTML file results
+// in an intent, so just skip.
+#if !defined(OS_ANDROID)
+IN_PROC_BROWSER_TEST_F(DownloadContentTest,
+ DownloadAttributeSameOriginRedirectAltClick) {
+ net::EmbeddedTestServer origin_one;
+ net::EmbeddedTestServer origin_two;
+ ASSERT_TRUE(origin_one.InitializeAndListen());
+ ASSERT_TRUE(origin_two.InitializeAndListen());
+
+ // The download-attribute.html page contains an anchor element whose href is
+ // set to the value of the query parameter (specified as |target| in the URL
+ // below). The suggested filename for the anchor is 'suggested-filename'. We
+ // will later send a "real" click to the anchor, triggering a download of the
+ // target URL.
+ //
+ // We construct two test servers; origin_one and origin_two. Once started, the
+ // server URLs will differ by the port number. Therefore they will be in
+ // different origins.
+ GURL download_url = origin_one.GetURL("/ping");
+ GURL referrer_url = origin_one.GetURL(
+ std::string("/download-attribute.html?noclick=") + download_url.spec());
+ origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
+
+ // <origin_one>/download-attribute.html initiates a download of
+ // <origin_one>/ping, which redirects to <origin_two>/download. The latter
+ // serves an HTML document.
+ origin_one.RegisterRequestHandler(
+ CreateRedirectHandler("/ping", origin_two.GetURL("/download")));
+ origin_two.RegisterRequestHandler(
+ CreateBasicResponseHandler("/download", net::HTTP_OK, base::StringPairs(),
+ "text/html", "<title>hello</title>"));
+
+ origin_one.StartAcceptingConnections();
+ origin_two.StartAcceptingConnections();
+
+ std::unique_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
+ NavigateToURL(shell(), referrer_url);
+
+ // Alt-click the link.
+ blink::WebMouseEvent mouse_event(
+ blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kAltKey,
+ blink::WebInputEvent::GetStaticTimeStampForTests());
+ mouse_event.button = blink::WebMouseEvent::Button::kLeft;
+ mouse_event.SetPositionInWidget(15, 15);
+ mouse_event.click_count = 1;
+ shell()->web_contents()->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(
+ mouse_event);
+ mouse_event.SetType(blink::WebInputEvent::kMouseUp);
+ shell()->web_contents()->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(
+ mouse_event);
+
+ observer->WaitForFinished();
+ EXPECT_EQ(
+ 1u, observer->NumDownloadsSeenInState(download::DownloadItem::COMPLETE));
+
+ std::vector<download::DownloadItem*> downloads;
+ DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
+ ASSERT_EQ(1u, downloads.size());
+#if defined(OS_WIN)
+ EXPECT_EQ(FILE_PATH_LITERAL("download.htm"),
+ downloads[0]->GetTargetFilePath().BaseName().value());
+#else
+ EXPECT_EQ(FILE_PATH_LITERAL("download.html"),
+ downloads[0]->GetTargetFilePath().BaseName().value());
+#endif
+
+ ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
+ ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
+}
+#endif // !defined(OS_ANDROID)
+
// Test that the suggested filename for data: URLs works.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeDataUrl) {
net::EmbeddedTestServer server;
@@ -2988,23 +3113,33 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeServerError) {
// should result in a network error page.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeNetworkError) {
SetupErrorInjectionDownloads();
+ WebContents* content = shell()->web_contents();
GURL url = TestDownloadHttpResponse::GetNextURLForDownload();
GURL server_url = embedded_test_server()->GetURL(url.host(), url.path());
- TestDownloadHttpResponse::Parameters parameters;
+ GURL document_url = embedded_test_server()->GetURL(
+ std::string("/download/download-attribute.html?target=") +
+ server_url.spec());
+
// Simulate a network failure by injecting an error before the response
// header.
+ TestDownloadHttpResponse::Parameters parameters;
parameters.injected_errors.push(-1);
parameters.inject_error_cb = inject_error_callback();
TestDownloadHttpResponse::StartServing(parameters, server_url);
- GURL document_url = embedded_test_server()->GetURL(
- std::string("/download/download-attribute.html?target=") +
- server_url.spec());
- auto observer = std::make_unique<content::TestNavigationObserver>(
- shell()->web_contents(), 2);
- NavigateToURL(shell(), document_url);
- observer->Wait();
- EXPECT_FALSE(observer->last_navigation_succeeded());
+ content::TestNavigationManager navigation_document(content, document_url);
+ content::TestNavigationManager navigation_download(content, server_url);
+ shell()->LoadURL(document_url);
+ navigation_document.WaitForNavigationFinished();
+ navigation_download.WaitForNavigationFinished();
+
+ EXPECT_TRUE(navigation_document.was_successful());
+ EXPECT_FALSE(navigation_download.was_successful());
+
+ NavigationEntry* navigation_entry =
+ shell()->web_contents()->GetController().GetLastCommittedEntry();
+ EXPECT_EQ(PAGE_TYPE_ERROR, navigation_entry->GetPageType());
+ EXPECT_EQ(server_url, navigation_entry->GetURL());
}
// A request that fails due to it being rejected by policy should result in a
@@ -3031,6 +3166,28 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeBlobURL) {
download->GetTargetFilePath().BaseName().value().c_str());
}
+class DownloadContentTestWithMojoBlobURLs : public DownloadContentTest {
+ public:
+ DownloadContentTestWithMojoBlobURLs() {
+ scoped_feature_list_.InitAndEnableFeature(blink::features::kMojoBlobURLs);
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(DownloadContentTestWithMojoBlobURLs,
+ DownloadAttributeBlobURL) {
+ GURL document_url =
+ embedded_test_server()->GetURL("/download/download-attribute-blob.html");
+ download::DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), document_url);
+ WaitForCompletion(download);
+
+ EXPECT_STREQ(FILE_PATH_LITERAL("suggested-filename.txt"),
+ download->GetTargetFilePath().BaseName().value().c_str());
+}
+
IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeSameSiteCookie) {
base::ThreadRestrictions::ScopedAllowIO allow_io_during_test;
net::EmbeddedTestServer test_server;
@@ -3470,41 +3627,92 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, FetchErrorResponseBodyResumption) {
std::string("header_value"));
}
-IN_PROC_BROWSER_TEST_F(DownloadContentTest,
- DISABLED_ForceDownloadMultipartRelatedPage) {
- // Force downloading the MHTML.
- DownloadTestContentBrowserClient new_client;
- new_client.set_allowed_rendering_mhtml_over_http(false);
- ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadFromWebUI) {
+ GURL webui_url("chrome://resources/images/apps/blue_button.png");
+ NavigateToURL(shell(), webui_url);
+ SetupEnsureNoPendingDownloads();
+ std::unique_ptr<download::DownloadUrlParameters> download_parameters(
+ DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
+ shell()->web_contents(), webui_url, TRAFFIC_ANNOTATION_FOR_TESTS));
+ std::unique_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
+ DownloadManagerForShell(shell())->DownloadUrl(std::move(download_parameters));
+ observer->WaitForFinished();
+
+ EXPECT_TRUE(EnsureNoPendingDownloads());
+
+ std::vector<download::DownloadItem*> downloads;
+ DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
+ ASSERT_EQ(1u, downloads.size());
+ ASSERT_EQ(download::DownloadItem::COMPLETE, downloads[0]->GetState());
+}
+
+// Test fixture for forcing MHTML download.
+class MhtmlDownloadTest : public DownloadContentTest {
+ protected:
+ void SetUpOnMainThread() override {
+ DownloadContentTest::SetUpOnMainThread();
+
+ // Force downloading the MHTML.
+ new_client_.set_allowed_rendering_mhtml_over_http(false);
+ old_client_ = SetBrowserClientForTesting(&new_client_);
+ }
+ void TearDownOnMainThread() override {
+ SetBrowserClientForTesting(old_client_);
+ DownloadContentTest::TearDownOnMainThread();
+ }
+
+ private:
+ DownloadTestContentBrowserClient new_client_;
+ ContentBrowserClient* old_client_;
+};
+
+IN_PROC_BROWSER_TEST_F(MhtmlDownloadTest, ForceDownloadMultipartRelatedPage) {
NavigateToURLAndWaitForDownload(
shell(),
// .mhtml file is mapped to "multipart/related" by the test server.
embedded_test_server()->GetURL("/download/hello.mhtml"),
download::DownloadItem::COMPLETE);
- SetBrowserClientForTesting(old_client);
}
-IN_PROC_BROWSER_TEST_F(DownloadContentTest, ForceDownloadMessageRfc822Page) {
- // Force downloading the MHTML.
- DownloadTestContentBrowserClient new_client;
- new_client.set_allowed_rendering_mhtml_over_http(false);
- ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
-
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(ADDRESS_SANITIZER)
+// Flaky https://crbug.com/852073
+#define MAYBE_ForceDownloadMessageRfc822Page \
+ DISABLED_ForceDownloadMessageRfc822Page
+#else
+#define MAYBE_ForceDownloadMessageRfc822Page ForceDownloadMessageRfc822Page
+#endif
+IN_PROC_BROWSER_TEST_F(MhtmlDownloadTest,
+ MAYBE_ForceDownloadMessageRfc822Page) {
NavigateToURLAndWaitForDownload(
shell(),
// .mht file is mapped to "message/rfc822" by the test server.
embedded_test_server()->GetURL("/download/test.mht"),
download::DownloadItem::COMPLETE);
- SetBrowserClientForTesting(old_client);
}
-IN_PROC_BROWSER_TEST_F(DownloadContentTest, AllowRenderMultipartRelatedPage) {
- // Allows loading the MHTML, instead of downloading it.
- DownloadTestContentBrowserClient new_client;
- new_client.set_allowed_rendering_mhtml_over_http(true);
- ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
+// Test fixture for loading MHTML.
+class MhtmlLoadingTest : public DownloadContentTest {
+ protected:
+ void SetUpOnMainThread() override {
+ DownloadContentTest::SetUpOnMainThread();
+
+ // Allows loading the MHTML, instead of downloading it.
+ new_client_.set_allowed_rendering_mhtml_over_http(true);
+ old_client_ = SetBrowserClientForTesting(&new_client_);
+ }
+
+ void TearDownOnMainThread() override {
+ SetBrowserClientForTesting(old_client_);
+ DownloadContentTest::TearDownOnMainThread();
+ }
+ private:
+ DownloadTestContentBrowserClient new_client_;
+ ContentBrowserClient* old_client_;
+};
+
+IN_PROC_BROWSER_TEST_F(MhtmlLoadingTest, AllowRenderMultipartRelatedPage) {
// .mhtml file is mapped to "multipart/related" by the test server.
GURL url = embedded_test_server()->GetURL("/download/hello.mhtml");
auto observer = std::make_unique<content::TestNavigationObserver>(url);
@@ -3514,15 +3722,9 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, AllowRenderMultipartRelatedPage) {
NavigateToURL(shell(), url);
observer->WaitForNavigationFinished();
- SetBrowserClientForTesting(old_client);
}
-IN_PROC_BROWSER_TEST_F(DownloadContentTest, AllowRenderMessageRfc822Page) {
- // Allows loading the MHTML, instead of downloading it.
- DownloadTestContentBrowserClient new_client;
- new_client.set_allowed_rendering_mhtml_over_http(true);
- ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
-
+IN_PROC_BROWSER_TEST_F(MhtmlLoadingTest, AllowRenderMessageRfc822Page) {
// .mht file is mapped to "message/rfc822" by the test server.
GURL url = embedded_test_server()->GetURL("/download/test.mht");
auto observer = std::make_unique<content::TestNavigationObserver>(url);
@@ -3532,7 +3734,6 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, AllowRenderMessageRfc822Page) {
NavigateToURL(shell(), url);
observer->WaitForNavigationFinished();
- SetBrowserClientForTesting(old_client);
}
} // namespace content
diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc
index 081c7a2c2f1..f8c137fe6d7 100644
--- a/chromium/content/browser/download/download_manager_impl.cc
+++ b/chromium/content/browser/download/download_manager_impl.cc
@@ -21,8 +21,9 @@
#include "base/supports_user_data.h"
#include "base/synchronization/lock.h"
#include "build/build_config.h"
-#include "components/download/downloader/in_progress/download_entry.h"
-#include "components/download/downloader/in_progress/in_progress_cache_impl.h"
+#include "components/download/database/in_progress/download_entry.h"
+#include "components/download/database/in_progress/in_progress_cache_impl.h"
+#include "components/download/database/switches.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_file.h"
#include "components/download/public/common/download_interrupt_reasons.h"
@@ -38,14 +39,15 @@
#include "content/browser/byte_stream.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
-#include "content/browser/download/blob_download_url_loader_factory_getter.h"
#include "content/browser/download/byte_stream_input_stream.h"
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/download/download_url_loader_factory_getter_impl.h"
#include "content/browser/download/download_utils.h"
+#include "content/browser/download/file_download_url_loader_factory_getter.h"
#include "content/browser/download/network_download_url_loader_factory_getter.h"
#include "content/browser/download/url_downloader.h"
#include "content/browser/download/url_downloader_factory.h"
+#include "content/browser/download/web_ui_download_url_loader_factory_getter.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -112,6 +114,18 @@ bool CanRequestURLFromRenderer(int render_process_id, GURL url) {
return true;
}
+void OnDownloadStarted(
+ download::DownloadItemImpl* download,
+ const download::DownloadUrlParameters::OnStartedCallback& on_started) {
+ if (on_started.is_null())
+ return;
+
+ if (!download || download->GetState() == download::DownloadItem::CANCELLED)
+ on_started.Run(nullptr, download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
+ else
+ on_started.Run(download, download::DOWNLOAD_INTERRUPT_REASON_NONE);
+}
+
// Creates an interrupted download and calls StartDownload. Can be called on
// any thread.
void CreateInterruptedDownload(
@@ -136,7 +150,7 @@ void CreateInterruptedDownload(
void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
content::ResourceContext* resource_context,
- uint32_t download_id,
+ bool is_new_download,
base::WeakPtr<DownloadManagerImpl> download_manager) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -146,7 +160,8 @@ void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params,
params->set_blob_storage_context_getter(
base::BindOnce(&BlobStorageContextGetter, resource_context));
std::unique_ptr<net::URLRequest> url_request =
- DownloadRequestCore::CreateRequestOnIOThread(download_id, params.get());
+ DownloadRequestCore::CreateRequestOnIOThread(is_new_download,
+ params.get());
if (blob_data_handle) {
storage::BlobProtocolHandler::SetRequestedBlobDataHandle(
url_request.get(), std::move(blob_data_handle));
@@ -288,17 +303,15 @@ DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context)
if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
download::UrlDownloadHandlerFactory::Install(new UrlDownloaderFactory());
in_progress_manager_ = std::make_unique<download::InProgressDownloadManager>(
- this, base::BindRepeating(&IsOriginSecure));
- in_progress_manager_->Initialize(
- IsOffTheRecord() ? base::FilePath() : browser_context_->GetPath(),
- base::BindOnce(&DownloadManagerImpl::PostInitialization,
- weak_factory_.GetWeakPtr(),
- DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE));
+ this, IsOffTheRecord() ? base::FilePath() : browser_context_->GetPath(),
+ base::BindRepeating(&IsOriginSecure));
+ in_progress_manager_->NotifyWhenInitialized(base::BindOnce(
+ &DownloadManagerImpl::OnInProgressDownloadManagerInitialized,
+ weak_factory_.GetWeakPtr()));
}
DownloadManagerImpl::~DownloadManagerImpl() {
DCHECK(!shutdown_needed_);
- download::SetIOTaskRunner(nullptr);
}
download::DownloadItemImpl* DownloadManagerImpl::CreateActiveItem(
@@ -311,6 +324,10 @@ download::DownloadItemImpl* DownloadManagerImpl::CreateActiveItem(
downloads_[id] = base::WrapUnique(download);
downloads_by_guid_[download->GetGuid()] = download;
+ DownloadItemUtils::AttachInfo(
+ download, GetBrowserContext(),
+ WebContentsImpl::FromRenderFrameHostID(info.render_process_id,
+ info.render_frame_id));
return download;
}
@@ -419,6 +436,25 @@ bool DownloadManagerImpl::InterceptDownload(
const download::DownloadCreateInfo& info) {
WebContents* web_contents = WebContentsImpl::FromRenderFrameHostID(
info.render_process_id, info.render_frame_id);
+ if (info.is_new_download &&
+ info.result ==
+ download::DOWNLOAD_INTERRUPT_REASON_SERVER_CROSS_ORIGIN_REDIRECT) {
+ if (web_contents) {
+ std::vector<GURL> url_chain(info.url_chain);
+ GURL url = url_chain.back();
+ url_chain.pop_back();
+ NavigationController::LoadURLParams params(url);
+ params.has_user_gesture = info.has_user_gesture;
+ params.referrer = Referrer(
+ info.referrer_url, Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
+ info.referrer_policy));
+ params.redirect_chain = url_chain;
+ web_contents->GetController().LoadURLWithParams(params);
+ }
+ if (info.request_handle)
+ info.request_handle->CancelRequest(false);
+ return true;
+ }
if (!delegate_ ||
!delegate_->InterceptDownloadIfApplicable(
info.url(), info.mime_type, info.request_origin, web_contents)) {
@@ -455,37 +491,59 @@ base::FilePath DownloadManagerImpl::GetDefaultDownloadDirectory() {
return default_download_directory;
}
-void DownloadManagerImpl::OnNewDownloadStarted(
- download::DownloadItem* download) {
- for (auto& observer : observers_)
- observer.OnDownloadCreated(this, download);
+void DownloadManagerImpl::OnInProgressDownloadManagerInitialized() {
+ std::vector<std::unique_ptr<download::DownloadItemImpl>>
+ in_progress_downloads = in_progress_manager_->TakeInProgressDownloads();
+ for (auto& download : in_progress_downloads) {
+ DCHECK(!base::ContainsKey(downloads_by_guid_, download->GetGuid()));
+ DCHECK(!base::ContainsKey(downloads_, download->GetId()));
+ DownloadItemUtils::AttachInfo(download.get(), GetBrowserContext(), nullptr);
+ download::DownloadItemImpl* item = download.get();
+ item->SetDelegate(this);
+ downloads_by_guid_[download->GetGuid()] = item;
+ downloads_[download->GetId()] = std::move(download);
+ for (auto& observer : observers_)
+ observer.OnDownloadCreated(this, item);
+ DVLOG(20) << __func__ << "() download = " << item->DebugString(true);
+ }
+ PostInitialization(DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE);
}
-download::DownloadItemImpl* DownloadManagerImpl::GetDownloadItem(
- uint32_t id,
- bool new_download,
- const download::DownloadCreateInfo& info) {
+void DownloadManagerImpl::StartDownloadItem(
+ std::unique_ptr<download::DownloadCreateInfo> info,
+ const download::DownloadUrlParameters::OnStartedCallback& on_started,
+ download::InProgressDownloadManager::StartDownloadItemCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK_NE(download::DownloadItem::kInvalidId, id);
- download::DownloadItemImpl* download = nullptr;
- if (new_download) {
- download = CreateActiveItem(id, info);
+ if (!info->is_new_download) {
+ download::DownloadItemImpl* download = downloads_by_guid_[info->guid];
+ if (!download || download->GetState() == download::DownloadItem::CANCELLED)
+ download = nullptr;
+ std::move(callback).Run(std::move(info), download);
+ OnDownloadStarted(download, on_started);
} else {
- auto item_iterator = downloads_.find(id);
- // Trying to resume an interrupted download.
- if (item_iterator == downloads_.end() ||
- (item_iterator->second->GetState() ==
- download::DownloadItem::CANCELLED)) {
- return nullptr;
- }
- download = item_iterator->second.get();
+ GetNextId(
+ base::BindRepeating(&DownloadManagerImpl::CreateNewDownloadItemToStart,
+ weak_factory_.GetWeakPtr(), base::Passed(&info),
+ on_started, base::Passed(&callback)));
}
- DownloadItemUtils::AttachInfo(
- download, GetBrowserContext(),
- WebContentsImpl::FromRenderFrameHostID(info.render_process_id,
- info.render_frame_id));
- return download;
+}
+
+void DownloadManagerImpl::CreateNewDownloadItemToStart(
+ std::unique_ptr<download::DownloadCreateInfo> info,
+ const download::DownloadUrlParameters::OnStartedCallback& on_started,
+ download::InProgressDownloadManager::StartDownloadItemCallback callback,
+ uint32_t id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ download::DownloadItemImpl* download = CreateActiveItem(id, *info);
+ std::move(callback).Run(std::move(info), download);
+ // For new downloads, we notify here, rather than earlier, so that
+ // the download_file is bound to download and all the usual
+ // setters (e.g. Cancel) work.
+ for (auto& observer : observers_)
+ observer.OnDownloadCreated(this, download);
+ OnDownloadStarted(download, on_started);
}
net::URLRequestContextGetter* DownloadManagerImpl::GetURLRequestContextGetter(
@@ -517,6 +575,18 @@ void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
}
}
+void DownloadManagerImpl::OnHistoryQueryComplete(
+ base::OnceClosure load_history_downloads_cb) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ download::switches::kEnableDownloadDB) &&
+ !in_progress_cache_initialized_) {
+ load_history_downloads_cb_ = std::move(load_history_downloads_cb);
+ } else {
+ std::move(load_history_downloads_cb).Run();
+ }
+}
+
void DownloadManagerImpl::CheckForFileRemoval(
download::DownloadItemImpl* download_item) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -595,10 +665,9 @@ void DownloadManagerImpl::CreateSavePackageDownloadItemWithId(
// download.
void DownloadManagerImpl::ResumeInterruptedDownload(
std::unique_ptr<download::DownloadUrlParameters> params,
- uint32_t id,
const GURL& site_url) {
BeginDownloadInternal(std::move(params), nullptr /* blob_data_handle */,
- nullptr /* blob_url_loader_factory */, id, site_url);
+ nullptr /* blob_url_loader_factory */, false, site_url);
}
void DownloadManagerImpl::SetDownloadItemFactoryForTesting(
@@ -697,9 +766,9 @@ download::DownloadInterruptReason DownloadManagerImpl::BeginDownloadRequest(
// TODO(ananta)
// Find a better way to create the DownloadResourceHandler instance.
std::unique_ptr<ResourceHandler> handler(
- DownloadResourceHandler::CreateForNewRequest(url_request.get(),
- params->request_origin(),
- params->download_source()));
+ DownloadResourceHandler::CreateForNewRequest(
+ url_request.get(), params->request_origin(),
+ params->download_source(), params->follow_cross_origin_redirects()));
ResourceDispatcherHostImpl::Get()->BeginURLRequest(
std::move(url_request), std::move(handler), true, // download
@@ -784,8 +853,7 @@ void DownloadManagerImpl::DownloadUrl(
auto* rfh = RenderFrameHost::FromID(params->render_process_host_id(),
params->render_frame_host_routing_id());
BeginDownloadInternal(std::move(params), std::move(blob_data_handle),
- std::move(blob_url_loader_factory),
- download::DownloadItem::kInvalidId,
+ std::move(blob_url_loader_factory), true,
rfh ? rfh->GetSiteInstance()->GetSiteURL() : GURL());
}
@@ -824,10 +892,15 @@ download::DownloadItem* DownloadManagerImpl::CreateDownloadItem(
bool transient,
const std::vector<download::DownloadItem::ReceivedSlice>& received_slices) {
if (base::ContainsKey(downloads_, id)) {
- NOTREACHED();
- return nullptr;
+ // If a completed or cancelled download item is already in the history db,
+ // remove it from the in-progress db.
+ if (state == download::DownloadItem::COMPLETE ||
+ state == download::DownloadItem::CANCELLED) {
+ in_progress_manager_->RemoveInProgressDownload(guid);
+ } else {
+ return downloads_[id].get();
+ }
}
- DCHECK(!base::ContainsKey(downloads_by_guid_, guid));
download::DownloadItemImpl* item = item_factory_->CreatePersistedItem(
this, guid, id, current_path, target_path, url_chain, referrer_url,
site_url, tab_url, tab_refererr_url, mime_type, original_mime_type,
@@ -855,6 +928,8 @@ void DownloadManagerImpl::PostInitialization(
break;
case DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE:
in_progress_cache_initialized_ = true;
+ if (load_history_downloads_cb_)
+ std::move(load_history_downloads_cb_).Run();
break;
case DOWNLOAD_INITIALIZATION_DEPENDENCY_NONE:
default:
@@ -1016,9 +1091,8 @@ void DownloadManagerImpl::InterceptNavigationOnChecksComplete(
void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete(
std::unique_ptr<download::DownloadUrlParameters> params,
- std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- uint32_t id,
+ bool is_new_download,
const GURL& site_url,
bool is_download_allowed) {
if (!is_download_allowed) {
@@ -1038,6 +1112,7 @@ void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete(
}
}
+ DCHECK_EQ(params->url().SchemeIsBlob(), bool{blob_url_loader_factory});
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter;
if (blob_url_loader_factory) {
@@ -1045,10 +1120,14 @@ void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete(
url_loader_factory_getter =
base::MakeRefCounted<DownloadURLLoaderFactoryGetterImpl>(
blob_url_loader_factory->Clone());
- } else if (params->url().SchemeIsBlob()) {
+ } else if (params->url().SchemeIsFile()) {
url_loader_factory_getter =
- base::MakeRefCounted<BlobDownloadURLLoaderFactoryGetter>(
- params->url(), std::move(blob_data_handle));
+ base::MakeRefCounted<FileDownloadURLLoaderFactoryGetter>(
+ params->url(), browser_context_->GetPath());
+ } else if (params->url().SchemeIs(content::kChromeUIScheme)) {
+ url_loader_factory_getter =
+ base::MakeRefCounted<WebUIDownloadURLLoaderFactoryGetter>(
+ rfh, params->url());
} else {
StoragePartitionImpl* storage_partition =
static_cast<StoragePartitionImpl*>(
@@ -1058,16 +1137,16 @@ void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete(
CreateDownloadURLLoaderFactoryGetter(storage_partition, rfh, true);
}
- in_progress_manager_->BeginDownload(std::move(params),
- std::move(url_loader_factory_getter), id,
- site_url, tab_url, tab_referrer_url);
+ in_progress_manager_->BeginDownload(
+ std::move(params), std::move(url_loader_factory_getter), is_new_download,
+ site_url, tab_url, tab_referrer_url);
}
void DownloadManagerImpl::BeginDownloadInternal(
std::unique_ptr<download::DownloadUrlParameters> params,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- uint32_t id,
+ bool is_new_download,
const GURL& site_url) {
// Check if the renderer is permitted to request the requested URL.
if (params->render_process_host_id() >= 0 &&
@@ -1096,8 +1175,7 @@ void DownloadManagerImpl::BeginDownloadInternal(
on_can_download_checks_done = base::BindOnce(
&DownloadManagerImpl::BeginResourceDownloadOnChecksComplete,
weak_factory_.GetWeakPtr(), std::move(params),
- std::move(blob_data_handle), std::move(blob_url_loader_factory),
- id, site_url);
+ std::move(blob_url_loader_factory), is_new_download, site_url);
if (delegate_) {
delegate_->CheckDownloadAllowed(std::move(web_contents_getter), url,
method,
@@ -1107,9 +1185,8 @@ void DownloadManagerImpl::BeginDownloadInternal(
}
BeginResourceDownloadOnChecksComplete(
- std::move(params), std::move(blob_data_handle),
- std::move(blob_url_loader_factory), id, site_url,
- rfh ? !content_initiated : true);
+ std::move(params), std::move(blob_url_loader_factory), is_new_download,
+ site_url, rfh ? !content_initiated : true);
} else {
StoragePartition* storage_partition =
BrowserContext::GetStoragePartitionForSite(browser_context_, site_url);
@@ -1119,7 +1196,7 @@ void DownloadManagerImpl::BeginDownloadInternal(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&BeginDownload, std::move(params),
std::move(blob_data_handle),
- browser_context_->GetResourceContext(), id,
+ browser_context_->GetResourceContext(), is_new_download,
weak_factory_.GetWeakPtr()));
}
}
diff --git a/chromium/content/browser/download/download_manager_impl.h b/chromium/content/browser/download/download_manager_impl.h
index 041492c4347..4f07f57f252 100644
--- a/chromium/content/browser/download/download_manager_impl.h
+++ b/chromium/content/browser/download/download_manager_impl.h
@@ -128,6 +128,8 @@ class CONTENT_EXPORT DownloadManagerImpl
int NonMaliciousInProgressCount() const override;
BrowserContext* GetBrowserContext() const override;
void CheckForHistoryFilesRemoval() override;
+ void OnHistoryQueryComplete(
+ base::OnceClosure load_history_downloads_cb) override;
download::DownloadItem* GetDownload(uint32_t id) override;
download::DownloadItem* GetDownloadByGuid(const std::string& guid) override;
@@ -194,14 +196,27 @@ class CONTENT_EXPORT DownloadManagerImpl
// InProgressDownloadManager::Delegate implementations.
bool InterceptDownload(const download::DownloadCreateInfo& info) override;
base::FilePath GetDefaultDownloadDirectory() override;
- download::DownloadItemImpl* GetDownloadItem(
- uint32_t id,
- bool new_download,
- const download::DownloadCreateInfo& info) override;
+ void StartDownloadItem(
+ std::unique_ptr<download::DownloadCreateInfo> info,
+ const download::DownloadUrlParameters::OnStartedCallback& on_started,
+ download::InProgressDownloadManager::StartDownloadItemCallback callback)
+ override;
net::URLRequestContextGetter* GetURLRequestContextGetter(
const download::DownloadCreateInfo& info) override;
- void OnNewDownloadStarted(download::DownloadItem* download) override;
- void GetNextId(const DownloadIdCallback& callback) override;
+
+ // Called when InProgressDownloadManager is initialzed.
+ void OnInProgressDownloadManagerInitialized();
+
+ // Creates a new download item and call |callback|.
+ void CreateNewDownloadItemToStart(
+ std::unique_ptr<download::DownloadCreateInfo> info,
+ const download::DownloadUrlParameters::OnStartedCallback& on_started,
+ download::InProgressDownloadManager::StartDownloadItemCallback callback,
+ uint32_t id);
+
+ // Called to get an ID for a new download. |callback| may be called
+ // synchronously.
+ void GetNextId(const DownloadIdCallback& callback);
// Create a new active item based on the info. Separate from
// StartDownload() for testing.
@@ -209,7 +224,6 @@ class CONTENT_EXPORT DownloadManagerImpl
uint32_t id,
const download::DownloadCreateInfo& info);
-
// Called with the result of DownloadManagerDelegate::CheckForFileExistence.
// Updates the state of the file and then notifies this update to the file's
// observer.
@@ -227,7 +241,6 @@ class CONTENT_EXPORT DownloadManagerImpl
std::string GetApplicationClientIdForFileScanning() const override;
void ResumeInterruptedDownload(
std::unique_ptr<download::DownloadUrlParameters> params,
- uint32_t id,
const GURL& site_url) override;
void OpenDownload(download::DownloadItemImpl* download) override;
bool IsMostRecentDownloadItemAtFilePath(
@@ -248,7 +261,7 @@ class CONTENT_EXPORT DownloadManagerImpl
std::unique_ptr<download::DownloadUrlParameters> params,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- uint32_t id,
+ bool is_new_download,
const GURL& site_url);
void InterceptNavigationOnChecksComplete(
@@ -261,9 +274,8 @@ class CONTENT_EXPORT DownloadManagerImpl
bool is_download_allowed);
void BeginResourceDownloadOnChecksComplete(
std::unique_ptr<download::DownloadUrlParameters> params,
- std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- uint32_t id,
+ bool is_new_download,
const GURL& site_url,
bool is_download_allowed);
@@ -314,6 +326,9 @@ class CONTENT_EXPORT DownloadManagerImpl
std::unique_ptr<download::InProgressDownloadManager> in_progress_manager_;
+ // Callback to run to load all history downloads.
+ base::OnceClosure load_history_downloads_cb_;
+
base::WeakPtrFactory<DownloadManagerImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DownloadManagerImpl);
diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc
index 9ccc49d3df7..c4e5f80b78f 100644
--- a/chromium/content/browser/download/download_manager_impl_unittest.cc
+++ b/chromium/content/browser/download/download_manager_impl_unittest.cc
@@ -320,6 +320,36 @@ class MockByteStreamReader : public ByteStreamReader {
MOCK_METHOD1(RegisterCallback, void(const base::Closure&));
};
+class TestInProgressManager : public download::InProgressDownloadManager {
+ public:
+ TestInProgressManager();
+ ~TestInProgressManager() override = default;
+
+ std::vector<std::unique_ptr<download::DownloadItemImpl>>
+ TakeInProgressDownloads() override;
+
+ void AddDownloadItem(std::unique_ptr<download::DownloadItemImpl> item);
+
+ private:
+ std::vector<std::unique_ptr<download::DownloadItemImpl>> download_items_;
+};
+
+TestInProgressManager::TestInProgressManager()
+ : download::InProgressDownloadManager(
+ nullptr,
+ base::FilePath(),
+ download::InProgressDownloadManager::IsOriginSecureCallback()) {}
+
+void TestInProgressManager::AddDownloadItem(
+ std::unique_ptr<download::DownloadItemImpl> item) {
+ download_items_.emplace_back(std::move(item));
+}
+
+std::vector<std::unique_ptr<download::DownloadItemImpl>>
+TestInProgressManager::TakeInProgressDownloads() {
+ return std::move(download_items_);
+}
+
} // namespace
class DownloadManagerTest : public testing::Test {
@@ -450,6 +480,15 @@ class DownloadManagerTest : public testing::Test {
base::Unretained(this)));
}
+ void OnInProgressDownloadManagerInitialized() {
+ download_manager_->OnInProgressDownloadManagerInitialized();
+ }
+
+ void SetInProgressDownloadManager(
+ std::unique_ptr<download::InProgressDownloadManager> manager) {
+ download_manager_->in_progress_manager_ = std::move(manager);
+ }
+
protected:
// Key test variable; we'll keep it available to sub-classes.
std::unique_ptr<DownloadManagerImpl> download_manager_;
@@ -609,4 +648,34 @@ TEST_F(DownloadManagerTest, RemoveDownloadsByURL) {
EXPECT_EQ(remove_count, 1);
}
+// Confirm that in-progress downloads will be taken and managed by
+// DownloadManager.
+TEST_F(DownloadManagerTest, OnInProgressDownloadsLoaded) {
+ auto in_progress_manager = std::make_unique<TestInProgressManager>();
+ const char kGuid[] = "8DF158E8-C980-4618-BB03-EBA3242EB48B";
+ auto in_progress_item = std::make_unique<download::DownloadItemImpl>(
+ in_progress_manager.get(), kGuid, 10, base::FilePath(), base::FilePath(),
+ std::vector<GURL>(), GURL("http://example.com/a"),
+ GURL("http://example.com/a"), GURL("http://example.com/a"),
+ 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(),
+ download::DownloadItem::INTERRUPTED,
+ download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, false,
+ base::Time::Now(), true,
+ std::vector<download::DownloadItem::ReceivedSlice>());
+ in_progress_manager->AddDownloadItem(std::move(in_progress_item));
+ SetInProgressDownloadManager(std::move(in_progress_manager));
+ EXPECT_CALL(GetMockObserver(), OnDownloadCreated(download_manager_.get(), _))
+ .WillOnce(Return());
+ OnInProgressDownloadManagerInitialized();
+ ASSERT_TRUE(download_manager_->GetDownloadByGuid(kGuid));
+
+ download::DownloadItem* download =
+ download_manager_->GetDownloadByGuid(kGuid);
+ download->Remove();
+ ASSERT_FALSE(download_manager_->GetDownloadByGuid(kGuid));
+}
+
} // namespace content
diff --git a/chromium/content/browser/download/download_request_core.cc b/chromium/content/browser/download/download_request_core.cc
index 3b2045e18ee..fb6a33bcd83 100644
--- a/chromium/content/browser/download/download_request_core.cc
+++ b/chromium/content/browser/download/download_request_core.cc
@@ -56,14 +56,14 @@ class DownloadRequestData : public base::SupportsUserData::Data {
static void Attach(net::URLRequest* request,
download::DownloadUrlParameters* download_parameters,
- uint32_t download_id);
+ bool is_new_download);
static DownloadRequestData* Get(const net::URLRequest* request);
static void Detach(net::URLRequest* request);
std::unique_ptr<download::DownloadSaveInfo> TakeSaveInfo() {
return std::move(save_info_);
}
- uint32_t download_id() const { return download_id_; }
+ bool is_new_download() const { return is_new_download_; }
std::string guid() const { return guid_; }
bool is_transient() const { return transient_; }
bool fetch_error_body() const { return fetch_error_body_; }
@@ -80,7 +80,7 @@ class DownloadRequestData : public base::SupportsUserData::Data {
static const int kKey;
std::unique_ptr<download::DownloadSaveInfo> save_info_;
- uint32_t download_id_ = download::DownloadItem::kInvalidId;
+ bool is_new_download_;
std::string guid_;
bool fetch_error_body_ = false;
download::DownloadUrlParameters::RequestHeadersType request_headers_;
@@ -95,11 +95,11 @@ const int DownloadRequestData::kKey = 0;
// static
void DownloadRequestData::Attach(net::URLRequest* request,
download::DownloadUrlParameters* parameters,
- uint32_t download_id) {
+ bool is_new_download) {
auto request_data = std::make_unique<DownloadRequestData>();
request_data->save_info_.reset(
new download::DownloadSaveInfo(parameters->GetSaveInfo()));
- request_data->download_id_ = download_id;
+ request_data->is_new_download_ = is_new_download;
request_data->guid_ = parameters->guid();
request_data->fetch_error_body_ = parameters->fetch_error_body();
request_data->request_headers_ = parameters->request_headers();
@@ -125,16 +125,15 @@ const int DownloadRequestCore::kDownloadByteStreamSize = 100 * 1024;
// static
std::unique_ptr<net::URLRequest> DownloadRequestCore::CreateRequestOnIOThread(
- uint32_t download_id,
+ bool is_new_download,
download::DownloadUrlParameters* params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(download_id == download::DownloadItem::kInvalidId ||
- !params->content_initiated())
- << "Content initiated downloads shouldn't specify a download ID";
+ DCHECK(is_new_download || !params->content_initiated())
+ << "Content initiated downloads should be a new download";
std::unique_ptr<net::URLRequest> request = CreateURLRequestOnIOThread(params);
- DownloadRequestData::Attach(request.get(), params, download_id);
+ DownloadRequestData::Attach(request.get(), params, is_new_download);
return request;
}
@@ -155,7 +154,7 @@ DownloadRequestCore::DownloadRequestCore(
download::DownloadSource download_source)
: delegate_(delegate),
request_(request),
- download_id_(download::DownloadItem::kInvalidId),
+ is_new_download_(true),
fetch_error_body_(false),
transient_(false),
bytes_read_(0),
@@ -193,7 +192,7 @@ DownloadRequestCore::DownloadRequestCore(
DownloadRequestData* request_data = DownloadRequestData::Get(request_);
if (request_data) {
save_info_ = request_data->TakeSaveInfo();
- download_id_ = request_data->download_id();
+ is_new_download_ = request_data->is_new_download();
guid_ = request_data->guid();
fetch_error_body_ = request_data->fetch_error_body();
request_headers_ = request_data->request_headers();
@@ -228,8 +227,9 @@ DownloadRequestCore::CreateDownloadCreateInfo(
create_info->connection_info = request()->response_info().connection_info;
create_info->url_chain = request()->url_chain();
create_info->referrer_url = GURL(request()->referrer());
+ create_info->referrer_policy = request()->referrer_policy();
create_info->result = result;
- create_info->download_id = download_id_;
+ create_info->is_new_download = is_new_download_;
create_info->guid = guid_;
create_info->transient = transient_;
create_info->response_headers = request()->response_headers();
diff --git a/chromium/content/browser/download/download_request_core.h b/chromium/content/browser/download/download_request_core.h
index 409e3e3912d..0fdd19edd45 100644
--- a/chromium/content/browser/download/download_request_core.h
+++ b/chromium/content/browser/download/download_request_core.h
@@ -109,7 +109,7 @@ class CONTENT_EXPORT DownloadRequestCore
std::string DebugString() const;
static std::unique_ptr<net::URLRequest> CreateRequestOnIOThread(
- uint32_t download_id,
+ bool is_new_download,
download::DownloadUrlParameters* params);
// Size of the buffer used between the DownloadRequestCore and the
@@ -129,7 +129,7 @@ class CONTENT_EXPORT DownloadRequestCore
// "Passthrough" fields. These are only kept here so that they can be used to
// populate the download::DownloadCreateInfo when the time comes.
std::unique_ptr<download::DownloadSaveInfo> save_info_;
- uint32_t download_id_;
+ bool is_new_download_;
std::string guid_;
bool fetch_error_body_;
download::DownloadUrlParameters::RequestHeadersType request_headers_;
diff --git a/chromium/content/browser/download/download_request_core_unittest.cc b/chromium/content/browser/download/download_request_core_unittest.cc
index 4d9c0db919d..5c6fb4e426b 100644
--- a/chromium/content/browser/download/download_request_core_unittest.cc
+++ b/chromium/content/browser/download/download_request_core_unittest.cc
@@ -46,8 +46,7 @@ class DownloadRequestCoreTest : public testing::Test {
}
void CreateRequestOnIOThread(download::DownloadUrlParameters* params) {
- url_request_ = DownloadRequestCore::CreateRequestOnIOThread(
- download::DownloadItem::kInvalidId, params);
+ url_request_ = DownloadRequestCore::CreateRequestOnIOThread(true, params);
DCHECK(url_request_.get());
}
diff --git a/chromium/content/browser/download/download_resource_handler.cc b/chromium/content/browser/download/download_resource_handler.cc
index d409db6c596..752cc1af42d 100644
--- a/chromium/content/browser/download/download_resource_handler.cc
+++ b/chromium/content/browser/download/download_resource_handler.cc
@@ -24,6 +24,7 @@
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_request_utils.h"
#include "content/public/browser/navigation_entry.h"
@@ -109,10 +110,8 @@ void InitializeDownloadTabInfoOnUIThread(
tab_info->tab_url = entry->GetURL();
tab_info->tab_referrer_url = entry->GetReferrer().url;
- tab_info->ukm_source_id = ukm::UkmRecorder::GetNewSourceID();
- download::DownloadUkmHelper::UpdateSourceURL(
- ukm::UkmRecorder::Get(), tab_info->ukm_source_id,
- web_contents->GetLastCommittedURL());
+ tab_info->ukm_source_id = static_cast<WebContentsImpl*>(web_contents)
+ ->GetUkmSourceIdForLastCommittedSource();
}
}
}
@@ -120,14 +119,35 @@ void InitializeDownloadTabInfoOnUIThread(
void DeleteOnUIThread(
std::unique_ptr<DownloadResourceHandler::DownloadTabInfo> tab_info) {}
+void NavigateOnUIThread(
+ const GURL& url,
+ const std::vector<GURL> url_chain,
+ const Referrer& referrer,
+ bool has_user_gesture,
+ const ResourceRequestInfo::WebContentsGetter& wc_getter) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ WebContents* web_contents = wc_getter.Run();
+ if (web_contents) {
+ NavigationController::LoadURLParams params(url);
+ params.has_user_gesture = has_user_gesture;
+ params.referrer = referrer;
+ params.redirect_chain = url_chain;
+ web_contents->GetController().LoadURLWithParams(params);
+ }
+}
+
} // namespace
DownloadResourceHandler::DownloadResourceHandler(
net::URLRequest* request,
const std::string& request_origin,
- download::DownloadSource download_source)
+ download::DownloadSource download_source,
+ bool follow_cross_origin_redirects)
: ResourceHandler(request),
tab_info_(new DownloadTabInfo()),
+ follow_cross_origin_redirects_(follow_cross_origin_redirects),
+ first_origin_(url::Origin::Create(request->url())),
core_(request, this, false, request_origin, download_source) {
// Do UI thread initialization for tab_info_ asap after
// DownloadResourceHandler creation since the tab could be navigated
@@ -157,7 +177,7 @@ std::unique_ptr<ResourceHandler> DownloadResourceHandler::Create(
net::URLRequest* request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::unique_ptr<ResourceHandler> handler(new DownloadResourceHandler(
- request, std::string(), download::DownloadSource::NAVIGATION));
+ request, std::string(), download::DownloadSource::NAVIGATION, true));
return handler;
}
@@ -165,10 +185,11 @@ std::unique_ptr<ResourceHandler> DownloadResourceHandler::Create(
std::unique_ptr<ResourceHandler> DownloadResourceHandler::CreateForNewRequest(
net::URLRequest* request,
const std::string& request_origin,
- download::DownloadSource download_source) {
+ download::DownloadSource download_source,
+ bool follow_cross_origin_redirects) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- std::unique_ptr<ResourceHandler> handler(
- new DownloadResourceHandler(request, request_origin, download_source));
+ std::unique_ptr<ResourceHandler> handler(new DownloadResourceHandler(
+ request, request_origin, download_source, follow_cross_origin_redirects));
return handler;
}
@@ -176,6 +197,21 @@ void DownloadResourceHandler::OnRequestRedirected(
const net::RedirectInfo& redirect_info,
network::ResourceResponse* response,
std::unique_ptr<ResourceController> controller) {
+ url::Origin new_origin(url::Origin::Create(redirect_info.new_url));
+ if (!follow_cross_origin_redirects_ &&
+ !first_origin_.IsSameOriginWith(new_origin)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &NavigateOnUIThread, redirect_info.new_url, request()->url_chain(),
+ Referrer(GURL(redirect_info.new_referrer),
+ Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
+ redirect_info.new_referrer_policy)),
+ GetRequestInfo()->HasUserGesture(),
+ GetRequestInfo()->GetWebContentsGetterForRequest()));
+ controller->Cancel();
+ return;
+ }
if (core_.OnRequestRedirected()) {
controller->Resume();
} else {
@@ -242,10 +278,6 @@ void DownloadResourceHandler::OnResponseCompleted(
controller->Resume();
}
-void DownloadResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- NOTREACHED();
-}
-
void DownloadResourceHandler::PauseRequest() {
core_.PauseRequest();
}
@@ -262,7 +294,7 @@ void DownloadResourceHandler::OnStart(
// download entirely.
if (create_info->result ==
download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED &&
- create_info->download_id == download::DownloadItem::kInvalidId) {
+ create_info->is_new_download) {
if (!callback.is_null())
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
diff --git a/chromium/content/browser/download/download_resource_handler.h b/chromium/content/browser/download/download_resource_handler.h
index 39f1982b309..2d206330813 100644
--- a/chromium/content/browser/download/download_resource_handler.h
+++ b/chromium/content/browser/download/download_resource_handler.h
@@ -44,7 +44,8 @@ class CONTENT_EXPORT DownloadResourceHandler
// |id| should be invalid if the id should be automatically assigned.
DownloadResourceHandler(net::URLRequest* request,
const std::string& request_origin,
- download::DownloadSource download_source);
+ download::DownloadSource download_source,
+ bool follow_cross_origin_redirects);
// static
// This function is passed into ResourceDispatcherHostImpl during its
@@ -61,7 +62,8 @@ class CONTENT_EXPORT DownloadResourceHandler
static std::unique_ptr<ResourceHandler> CreateForNewRequest(
net::URLRequest* request,
const std::string& request_origin,
- download::DownloadSource download_source);
+ download::DownloadSource download_source,
+ bool follow_cross_origin_redirects);
void OnRequestRedirected(
const net::RedirectInfo& redirect_info,
@@ -90,9 +92,6 @@ class CONTENT_EXPORT DownloadResourceHandler
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- // N/A to this flavor of DownloadHandler.
- void OnDataDownloaded(int bytes_downloaded) override;
-
void PauseRequest();
void ResumeRequest();
@@ -120,6 +119,9 @@ class CONTENT_EXPORT DownloadResourceHandler
// deletion must occur on the IO thread.
std::unique_ptr<DownloadTabInfo> tab_info_;
+ bool follow_cross_origin_redirects_;
+ url::Origin first_origin_;
+
DownloadRequestCore core_;
DISALLOW_COPY_AND_ASSIGN(DownloadResourceHandler);
diff --git a/chromium/content/browser/download/download_utils.cc b/chromium/content/browser/download/download_utils.cc
index ab0e360a306..fec2b6a861c 100644
--- a/chromium/content/browser/download/download_utils.cc
+++ b/chromium/content/browser/download/download_utils.cc
@@ -9,8 +9,8 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/task_scheduler/post_task.h"
-#include "components/download/downloader/in_progress/download_entry.h"
-#include "components/download/downloader/in_progress/in_progress_cache.h"
+#include "components/download/database/in_progress/download_entry.h"
+#include "components/download/database/in_progress/in_progress_cache.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_interrupt_reasons_utils.h"
#include "components/download/public/common/download_save_info.h"
diff --git a/chromium/content/browser/download/file_download_url_loader_factory_getter.cc b/chromium/content/browser/download/file_download_url_loader_factory_getter.cc
new file mode 100644
index 00000000000..973baed881d
--- /dev/null
+++ b/chromium/content/browser/download/file_download_url_loader_factory_getter.cc
@@ -0,0 +1,44 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/download/file_download_url_loader_factory_getter.h"
+
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
+#include "components/download/public/common/download_task_runner.h"
+#include "content/browser/file_url_loader_factory.h"
+#include "content/browser/url_loader_factory_getter.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+namespace content {
+
+FileDownloadURLLoaderFactoryGetter::FileDownloadURLLoaderFactoryGetter(
+ const GURL& url,
+ const base::FilePath& profile_path)
+ : url_(url), profile_path_(profile_path) {
+ DCHECK(url.SchemeIs(url::kFileScheme));
+}
+
+FileDownloadURLLoaderFactoryGetter::~FileDownloadURLLoaderFactoryGetter() =
+ default;
+
+scoped_refptr<network::SharedURLLoaderFactory>
+FileDownloadURLLoaderFactoryGetter::GetURLLoaderFactory() {
+ DCHECK(download::GetIOTaskRunner()->BelongsToCurrentThread());
+
+ network::mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info;
+ mojo::MakeStrongBinding(
+ std::make_unique<FileURLLoaderFactory>(
+ profile_path_, base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
+ MakeRequest(&url_loader_factory_ptr_info));
+
+ return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(url_loader_factory_ptr_info));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/download/file_download_url_loader_factory_getter.h b/chromium/content/browser/download/file_download_url_loader_factory_getter.h
new file mode 100644
index 00000000000..9c3e79c7a13
--- /dev/null
+++ b/chromium/content/browser/download/file_download_url_loader_factory_getter.h
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All 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_DOWNLOAD_FILE_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
+#define CONTENT_BROWSER_DOWNLOAD_FILE_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
+
+#include "base/files/file_path.h"
+#include "components/download/public/common/download_url_loader_factory_getter.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// Class for retrieving the URLLoaderFactory for a file URL.
+class FileDownloadURLLoaderFactoryGetter
+ : public download::DownloadURLLoaderFactoryGetter {
+ public:
+ FileDownloadURLLoaderFactoryGetter(const GURL& url,
+ const base::FilePath& profile_path);
+
+ // download::DownloadURLLoaderFactoryGetter implementation.
+ scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
+
+ protected:
+ ~FileDownloadURLLoaderFactoryGetter() override;
+
+ private:
+ GURL url_;
+ base::FilePath profile_path_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileDownloadURLLoaderFactoryGetter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOWNLOAD_FILE_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
diff --git a/chromium/content/browser/download/mhtml_generation_browsertest.cc b/chromium/content/browser/download/mhtml_generation_browsertest.cc
index d3e9279628a..379cc3ac485 100644
--- a/chromium/content/browser/download/mhtml_generation_browsertest.cc
+++ b/chromium/content/browser/download/mhtml_generation_browsertest.cc
@@ -13,7 +13,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_restrictions.h"
#include "components/download/public/common/download_task_runner.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc
index 7035f3e49d4..0310f540c34 100644
--- a/chromium/content/browser/download/save_package.cc
+++ b/chromium/content/browser/download/save_package.cc
@@ -44,6 +44,7 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
@@ -257,7 +258,8 @@ void SavePackage::InternalInit() {
download::RecordSavePackageEvent(download::SAVE_PACKAGE_STARTED);
- ukm_source_id_ = ukm::UkmRecorder::GetNewSourceID();
+ ukm_source_id_ = static_cast<WebContentsImpl*>(web_contents())
+ ->GetUkmSourceIdForLastCommittedSource();
ukm_download_id_ = download::GetUniqueDownloadId();
download::DownloadUkmHelper::RecordDownloadStarted(
ukm_download_id_, ukm_source_id_, download::DownloadContent::TEXT,
@@ -284,9 +286,6 @@ bool SavePackage::Init(
std::unique_ptr<download::DownloadRequestHandleInterface> request_handle(
new SavePackageRequestHandle(AsWeakPtr()));
- download::DownloadUkmHelper::UpdateSourceURL(
- ukm::UkmRecorder::Get(), ukm_source_id_,
- web_contents()->GetLastCommittedURL());
RenderFrameHost* frame_host = web_contents()->GetMainFrame();
download_manager_->CreateSavePackageDownloadItem(
saved_main_file_path_, page_url_,
diff --git a/chromium/content/browser/download/url_downloader.cc b/chromium/content/browser/download/url_downloader.cc
index 034fadddce8..e44234a31f5 100644
--- a/chromium/content/browser/download/url_downloader.cc
+++ b/chromium/content/browser/download/url_downloader.cc
@@ -13,6 +13,7 @@
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_request_handle_interface.h"
#include "components/download/public/common/download_url_parameters.h"
+#include "components/download/public/common/url_download_request_handle.h"
#include "content/browser/byte_stream.h"
#include "content/browser/download/byte_stream_input_stream.h"
#include "content/public/browser/browser_thread.h"
@@ -25,43 +26,6 @@
namespace content {
-class UrlDownloader::RequestHandle
- : public download::DownloadRequestHandleInterface {
- public:
- RequestHandle(base::WeakPtr<UrlDownloader> downloader,
- scoped_refptr<base::SequencedTaskRunner> downloader_task_runner)
- : downloader_(downloader),
- downloader_task_runner_(downloader_task_runner) {}
- RequestHandle(RequestHandle&& other)
- : downloader_(std::move(other.downloader_)),
- downloader_task_runner_(std::move(other.downloader_task_runner_)) {}
- RequestHandle& operator=(RequestHandle&& other) {
- downloader_ = std::move(other.downloader_);
- downloader_task_runner_ = std::move(other.downloader_task_runner_);
- return *this;
- }
-
- // DownloadRequestHandleInterface
- void PauseRequest() override {
- downloader_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&UrlDownloader::PauseRequest, downloader_));
- }
- void ResumeRequest() override {
- downloader_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&UrlDownloader::ResumeRequest, downloader_));
- }
- void CancelRequest(bool user_cancel) override {
- downloader_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&UrlDownloader::CancelRequest, downloader_));
- }
-
- private:
- base::WeakPtr<UrlDownloader> downloader_;
- scoped_refptr<base::SequencedTaskRunner> downloader_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(RequestHandle);
-};
-
// static
std::unique_ptr<UrlDownloader> UrlDownloader::BeginDownload(
base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
@@ -221,7 +185,7 @@ void UrlDownloader::OnStart(
std::unique_ptr<download::DownloadCreateInfo> create_info,
std::unique_ptr<ByteStreamReader> stream_reader,
const download::DownloadUrlParameters::OnStartedCallback& callback) {
- create_info->request_handle.reset(new RequestHandle(
+ create_info->request_handle.reset(new download::UrlDownloadRequestHandle(
weak_ptr_factory_.GetWeakPtr(), base::SequencedTaskRunnerHandle::Get()));
BrowserThread::PostTask(
diff --git a/chromium/content/browser/download/url_downloader.h b/chromium/content/browser/download/url_downloader.h
index 0ee10feddf7..e5b7289ea15 100644
--- a/chromium/content/browser/download/url_downloader.h
+++ b/chromium/content/browser/download/url_downloader.h
@@ -42,8 +42,6 @@ class UrlDownloader : public net::URLRequest::Delegate,
bool is_parallel_request);
private:
- class RequestHandle;
-
void Start();
// URLRequest::Delegate:
@@ -64,9 +62,10 @@ class UrlDownloader : public net::URLRequest::Delegate,
override;
void OnReadyToRead() override;
- void PauseRequest();
- void ResumeRequest();
- void CancelRequest();
+ // UrlDownloadHandler implementations.
+ void PauseRequest() override;
+ void ResumeRequest() override;
+ void CancelRequest() override;
// 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
diff --git a/chromium/content/browser/download/url_downloader_factory.cc b/chromium/content/browser/download/url_downloader_factory.cc
index 752cea70a5d..5a66bd2b9fa 100644
--- a/chromium/content/browser/download/url_downloader_factory.cc
+++ b/chromium/content/browser/download/url_downloader_factory.cc
@@ -23,8 +23,7 @@ UrlDownloaderFactory::CreateUrlDownloadHandler(
url_loader_factory_getter,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
std::unique_ptr<net::URLRequest> url_request =
- DownloadRequestCore::CreateRequestOnIOThread(
- download::DownloadItem::kInvalidId, params.get());
+ DownloadRequestCore::CreateRequestOnIOThread(true, params.get());
return download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr(
UrlDownloader::BeginDownload(delegate, std::move(url_request),
diff --git a/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc b/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc
new file mode 100644
index 00000000000..c4873157c81
--- /dev/null
+++ b/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc
@@ -0,0 +1,33 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/download/web_ui_download_url_loader_factory_getter.h"
+
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_ui_url_loader_factory.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
+
+namespace content {
+
+WebUIDownloadURLLoaderFactoryGetter::WebUIDownloadURLLoaderFactoryGetter(
+ RenderFrameHost* rfh,
+ const GURL& url) {
+ auto factory_request = mojo::MakeRequest(&factory_info_);
+ factory_ =
+ CreateWebUIURLLoader(rfh, url.scheme(), base::flat_set<std::string>());
+ factory_->Clone(std::move(factory_request));
+}
+
+WebUIDownloadURLLoaderFactoryGetter::~WebUIDownloadURLLoaderFactoryGetter() {
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)
+ ->DeleteSoon(FROM_HERE, std::move(factory_));
+}
+
+scoped_refptr<network::SharedURLLoaderFactory>
+WebUIDownloadURLLoaderFactoryGetter::GetURLLoaderFactory() {
+ return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(factory_info_));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.h b/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.h
new file mode 100644
index 00000000000..5f39fd718c4
--- /dev/null
+++ b/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.h
@@ -0,0 +1,40 @@
+// Copyright 2018 The Chromium Authors. All 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_DOWNLOAD_WEB_UI_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
+#define CONTENT_BROWSER_DOWNLOAD_WEB_UI_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
+
+#include "base/files/file_path.h"
+#include "components/download/public/common/download_url_loader_factory_getter.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+class GURL;
+
+namespace content {
+class RenderFrameHost;
+
+// Class for retrieving the URLLoaderFactory for a webui URL.
+class WebUIDownloadURLLoaderFactoryGetter
+ : public download::DownloadURLLoaderFactoryGetter {
+ public:
+ WebUIDownloadURLLoaderFactoryGetter(RenderFrameHost* rfh, const GURL& url);
+
+ // download::DownloadURLLoaderFactoryGetter implementation.
+ scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
+
+ protected:
+ ~WebUIDownloadURLLoaderFactoryGetter() override;
+
+ private:
+ network::mojom::URLLoaderFactoryPtrInfo factory_info_;
+
+ // Lives on the UI thread and must be deleted there.
+ std::unique_ptr<network::mojom::URLLoaderFactory> factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebUIDownloadURLLoaderFactoryGetter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOWNLOAD_WEB_UI_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
diff --git a/chromium/content/browser/file_url_loader_factory.cc b/chromium/content/browser/file_url_loader_factory.cc
index f260e71a625..44eb522466d 100644
--- a/chromium/content/browser/file_url_loader_factory.cc
+++ b/chromium/content/browser/file_url_loader_factory.cc
@@ -107,7 +107,9 @@ class FileURLDirectoryLoader
}
// network::mojom::URLLoader:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override {}
void ProceedWithResponse() override { NOTREACHED(); }
void SetPriority(net::RequestPriority priority,
@@ -160,7 +162,7 @@ class FileURLDirectoryLoader
network::ResourceResponseHead head;
head.mime_type = "text/html";
head.charset = "utf-8";
- client->OnReceiveResponse(head, nullptr);
+ client->OnReceiveResponse(head);
client->OnStartLoadingResponseBody(std::move(pipe.consumer_handle));
client_ = std::move(client);
@@ -316,7 +318,9 @@ class FileURLLoader : public network::mojom::URLLoader {
}
// network::mojom::URLLoader:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override {}
void ProceedWithResponse() override {}
void SetPriority(net::RequestPriority priority,
@@ -559,7 +563,7 @@ class FileURLLoader : public network::mojom::URLLoader {
base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentType,
head.mime_type.c_str()));
}
- client->OnReceiveResponse(head, nullptr);
+ client->OnReceiveResponse(head);
client->OnStartLoadingResponseBody(std::move(pipe.consumer_handle));
client_ = std::move(client);
@@ -635,7 +639,6 @@ void FileURLLoaderFactory::CreateLoaderAndStart(
const network::ResourceRequest& request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
- DCHECK(!request.download_to_file);
base::FilePath file_path;
const bool is_file = net::FileURLToFilePath(request.url, &file_path);
if (is_file && file_path.EndsWithSeparator() && file_path.IsAbsolute()) {
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper.cc b/chromium/content/browser/fileapi/browser_file_system_helper.cc
index aef88c1d686..acf067a117b 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper.cc
+++ b/chromium/content/browser/fileapi/browser_file_system_helper.cc
@@ -151,8 +151,12 @@ void PrepareDropDataForChildProcess(
#if defined(OS_CHROMEOS)
// The externalfile:// scheme is used in Chrome OS to open external files in a
// browser tab.
+ // TODO(https://crbug.com/858972): This seems like it could be forged by the
+ // renderer. This probably needs to check that this didn't originate from the
+ // renderer... Also, this probably can just be GrantRequestURL (which doesn't
+ // yet exist) instead of GrantCommitURL.
if (drop_data->url.SchemeIs(content::kExternalFileScheme))
- security_policy->GrantRequestURL(child_id, drop_data->url);
+ security_policy->GrantCommitURL(child_id, drop_data->url);
#endif
// The filenames vector represents a capability to access the given files.
diff --git a/chromium/content/browser/fileapi/file_system_url_loader_factory.cc b/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
index 0b426204681..7ef37b18b9f 100644
--- a/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
+++ b/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
@@ -94,7 +94,9 @@ class FileSystemEntryURLLoader
: binding_(this), params_(std::move(params)) {}
// network::mojom::URLLoader:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override {}
void ProceedWithResponse() override {}
void SetPriority(net::RequestPriority priority,
@@ -339,7 +341,7 @@ class FileSystemDirectoryURLLoader : public FileSystemEntryURLLoader {
head.content_length = data_.size();
head.headers = CreateHttpResponseHeaders(200);
- client_->OnReceiveResponse(head, /*downloaded_file=*/nullptr);
+ client_->OnReceiveResponse(head);
client_->OnStartLoadingResponseBody(std::move(pipe.consumer_handle));
data_producer_ = std::make_unique<mojo::StringDataPipeProducer>(
@@ -487,6 +489,11 @@ class FileSystemFileURLLoader : public FileSystemEntryURLLoader {
int64_t bytes_to_read = std::min(
static_cast<int64_t>(kDefaultFileSystemUrlPipeSize), remaining_bytes_);
if (!bytes_to_read) {
+ if (consumer_handle_.is_valid()) {
+ // This was an empty file; make sure to call OnReceiveResponse
+ // regardless.
+ client_->OnReceiveResponse(head_);
+ }
OnFileWritten(MOJO_RESULT_OK);
return;
}
@@ -517,7 +524,7 @@ class FileSystemFileURLLoader : public FileSystemEntryURLLoader {
&head_.mime_type);
}
- client_->OnReceiveResponse(head_, /*downloaded_file=*/nullptr);
+ client_->OnReceiveResponse(head_);
client_->OnStartLoadingResponseBody(std::move(consumer_handle_));
}
remaining_bytes_ -= result;
diff --git a/chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc b/chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc
index 79fd580333d..82cfc2765d2 100644
--- a/chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc
+++ b/chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc
@@ -34,6 +34,7 @@
#include "storage/browser/test/mock_special_storage_policy.h"
#include "storage/browser/test/test_file_system_backend.h"
#include "storage/browser/test/test_file_system_context.h"
+#include "storage/browser/test/test_file_system_options.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/icu/source/i18n/unicode/datefmt.h"
#include "third_party/icu/source/i18n/unicode/regex.h"
@@ -154,25 +155,27 @@ void ShutdownFileSystemContextOnIOThread(
class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
protected:
- FileSystemURLLoaderFactoryTest() : weak_factory_(this) {}
+ FileSystemURLLoaderFactoryTest() {}
~FileSystemURLLoaderFactoryTest() override = default;
void SetUpOnMainThread() override {
feature_list_.InitAndEnableFeature(network::features::kNetworkService);
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-
special_storage_policy_ = new MockSpecialStoragePolicy;
+
+ // We use a test FileSystemContext which runs on the main thread, so we
+ // can work with it synchronously.
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
file_system_context_ =
CreateFileSystemContextForTesting(nullptr, temp_dir_.GetPath());
-
- // We use the main thread so that we can get the root path synchronously.
+ base::RunLoop run_loop;
file_system_context_->OpenFileSystem(
GURL("http://remote/"), storage::kFileSystemTypeTemporary,
storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::BindOnce(&FileSystemURLLoaderFactoryTest::OnOpenFileSystem,
- weak_factory_.GetWeakPtr()));
- base::RunLoop().RunUntilIdle();
+ run_loop.QuitWhenIdleClosure()));
+ run_loop.Run();
+
ContentBrowserTest::SetUpOnMainThread();
}
@@ -333,6 +336,14 @@ class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
network::mojom::URLLoaderPtr loader_;
private:
+ static void OnOpenFileSystem(base::OnceClosure done_closure,
+ const GURL& root_url,
+ const std::string& name,
+ base::File::Error result) {
+ ASSERT_EQ(base::File::FILE_OK, result);
+ std::move(done_closure).Run();
+ }
+
storage::FileSystemFileUtil* file_util() {
return file_system_context_->sandbox_delegate()->sync_file_util();
}
@@ -344,12 +355,6 @@ class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
return context;
}
- void OnOpenFileSystem(const GURL& root_url,
- const std::string& name,
- base::File::Error result) {
- ASSERT_EQ(base::File::FILE_OK, result);
- }
-
RenderFrameHost* render_frame_host() const {
return shell()->web_contents()->GetMainFrame();
}
@@ -393,7 +398,6 @@ class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
base::test::ScopedFeatureList feature_list_;
scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
scoped_refptr<FileSystemContext> file_system_context_;
- base::WeakPtrFactory<FileSystemURLLoaderFactoryTest> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(FileSystemURLLoaderFactoryTest);
};
diff --git a/chromium/content/browser/find_request_manager_browsertest.cc b/chromium/content/browser/find_request_manager_browsertest.cc
index c639245949f..f0d21d59c56 100644
--- a/chromium/content/browser/find_request_manager_browsertest.cc
+++ b/chromium/content/browser/find_request_manager_browsertest.cc
@@ -328,14 +328,9 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(CharacterByCharacter)) {
// TODO(crbug.com/615291): This test frequently fails on Android.
// TODO(crbug.com/674742): This test is flaky on Win
-#if defined(OS_ANDROID) || defined(OS_WIN)
-#define MAYBE_RapidFire DISABLED_RapidFire
-#else
-#define MAYBE_RapidFire RapidFire
-#endif
-
+// TODO(crbug.com/850286): Flaky on CrOS MSan
// Tests sending a large number of find requests subsequently.
-IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE_RapidFire) {
+IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_RapidFire) {
LoadAndWait("/find_in_page.html");
if (GetParam())
MakeChildFrameCrossProcess();
diff --git a/chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc b/chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc
index f25ed52f307..af837fc7f06 100644
--- a/chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc
+++ b/chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc
@@ -450,12 +450,12 @@ class BlockedSchemeNavigationBrowserTest
DownloadManager* download_manager = BrowserContext::GetDownloadManager(
shell()->web_contents()->GetBrowserContext());
- EXPECT_TRUE(ExecuteScript(rfh, javascript));
- Shell* new_shell = new_shell_observer.GetShell();
-
DownloadTestObserverTerminal download_observer(
download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
+ EXPECT_TRUE(ExecuteScript(rfh, javascript));
+ Shell* new_shell = new_shell_observer.GetShell();
+
WaitForLoadStop(new_shell->web_contents());
// If no download happens, this will timeout.
download_observer.WaitForFinished();
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 337d713ddfa..1017d3ce539 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
@@ -118,7 +118,7 @@ void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view) {
if (is_hidden_)
OnVisibilityChanged(false);
FrameMsg_ViewChanged_Params params;
- if (!base::FeatureList::IsEnabled(::features::kMash))
+ if (features::IsAshInBrowserProcess())
params.frame_sink_id = view_->GetFrameSinkId();
frame_proxy_in_parent_renderer_->Send(new FrameMsg_ViewChanged(
frame_proxy_in_parent_renderer_->GetRoutingID(), params));
@@ -145,9 +145,9 @@ void CrossProcessFrameConnector::RenderProcessGone() {
frame_proxy_in_parent_renderer_->GetRoutingID()));
}
-void CrossProcessFrameConnector::SetChildFrameSurface(
+void CrossProcessFrameConnector::FirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
- frame_proxy_in_parent_renderer_->Send(new FrameMsg_SetChildFrameSurface(
+ frame_proxy_in_parent_renderer_->Send(new FrameMsg_FirstSurfaceActivation(
frame_proxy_in_parent_renderer_->GetRoutingID(), surface_info));
}
@@ -229,14 +229,30 @@ void CrossProcessFrameConnector::ForwardProcessAckedTouchEvent(
const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) {
auto* main_view = GetRootRenderWidgetHostView();
+ // Note that the event's coordinates are in |view_|'s coordinate space, but
+ // since |ProcessAckedTouchEvent| doesn't use the coordinates, we don't
+ // bother to transform them back to the root coordinate space.
if (main_view)
main_view->ProcessAckedTouchEvent(touch, ack_result);
}
+void CrossProcessFrameConnector::ForwardAckedTouchpadPinchGestureEvent(
+ const blink::WebGestureEvent& event,
+ InputEventAckState ack_result) {
+ auto* root_view = GetRootRenderWidgetHostView();
+ if (!root_view)
+ return;
+
+ blink::WebGestureEvent pinch_event(event);
+ const gfx::PointF root_point =
+ view_->TransformPointToRootCoordSpaceF(event.PositionInWidget());
+ pinch_event.SetPositionInWidget(root_point);
+ root_view->GestureEventAck(pinch_event, ack_result);
+}
+
void CrossProcessFrameConnector::BubbleScrollEvent(
const blink::WebGestureEvent& event) {
- DCHECK((view_->wheel_scroll_latching_enabled() &&
- event.GetType() == blink::WebInputEvent::kGestureScrollBegin) ||
+ DCHECK(event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
event.GetType() == blink::WebInputEvent::kGestureFlingStart);
@@ -255,28 +271,19 @@ void CrossProcessFrameConnector::BubbleScrollEvent(
const gfx::PointF root_point =
view_->TransformPointToRootCoordSpaceF(event.PositionInWidget());
resent_gesture_event.SetPositionInWidget(root_point);
-
- if (view_->wheel_scroll_latching_enabled()) {
- if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
- event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
- is_scroll_bubbling_ = true;
- } else if (is_scroll_bubbling_) {
- event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
- }
- if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
- event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
- is_scroll_bubbling_ = false;
- }
- } else { // !view_->wheel_scroll_latching_enabled()
- if (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate) {
- event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
- is_scroll_bubbling_ = true;
- } else if ((event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
- event.GetType() == blink::WebInputEvent::kGestureFlingStart) &&
- is_scroll_bubbling_) {
- event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
- is_scroll_bubbling_ = false;
- }
+ // When a gesture event is bubbled to the parent frame, set the allowed touch
+ // action of the parent frame to Auto so that this gesture event is allowed.
+ parent_view->host()->input_router()->ForceSetTouchActionAuto();
+
+ if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
+ event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
+ is_scroll_bubbling_ = true;
+ } else if (is_scroll_bubbling_) {
+ event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_);
+ }
+ if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
+ event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
+ is_scroll_bubbling_ = false;
}
}
@@ -313,8 +320,8 @@ void CrossProcessFrameConnector::OnSynchronizeVisualProperties(
// the viz::LocalSurfaceId must also change.
if ((last_received_local_frame_size_ != visual_properties.local_frame_size ||
screen_info_ != visual_properties.screen_info ||
- capture_sequence_number() !=
- visual_properties.capture_sequence_number) &&
+ capture_sequence_number() != visual_properties.capture_sequence_number ||
+ last_received_zoom_level_ != visual_properties.zoom_level) &&
local_surface_id_ == surface_id.local_surface_id()) {
bad_message::ReceivedBadMessage(
frame_proxy_in_parent_renderer_->GetProcess(),
@@ -322,6 +329,7 @@ void CrossProcessFrameConnector::OnSynchronizeVisualProperties(
return;
}
+ last_received_zoom_level_ = visual_properties.zoom_level;
last_received_local_frame_size_ = visual_properties.local_frame_size;
SynchronizeVisualProperties(surface_id, visual_properties);
}
@@ -544,6 +552,16 @@ void CrossProcessFrameConnector::MaybeLogCrash(CrashVisibility visibility) {
// Actually log the UMA.
UMA_HISTOGRAM_ENUMERATION("Stability.ChildFrameCrash.Visibility", visibility);
+
+ if (visibility == CrashVisibility::kShownAfterCrashing) {
+ auto* rfh = frame_proxy_in_parent_renderer_->frame_tree_node()
+ ->current_frame_host();
+ if (rfh->GetParent() && rfh->is_local_root()) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "RenderFrameHostImpl.ReceivedPostMessageFromNonDescendant",
+ rfh->received_post_message_from_non_descendant());
+ }
+ }
}
bool CrossProcessFrameConnector::IsVisible() {
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 21759b18be7..b0dc031915c 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.h
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.h
@@ -77,7 +77,7 @@ class CONTENT_EXPORT CrossProcessFrameConnector
RenderWidgetHostViewBase* GetParentRenderWidgetHostView() override;
RenderWidgetHostViewBase* GetRootRenderWidgetHostView() override;
void RenderProcessGone() override;
- void SetChildFrameSurface(const viz::SurfaceInfo& surface_info) override;
+ void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
void SendIntrinsicSizingInfoToParent(
const blink::WebIntrinsicSizingInfo&) override;
@@ -98,6 +98,9 @@ class CONTENT_EXPORT CrossProcessFrameConnector
viz::EventSource source = viz::EventSource::ANY) override;
void ForwardProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) override;
+ void ForwardAckedTouchpadPinchGestureEvent(
+ const blink::WebGestureEvent& event,
+ InputEventAckState ack_result) override;
void BubbleScrollEvent(const blink::WebGestureEvent& event) override;
bool HasFocus() override;
void FocusRootView() override;
@@ -198,6 +201,10 @@ class CONTENT_EXPORT CrossProcessFrameConnector
// off.
gfx::Size last_received_local_frame_size_;
+ // The last zoom level received from parent renderer, which is used to check
+ // if a new surface is created in case of zoom level change.
+ double last_received_zoom_level_ = 0.0;
+
DISALLOW_COPY_AND_ASSIGN(CrossProcessFrameConnector);
};
diff --git a/chromium/content/browser/frame_host/frame_navigation_entry.h b/chromium/content/browser/frame_host/frame_navigation_entry.h
index 50076c1af7e..ee599312d4a 100644
--- a/chromium/content/browser/frame_host/frame_navigation_entry.h
+++ b/chromium/content/browser/frame_host/frame_navigation_entry.h
@@ -88,11 +88,15 @@ class CONTENT_EXPORT FrameNavigationEntry
void set_document_sequence_number(int64_t document_sequence_number);
int64_t document_sequence_number() const { return document_sequence_number_; }
- // The SiteInstance responsible for rendering this frame. All frames sharing
- // 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.
+ // The SiteInstance, as assigned at commit time, responsible for rendering
+ // this frame. All frames sharing 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.
+ // TODO(nasko, creis): The SiteInstance of a FrameNavigationEntry should
+ // not change once it has been assigned. See https://crbug.com/849430.
void set_site_instance(scoped_refptr<SiteInstanceImpl> site_instance) {
+ CHECK(!site_instance_ || site_instance_ == 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 5f7134c4f2b..ed5a3d823ac 100644
--- a/chromium/content/browser/frame_host/frame_tree.cc
+++ b/chromium/content/browser/frame_host/frame_tree.cc
@@ -353,6 +353,7 @@ RenderViewHostImpl* FrameTree::CreateRenderViewHost(
SiteInstance* site_instance,
int32_t routing_id,
int32_t main_frame_routing_id,
+ int32_t widget_routing_id,
bool swapped_out,
bool hidden) {
RenderViewHostMap::iterator iter =
@@ -363,7 +364,8 @@ RenderViewHostImpl* FrameTree::CreateRenderViewHost(
RenderViewHostImpl* rvh =
static_cast<RenderViewHostImpl*>(RenderViewHostFactory::Create(
site_instance, render_view_delegate_, render_widget_delegate_,
- routing_id, main_frame_routing_id, swapped_out, hidden));
+ routing_id, main_frame_routing_id, widget_routing_id, swapped_out,
+ hidden));
render_view_host_map_[site_instance->GetId()] = rvh;
return rvh;
diff --git a/chromium/content/browser/frame_host/frame_tree.h b/chromium/content/browser/frame_host/frame_tree.h
index 3b24e06febd..248489e5aa5 100644
--- a/chromium/content/browser/frame_host/frame_tree.h
+++ b/chromium/content/browser/frame_host/frame_tree.h
@@ -183,6 +183,7 @@ class CONTENT_EXPORT FrameTree {
RenderViewHostImpl* CreateRenderViewHost(SiteInstance* site_instance,
int32_t routing_id,
int32_t main_frame_routing_id,
+ int32_t widget_routing_id,
bool swapped_out,
bool hidden);
diff --git a/chromium/content/browser/frame_host/frame_tree_node.cc b/chromium/content/browser/frame_host/frame_tree_node.cc
index a99f5ab0ee5..46e3d2a7678 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.cc
+++ b/chromium/content/browser/frame_host/frame_tree_node.cc
@@ -24,6 +24,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
+#include "third_party/blink/public/common/frame/user_activation_update_type.h"
namespace content {
@@ -466,8 +467,9 @@ void FrameTreeNode::ResetNavigationRequest(bool keep_state,
// The renderer should be informed if the caller allows to do so and the
// navigation came from a BeginNavigation IPC.
- int need_to_inform_renderer =
- inform_renderer && navigation_request_->from_begin_navigation();
+ bool need_to_inform_renderer =
+ !IsPerNavigationMojoInterfaceEnabled() & inform_renderer &&
+ navigation_request_->from_begin_navigation();
NavigationRequest::AssociatedSiteInstanceType site_instance_type =
navigation_request_->associated_site_instance_type();
@@ -597,9 +599,31 @@ void FrameTreeNode::BeforeUnloadCanceled() {
ResetNavigationRequest(false, true);
}
-void FrameTreeNode::OnSetHasReceivedUserGesture() {
- render_manager_.OnSetHasReceivedUserGesture();
+bool FrameTreeNode::NotifyUserActivation() {
+ for (FrameTreeNode* node = this; node; node = node->parent())
+ node->user_activation_state_.Activate();
replication_state_.has_received_user_gesture = true;
+ return true;
+}
+
+bool FrameTreeNode::ConsumeTransientUserActivation() {
+ bool was_active = user_activation_state_.IsActive();
+ for (FrameTreeNode* node : frame_tree()->Nodes())
+ node->user_activation_state_.ConsumeIfActive();
+ return was_active;
+}
+
+bool FrameTreeNode::UpdateUserActivationState(
+ blink::UserActivationUpdateType update_type) {
+ render_manager_.UpdateUserActivationState(update_type);
+ switch (update_type) {
+ case blink::UserActivationUpdateType::kConsumeTransientActivation:
+ return ConsumeTransientUserActivation();
+
+ case blink::UserActivationUpdateType::kNotifyActivation:
+ return NotifyUserActivation();
+ }
+ NOTREACHED() << "Invalid update_type.";
}
void FrameTreeNode::OnSetHasReceivedUserGestureBeforeNavigation(bool value) {
diff --git a/chromium/content/browser/frame_host/frame_tree_node.h b/chromium/content/browser/frame_host/frame_tree_node.h
index db49e3691d9..4e589ac428f 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.h
+++ b/chromium/content/browser/frame_host/frame_tree_node.h
@@ -21,6 +21,8 @@
#include "content/common/frame_owner_properties.h"
#include "content/common/frame_replication_state.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
+#include "third_party/blink/public/common/frame/user_activation_state.h"
+#include "third_party/blink/public/common/frame/user_activation_update_type.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -342,7 +344,13 @@ class CONTENT_EXPORT FrameTreeNode {
// Returns the BlameContext associated with this node.
FrameTreeNodeBlameContext& blame_context() { return blame_context_; }
- void OnSetHasReceivedUserGesture();
+ // Updates the user activation state in the browser frame tree and in the
+ // frame trees in all renderer processes except the renderer for this node
+ // (which initiated the update). Returns |false| if the update tries to
+ // consume an already consumed/expired transient state, |true| otherwise. See
+ // the comment on user_activation_state_ below.
+ bool UpdateUserActivationState(blink::UserActivationUpdateType update_type);
+
void OnSetHasReceivedUserGestureBeforeNavigation(bool value);
// Returns the sandbox flags currently in effect for this frame. This includes
@@ -380,6 +388,18 @@ class CONTENT_EXPORT FrameTreeNode {
// request and reset to false in FrameTreeNode.
void set_was_discarded() { was_discarded_ = true; }
+ // Returns the sticky bit of the User Activation v2 state of the
+ // |FrameTreeNode|.
+ bool HasBeenActivated() const {
+ return user_activation_state_.HasBeenActive();
+ }
+
+ // Returns the transient bit of the User Activation v2 state of the
+ // |FrameTreeNode|.
+ bool HasTransientUserActivation() {
+ return user_activation_state_.IsActive();
+ }
+
private:
FRIEND_TEST_ALL_PREFIXES(SitePerProcessFeaturePolicyBrowserTest,
ContainerPolicyDynamic);
@@ -390,6 +410,10 @@ class CONTENT_EXPORT FrameTreeNode {
FrameTreeNode* GetSibling(int relative_offset) const;
+ bool NotifyUserActivation();
+
+ bool ConsumeTransientUserActivation();
+
// The next available browser-global FrameTreeNode ID.
static int next_frame_tree_node_id_;
@@ -492,6 +516,34 @@ class CONTENT_EXPORT FrameTreeNode {
bool was_discarded_;
+ // The user activation state of the current frame.
+ //
+ // Changes to this state update other FrameTreeNodes as follows: for
+ // notification updates (on user inputs) all ancestor nodes are updated; for
+ // activation consumption calls, the whole frame tree is updated (w/o such
+ // exhaustive consumption, a rouge iframe can cause multiple consumptions per
+ // user activation).
+ //
+ // The user activation state is replicated in the browser process (in
+ // FrameTreeNode) and in the renderer processes (in LocalFrame and
+ // RemoteFrames). The replicated states across the browser and renderer
+ // processes are kept in sync as follows:
+ //
+ // [A] Consumption of activation state for popups starts in the frame tree of
+ // the browser process and propagate to the renderer trees through direct IPCs
+ // (one IPC sent to each renderer).
+ //
+ // [B] Consumption calls from JS/blink side (e.g. video picture-in-picture)
+ // update the originating renderer's local frame tree and send an IPC to the
+ // browser; the browser updates its frame tree and sends IPCs to all other
+ // renderers each of which then updates its local frame tree.
+ //
+ // [B'] Notification updates on user inputs still follow [B] but they should
+ // really follow [A]. TODO(mustaq): fix through https://crbug.com/848778.
+ //
+ // [C] Expiration of an active state is tracked independently in each process.
+ blink::UserActivationState user_activation_state_;
+
// A helper for tracing the snapshots of this FrameTreeNode and attributing
// browser process activities to this node (when possible). It is unrelated
// to the core logic of FrameTreeNode.
diff --git a/chromium/content/browser/frame_host/frame_tree_unittest.cc b/chromium/content/browser/frame_host/frame_tree_unittest.cc
index 40a35831d96..015150461cd 100644
--- a/chromium/content/browser/frame_host/frame_tree_unittest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors.All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -159,7 +159,7 @@ TEST_F(FrameTreeTest, Shape) {
// itself. Instead, leave them in "not live" state, which is indicated by the
// * after the frame id, since this test cares about the shape, not the
// frame liveness.
- EXPECT_EQ("2: []", GetTreeState(frame_tree));
+ EXPECT_EQ("3: []", GetTreeState(frame_tree));
// Simulate attaching a series of frames to build the frame tree.
frame_tree->AddFrame(root, process_id, 14,
@@ -194,7 +194,7 @@ TEST_F(FrameTreeTest, Shape) {
blink::FramePolicy(), FrameOwnerProperties(), false);
EXPECT_EQ(
- "2: [14: [244: [], 245: []], "
+ "3: [14: [244: [], 245: []], "
"15: [255 'no children node': []], "
"16: []]",
GetTreeState(frame_tree));
@@ -250,7 +250,7 @@ TEST_F(FrameTreeTest, Shape) {
// Now that's it's fully built, verify the tree structure is as expected.
EXPECT_EQ(
- "2: [14: [244: [], 245: []], "
+ "3: [14: [244: [], 245: []], "
"15: [255 'no children node': []], "
"16: [264: [], 265: [], 266: [], "
"267 'node with deep subtree': "
@@ -264,27 +264,27 @@ TEST_F(FrameTreeTest, Shape) {
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",
+ EXPECT_EQ("3 14 15 16 244 245 255 264 265 266 267 268 365 455 555 655",
GetTraversalOrder(frame_tree, nullptr));
- EXPECT_EQ("2", GetTraversalOrder(frame_tree, root));
- EXPECT_EQ("2 14 15 16 255 264 265 266 267 268 365 455 555 655",
+ EXPECT_EQ("3", GetTraversalOrder(frame_tree, root));
+ EXPECT_EQ("3 14 15 16 255 264 265 266 267 268 365 455 555 655",
GetTraversalOrder(frame_tree, child_14));
- EXPECT_EQ("2 14 15 16 244 245 255 264 265 266 267 268 365 455 555 655",
+ EXPECT_EQ("3 14 15 16 244 245 255 264 265 266 267 268 365 455 555 655",
GetTraversalOrder(frame_tree, child_244));
- EXPECT_EQ("2 14 15 16 244 245 255 264 265 266 267 268 365 455 555 655",
+ EXPECT_EQ("3 14 15 16 244 245 255 264 265 266 267 268 365 455 555 655",
GetTraversalOrder(frame_tree, child_245));
- EXPECT_EQ("2 14 15 16 244 245 264 265 266 267 268 365 455 555 655",
+ EXPECT_EQ("3 14 15 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 267 268",
+ EXPECT_EQ("3 14 15 16 244 245 255 264 265 266 267 268",
GetTraversalOrder(frame_tree, child_267));
- EXPECT_EQ("2 14 15 16 244 245 255 264 265 266 267 268 365 455 555",
+ EXPECT_EQ("3 14 15 16 244 245 255 264 265 266 267 268 365 455 555",
GetTraversalOrder(frame_tree, child_555));
- EXPECT_EQ("2 14 15 16 244 245 255 264 265 266 267 268 365 455 555 655",
+ EXPECT_EQ("3 14 15 16 244 245 255 264 265 266 267 268 365 455 555 655",
GetTraversalOrder(frame_tree, child_655));
frame_tree->RemoveFrame(child_555);
EXPECT_EQ(
- "2: [14: [244: [], 245: []], "
+ "3: [14: [244: [], 245: []], "
"15: [255 'no children node': []], "
"16: [264: [], 265: [], 266: [], "
"267 'node with deep subtree': "
@@ -293,7 +293,7 @@ TEST_F(FrameTreeTest, Shape) {
frame_tree->RemoveFrame(child_16->child_at(1));
EXPECT_EQ(
- "2: [14: [244: [], 245: []], "
+ "3: [14: [244: [], 245: []], "
"15: [255 'no children node': []], "
"16: [264: [], 266: [], "
"267 'node with deep subtree': "
@@ -302,7 +302,7 @@ TEST_F(FrameTreeTest, Shape) {
frame_tree->RemoveFrame(root->child_at(1));
EXPECT_EQ(
- "2: [14: [244: [], 245: []], "
+ "3: [14: [244: [], 245: []], "
"16: [264: [], 266: [], "
"267 'node with deep subtree': "
"[365: [455: []]], 268: []]]",
@@ -424,7 +424,7 @@ TEST_F(FrameTreeTest, GetSibling) {
TEST_F(FrameTreeTest, ObserverWalksTreeDuringFrameCreation) {
TreeWalkingWebContentsLogger activity(contents());
contents()->NavigateAndCommit(GURL("http://www.google.com"));
- EXPECT_EQ("RenderFrameCreated(2) -> 2: []", activity.GetLog());
+ EXPECT_EQ("RenderFrameCreated(3) -> 3: []", activity.GetLog());
FrameTree* frame_tree = contents()->GetFrameTree();
FrameTreeNode* root = frame_tree->root();
@@ -436,8 +436,8 @@ TEST_F(FrameTreeTest, ObserverWalksTreeDuringFrameCreation) {
base::UnguessableToken::Create(), blink::FramePolicy(),
FrameOwnerProperties());
EXPECT_EQ(
- "RenderFrameHostChanged(new)(14) -> 2: []\n"
- "RenderFrameCreated(14) -> 2: [14: []]",
+ "RenderFrameHostChanged(new)(14) -> 3: []\n"
+ "RenderFrameCreated(14) -> 3: [14: []]",
activity.GetLog());
main_test_rfh()->OnCreateChildFrame(
18, CreateStubInterfaceProviderRequest(),
@@ -445,13 +445,13 @@ TEST_F(FrameTreeTest, ObserverWalksTreeDuringFrameCreation) {
base::UnguessableToken::Create(), blink::FramePolicy(),
FrameOwnerProperties());
EXPECT_EQ(
- "RenderFrameHostChanged(new)(18) -> 2: [14: []]\n"
- "RenderFrameCreated(18) -> 2: [14: [], 18: []]",
+ "RenderFrameHostChanged(new)(18) -> 3: [14: []]\n"
+ "RenderFrameCreated(18) -> 3: [14: [], 18: []]",
activity.GetLog());
frame_tree->RemoveFrame(root->child_at(0));
- EXPECT_EQ("RenderFrameDeleted(14) -> 2: [18: []]", activity.GetLog());
+ EXPECT_EQ("RenderFrameDeleted(14) -> 3: [18: []]", activity.GetLog());
frame_tree->RemoveFrame(root->child_at(0));
- EXPECT_EQ("RenderFrameDeleted(18) -> 2: []", activity.GetLog());
+ EXPECT_EQ("RenderFrameDeleted(18) -> 3: []", activity.GetLog());
}
// Make sure that WebContentsObservers see a consistent view of the tree after
@@ -459,7 +459,7 @@ TEST_F(FrameTreeTest, ObserverWalksTreeDuringFrameCreation) {
TEST_F(FrameTreeTest, ObserverWalksTreeAfterCrash) {
TreeWalkingWebContentsLogger activity(contents());
contents()->NavigateAndCommit(GURL("http://www.google.com"));
- EXPECT_EQ("RenderFrameCreated(2) -> 2: []", activity.GetLog());
+ EXPECT_EQ("RenderFrameCreated(3) -> 3: []", activity.GetLog());
main_test_rfh()->OnCreateChildFrame(
22, CreateStubInterfaceProviderRequest(),
@@ -467,8 +467,8 @@ TEST_F(FrameTreeTest, ObserverWalksTreeAfterCrash) {
base::UnguessableToken::Create(), blink::FramePolicy(),
FrameOwnerProperties());
EXPECT_EQ(
- "RenderFrameHostChanged(new)(22) -> 2: []\n"
- "RenderFrameCreated(22) -> 2: [22: []]",
+ "RenderFrameHostChanged(new)(22) -> 3: []\n"
+ "RenderFrameCreated(22) -> 3: [22: []]",
activity.GetLog());
main_test_rfh()->OnCreateChildFrame(
23, CreateStubInterfaceProviderRequest(),
@@ -476,17 +476,17 @@ TEST_F(FrameTreeTest, ObserverWalksTreeAfterCrash) {
base::UnguessableToken::Create(), blink::FramePolicy(),
FrameOwnerProperties());
EXPECT_EQ(
- "RenderFrameHostChanged(new)(23) -> 2: [22: []]\n"
- "RenderFrameCreated(23) -> 2: [22: [], 23: []]",
+ "RenderFrameHostChanged(new)(23) -> 3: [22: []]\n"
+ "RenderFrameCreated(23) -> 3: [22: [], 23: []]",
activity.GetLog());
// Crash the renderer
main_test_rfh()->GetProcess()->SimulateCrash();
EXPECT_EQ(
- "RenderProcessGone -> 2*: [22*: [], 23*: []]\n"
- "RenderFrameDeleted(23) -> 2*: [22*: [], 23*: []]\n"
- "RenderFrameDeleted(22) -> 2*: [22*: [], 23*: []]\n"
- "RenderFrameDeleted(2) -> 2*: []",
+ "RenderProcessGone -> 3*: [22*: [], 23*: []]\n"
+ "RenderFrameDeleted(23) -> 3*: [22*: [], 23*: []]\n"
+ "RenderFrameDeleted(22) -> 3*: [22*: [], 23*: []]\n"
+ "RenderFrameDeleted(3) -> 3*: []",
activity.GetLog());
}
@@ -498,7 +498,7 @@ TEST_F(FrameTreeTest, FailAddFrameWithWrongProcessId) {
FrameTreeNode* root = frame_tree->root();
int process_id = root->current_frame_host()->GetProcess()->GetID();
- ASSERT_EQ("2: []", GetTreeState(frame_tree));
+ ASSERT_EQ("3: []", GetTreeState(frame_tree));
// Simulate attaching a frame from mismatched process id.
ASSERT_FALSE(frame_tree->AddFrame(
@@ -506,7 +506,7 @@ TEST_F(FrameTreeTest, FailAddFrameWithWrongProcessId) {
blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0", false,
base::UnguessableToken::Create(), blink::FramePolicy(),
FrameOwnerProperties(), false));
- ASSERT_EQ("2: []", GetTreeState(frame_tree));
+ ASSERT_EQ("3: []", GetTreeState(frame_tree));
}
// Ensure that frames removed while a process has crashed are not preserved in
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index ad9de41d1e3..f839f62061b 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -607,12 +607,9 @@ RenderViewHostImpl* InterstitialPageImpl::CreateRenderViewHost() {
SessionStorageNamespaceImpl::Create(dom_storage_context);
// Use the RenderViewHost from our FrameTree.
- // TODO(avi): The view routing ID can be restored to MSG_ROUTING_NONE once
- // RenderViewHostImpl has-a RenderWidgetHostImpl. https://crbug.com/545684
- int32_t widget_routing_id = site_instance->GetProcess()->GetNextRoutingID();
frame_tree_->root()->render_manager()->Init(
- site_instance.get(), widget_routing_id, MSG_ROUTING_NONE,
- widget_routing_id, false);
+ site_instance.get(), MSG_ROUTING_NONE, MSG_ROUTING_NONE, MSG_ROUTING_NONE,
+ false);
return frame_tree_->root()->current_frame_host()->render_view_host();
}
diff --git a/chromium/content/browser/frame_host/navigation_controller_delegate.h b/chromium/content/browser/frame_host/navigation_controller_delegate.h
index 1b9f0c935c7..64c22ec9869 100644
--- a/chromium/content/browser/frame_host/navigation_controller_delegate.h
+++ b/chromium/content/browser/frame_host/navigation_controller_delegate.h
@@ -11,6 +11,7 @@
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_details.h"
+#include "content/public/common/previews_state.h"
namespace content {
@@ -69,6 +70,14 @@ class NavigationControllerDelegate {
virtual void DetachInterstitialPage(bool has_focus) = 0;
virtual void UpdateOverridingUserAgent() = 0;
+
+ // Gives the delegate a chance to adjust the previews state during navigation.
+ // When called, previews_state will be pointing to a valid set of previews, or
+ // an enum value disabling previews. The call will change the value of
+ // previews_state in place, and must change it to either a value disabling
+ // previews, or a subset of the previews passed in.
+ virtual void AdjustPreviewsStateForNavigation(
+ PreviewsState* previews_state) = 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 74ff6b4286c..d8aca9e2cbf 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc
@@ -50,6 +50,7 @@
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "content/browser/bad_message.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browser_url_handler_impl.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
@@ -80,6 +81,7 @@
#include "media/base/mime_util.h"
#include "net/base/escape.h"
#include "skia/ext/platform_canvas.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "url/url_constants.h"
@@ -230,6 +232,60 @@ void CopyReplacedNavigationEntryDataIfPreviouslyEmpty(
output_entry->SetReplacedEntryData(data);
}
+FrameMsg_Navigate_Type::Value GetNavigationType(
+ const GURL& old_url,
+ const GURL& new_url,
+ ReloadType reload_type,
+ const NavigationEntryImpl& entry,
+ const FrameNavigationEntry& frame_entry,
+ bool is_same_document_history_load) {
+ // Reload navigations
+ switch (reload_type) {
+ case ReloadType::NORMAL:
+ return FrameMsg_Navigate_Type::RELOAD;
+ case ReloadType::BYPASSING_CACHE:
+ return FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE;
+ case ReloadType::ORIGINAL_REQUEST_URL:
+ return FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
+ case ReloadType::NONE:
+ break; // Fall through to rest of function.
+ }
+
+ if (entry.restore_type() == RestoreType::LAST_SESSION_EXITED_CLEANLY) {
+ if (entry.GetHasPostData())
+ return FrameMsg_Navigate_Type::RESTORE_WITH_POST;
+ else
+ return FrameMsg_Navigate_Type::RESTORE;
+ }
+
+ // History navigations.
+ if (frame_entry.page_state().IsValid()) {
+ if (is_same_document_history_load)
+ return FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT;
+ else
+ return FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
+ }
+ DCHECK(!is_same_document_history_load);
+
+ // A same-document fragment-navigation happens when the only part of the url
+ // that is modified is after the '#' character.
+ //
+ // When modifying this condition, please take a look at:
+ // FrameLoader::shouldPerformFragmentNavigation.
+ //
+ // Note: this check is only valid for navigations that are not history
+ // navigations. For instance, if the history is: 'A#bar' -> 'B' -> 'A#foo', a
+ // history navigation from 'A#foo' to 'A#bar' is not a same-document
+ // navigation, but a different-document one. This is why history navigation
+ // are classified before this check.
+ if (new_url.has_ref() && old_url.EqualsIgnoringRef(new_url) &&
+ frame_entry.method() == "GET") {
+ return FrameMsg_Navigate_Type::SAME_DOCUMENT;
+ } else {
+ return FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
+ }
+}
+
} // namespace
// NavigationControllerImpl ----------------------------------------------------
@@ -433,43 +489,11 @@ void NavigationControllerImpl::Reload(ReloadType reload_type,
if (!IsInitialNavigation())
DiscardNonCommittedEntriesInternal();
- // If we are reloading an entry that no longer belongs to the current
- // SiteInstance (for example, refreshing a page for just installed app), the
- // reload must happen in a new process. The new entry behaves as new
- // navigation (which happens to clear forward history). Tabs that are
- // discarded due to low memory conditions may not have a SiteInstance, and
- // should not be treated as a cross-site reload.
- SiteInstanceImpl* site_instance = entry->site_instance();
- // Permit reloading guests without further checks.
- bool is_for_guests_only = site_instance && site_instance->HasProcess() &&
- site_instance->GetProcess()->IsForGuestsOnly();
- if (!is_for_guests_only && site_instance &&
- site_instance->HasWrongProcessForURL(entry->GetURL())) {
- // Create a navigation entry that resembles the current one, but do not
- // copy page id, site instance, content state, or timestamp.
- NavigationEntryImpl* nav_entry = NavigationEntryImpl::FromNavigationEntry(
- CreateNavigationEntry(entry->GetURL(), entry->GetReferrer(),
- entry->GetTransitionType(), false,
- entry->extra_headers(), browser_context_,
- nullptr /* blob_url_loader_factory */)
- .release());
-
- // Mark the reload type as NO_RELOAD, so navigation will not be considered
- // a reload in the renderer.
- reload_type = ReloadType::NONE;
-
- nav_entry->set_should_replace_entry(true);
- nav_entry->set_is_renderer_initiated(entry->is_renderer_initiated());
- pending_entry_ = nav_entry;
- DCHECK_EQ(-1, pending_entry_index_);
- } else {
- pending_entry_ = entry;
- pending_entry_index_ = current_index;
-
- pending_entry_->SetTransitionType(ui::PAGE_TRANSITION_RELOAD);
- }
+ pending_entry_ = entry;
+ pending_entry_index_ = current_index;
+ pending_entry_->SetTransitionType(ui::PAGE_TRANSITION_RELOAD);
- NavigateToPendingEntry(reload_type, nullptr /* navigation_ui_data */);
+ NavigateToExistingPendingEntry(reload_type);
}
}
@@ -504,18 +528,6 @@ NavigationControllerImpl::GetEntryWithUniqueID(int nav_entry_id) const {
return (index != -1) ? entries_[index].get() : nullptr;
}
-void NavigationControllerImpl::LoadEntry(
- std::unique_ptr<NavigationEntryImpl> entry,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
- DiscardPendingEntry(false);
-
- // When navigating to a new page, we don't know for sure if we will actually
- // end up leaving the current page. The new page load could for example
- // result in a download or a 'no content' response (e.g., a mailto: URL).
- SetPendingEntry(std::move(entry));
- NavigateToPendingEntry(ReloadType::NONE, std::move(navigation_ui_data));
-}
-
void NavigationControllerImpl::SetPendingEntry(
std::unique_ptr<NavigationEntryImpl> entry) {
DiscardNonCommittedEntriesInternal();
@@ -684,7 +696,7 @@ void NavigationControllerImpl::GoToIndex(int index) {
pending_entry_index_ = index;
pending_entry_->SetTransitionType(ui::PageTransitionFromInt(
pending_entry_->GetTransitionType() | ui::PAGE_TRANSITION_FORWARD_BACK));
- NavigateToPendingEntry(ReloadType::NONE, nullptr /* navigation_ui_data */);
+ NavigateToExistingPendingEntry(ReloadType::NONE);
}
void NavigationControllerImpl::GoToOffset(int offset) {
@@ -756,124 +768,7 @@ void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) {
// The user initiated a load, we don't need to reload anymore.
needs_reload_ = false;
- bool override = false;
- switch (params.override_user_agent) {
- case UA_OVERRIDE_INHERIT:
- override = ShouldKeepOverride(GetLastCommittedEntry());
- break;
- case UA_OVERRIDE_TRUE:
- override = true;
- break;
- case UA_OVERRIDE_FALSE:
- override = false;
- break;
- default:
- NOTREACHED();
- break;
- }
-
- std::unique_ptr<NavigationEntryImpl> entry;
-
- int frame_tree_node_id = params.frame_tree_node_id;
- // navigation_ui_data should only be present for main frame navigations.
- DCHECK(frame_tree_node_id == RenderFrameHost::kNoFrameTreeNodeId ||
- !params.navigation_ui_data);
-
- if (frame_tree_node_id != RenderFrameHost::kNoFrameTreeNodeId ||
- !params.frame_name.empty()) {
- FrameTreeNode* node =
- params.frame_tree_node_id != RenderFrameHost::kNoFrameTreeNodeId
- ? delegate_->GetFrameTree()->FindByID(params.frame_tree_node_id)
- : delegate_->GetFrameTree()->FindByName(params.frame_name);
- if (node && !node->IsMainFrame()) {
- DCHECK(GetLastCommittedEntry());
-
- // Update the FTN ID to use below in case we found a named frame.
- frame_tree_node_id = node->frame_tree_node_id();
-
- // Create an identical NavigationEntry with a new FrameNavigationEntry for
- // the target subframe.
- entry = GetLastCommittedEntry()->Clone();
- entry->AddOrUpdateFrameEntry(
- node, -1, -1, nullptr,
- static_cast<SiteInstanceImpl*>(params.source_site_instance.get()),
- params.url, params.referrer, params.redirect_chain, PageState(),
- "GET", -1, params.blob_url_loader_factory);
- }
- }
-
- // Otherwise, create a pending entry for the main frame.
- if (!entry) {
- // extra_headers in params are \n separated, navigation entries want \r\n.
- std::string extra_headers_crlf;
- base::ReplaceChars(params.extra_headers, "\n", "\r\n", &extra_headers_crlf);
- entry = NavigationEntryImpl::FromNavigationEntry(CreateNavigationEntry(
- params.url, params.referrer, params.transition_type,
- params.is_renderer_initiated, extra_headers_crlf, browser_context_,
- params.blob_url_loader_factory));
- entry->set_source_site_instance(
- static_cast<SiteInstanceImpl*>(params.source_site_instance.get()));
- entry->SetRedirectChain(params.redirect_chain);
- }
-
- // Set the FTN ID (only used in non-site-per-process, for tests).
- entry->set_frame_tree_node_id(frame_tree_node_id);
- // Don't allow an entry replacement if there is no entry to replace.
- // http://crbug.com/457149
- if (params.should_replace_current_entry && entries_.size() > 0)
- entry->set_should_replace_entry(true);
- entry->set_should_clear_history_list(params.should_clear_history_list);
- entry->SetIsOverridingUserAgent(override);
- entry->set_transferred_global_request_id(
- params.transferred_global_request_id);
-
-// Always propagate `has_user_gesture` on Android but only when the request
-// was originated by the renderer on other platforms. This is merely for
-// backward compatibility as browser process user gestures create confusion
-// in many tests.
-#if defined(OS_ANDROID)
- entry->set_has_user_gesture(params.has_user_gesture);
-#else
- if (params.is_renderer_initiated)
- entry->set_has_user_gesture(params.has_user_gesture);
-#endif
-
-#if defined(OS_ANDROID)
- if (params.intent_received_timestamp > 0) {
- entry->set_intent_received_timestamp(
- base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(params.intent_received_timestamp));
- }
-#endif
-
- switch (params.load_type) {
- case LOAD_TYPE_DEFAULT:
- break;
- case LOAD_TYPE_HTTP_POST:
- entry->SetHasPostData(true);
- entry->SetPostData(params.post_data);
- break;
- case LOAD_TYPE_DATA:
- entry->SetBaseURLForDataURL(params.base_url_for_data_url);
- entry->SetVirtualURL(params.virtual_url_for_data_url);
-#if defined(OS_ANDROID)
- entry->SetDataURLAsString(params.data_url_as_string);
-#endif
- entry->SetCanLoadLocalResources(params.can_load_local_resources);
- break;
- default:
- NOTREACHED();
- break;
- }
-
- // TODO(clamy): NavigationEntry is meant for information that will be kept
- // after the navigation ended and therefore is not appropriate for
- // started_from_context_menu. Move started_from_context_menu to
- // NavigationUIData.
- entry->set_started_from_context_menu(params.started_from_context_menu);
- LoadEntry(std::move(entry), params.navigation_ui_data
- ? params.navigation_ui_data->Clone()
- : nullptr);
+ NavigateWithoutEntry(params);
}
bool NavigationControllerImpl::PendingEntryMatchesHandle(
@@ -914,8 +809,25 @@ bool NavigationControllerImpl::RendererDidNavigate(
was_restored = true;
}
- // The renderer tells us whether the navigation replaces the current entry.
- details->did_replace_entry = params.should_replace_current_entry;
+ // If this is a navigation to a matching pending_entry_ and the SiteInstance
+ // has changed, this must be treated as a new navigation with replacement.
+ // Set the replacement bit here and ClassifyNavigation will identify this
+ // case and return NEW_PAGE.
+ if (!rfh->GetParent() && pending_entry_ &&
+ pending_entry_->GetUniqueID() == params.nav_entry_id &&
+ pending_entry_->site_instance() &&
+ pending_entry_->site_instance() != rfh->GetSiteInstance()) {
+ DCHECK_NE(-1, pending_entry_index_);
+ // TODO(nasko,creis): Instead of setting this value here, set
+ // should_replace_current_entry on the parameters we send to the
+ // renderer process as part of CommitNavigation. The renderer should
+ // in turn send it back here as part of |params| and it can be just
+ // enforced and renderer process terminated on mismatch.
+ details->did_replace_entry = true;
+ } else {
+ // 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);
@@ -1110,28 +1022,44 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
return NAVIGATION_TYPE_NAV_IGNORE;
// This is history.replaceState() or history.reload().
+ // TODO(nasko): With error page isolation, reloading an existing session
+ // history entry can result in change of SiteInstance. Check for such a case
+ // here and classify it as NEW_PAGE, as such navigations should be treated
+ // as new with replacement.
return NAVIGATION_TYPE_EXISTING_PAGE;
}
- if (pending_entry_ && pending_entry_index_ == -1 &&
- pending_entry_->GetUniqueID() == params.nav_entry_id) {
- // In this case, we have a pending entry for a load of a new URL but Blink
- // didn't do a new navigation (params.did_create_new_entry). First check to
- // make sure Blink didn't treat a new cross-process navigation as inert, and
- // thus set params.did_create_new_entry to false. In that case, we must
- // treat it as NEW since the SiteInstance doesn't match the entry.
- if (!GetLastCommittedEntry() ||
- GetLastCommittedEntry()->site_instance() != rfh->GetSiteInstance())
+ if (pending_entry_ && pending_entry_->GetUniqueID() == params.nav_entry_id) {
+ // If the SiteInstance of the |pending_entry_| does not match the
+ // SiteInstance that got committed, treat this as a new navigation with
+ // replacement. This can happen if back/forward/reload encounters a server
+ // redirect to a different site or an isolated error page gets successfully
+ // reloaded into a different SiteInstance.
+ if (pending_entry_->site_instance() &&
+ pending_entry_->site_instance() != rfh->GetSiteInstance()) {
return NAVIGATION_TYPE_NEW_PAGE;
+ }
- // Otherwise, this happens when you press enter in the URL bar to reload. We
- // will create a pending entry, but Blink will convert it to a reload since
- // it's the same page and not create a new entry for it (the user doesn't
- // want to have a new back/forward entry when they do this). Therefore we
- // want to just ignore the pending entry and go back to where we were (the
- // "existing entry").
- // TODO(creis,avi): Eliminate SAME_PAGE in https://crbug.com/536102.
- return NAVIGATION_TYPE_SAME_PAGE;
+ if (pending_entry_index_ == -1) {
+ // In this case, we have a pending entry for a load of a new URL but Blink
+ // didn't do a new navigation (params.did_create_new_entry). First check
+ // to make sure Blink didn't treat a new cross-process navigation as
+ // inert, and thus set params.did_create_new_entry to false. In that case,
+ // we must treat it as NEW since the SiteInstance doesn't match the entry.
+ if (!GetLastCommittedEntry() ||
+ GetLastCommittedEntry()->site_instance() != rfh->GetSiteInstance()) {
+ return NAVIGATION_TYPE_NEW_PAGE;
+ }
+
+ // Otherwise, this happens when you press enter in the URL bar to reload.
+ // We will create a pending entry, but Blink will convert it to a reload
+ // since it's the same page and not create a new entry for it (the user
+ // doesn't want to have a new back/forward entry when they do this).
+ // Therefore we want to just ignore the pending entry and go back to where
+ // we were (the "existing entry").
+ // TODO(creis,avi): Eliminate SAME_PAGE in https://crbug.com/536102.
+ return NAVIGATION_TYPE_SAME_PAGE;
+ }
}
// Everything below here is assumed to be an existing entry, but if there is
@@ -1315,6 +1243,15 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
last_committed_entry_index_ = -1;
}
+ // If this is a new navigation with replacement and there is a
+ // pending_entry_ which matches the navigation reported by the renderer
+ // process, then it should be the one replaced, so update the
+ // last_committed_entry_index_ to use it.
+ if (replace_entry && pending_entry_index_ != -1 &&
+ pending_entry_->GetUniqueID() == params.nav_entry_id) {
+ last_committed_entry_index_ = pending_entry_index_;
+ }
+
InsertOrReplaceEntry(std::move(new_entry), replace_entry);
}
@@ -1908,12 +1845,18 @@ bool NavigationControllerImpl::StartHistoryNavigationInNewSubframe(
}
}
- // TODO(clamy): Create a NavigationRequest here and pass it to Navigator for
- // navigating.
- return render_frame_host->frame_tree_node()->navigator()->NavigateToEntry(
- render_frame_host->frame_tree_node(), *frame_entry, *entry,
- ReloadType::NONE, false, true, false, nullptr,
- nullptr /* navigation_ui_data */);
+ std::unique_ptr<NavigationRequest> request = CreateNavigationRequest(
+ render_frame_host->frame_tree_node(), *entry, frame_entry,
+ ReloadType::NONE, false /* is_same_document_history_load */,
+ true /* is_history_navigation_in_new_child */, nullptr, nullptr);
+
+ if (!request)
+ return false;
+
+ render_frame_host->frame_tree_node()->navigator()->Navigate(
+ std::move(request), ReloadType::NONE, RestoreType::NONE);
+
+ return true;
}
void NavigationControllerImpl::NavigateFromFrameProxy(
@@ -1992,11 +1935,16 @@ void NavigationControllerImpl::NavigateFromFrameProxy(
std::vector<GURL>(), PageState(), method, -1, blob_url_loader_factory);
}
- // TODO(clamy): Create a NavigationRequest here and pass it to Navigator for
- // navigating.
- render_frame_host->frame_tree_node()->navigator()->NavigateToEntry(
- node, *frame_entry, *entry.get(), ReloadType::NONE, false, false, false,
- post_body, nullptr /* navigation_ui_data */);
+ std::unique_ptr<NavigationRequest> request = CreateNavigationRequest(
+ render_frame_host->frame_tree_node(), *entry, frame_entry.get(),
+ ReloadType::NONE, false /* is_same_document_history_load */,
+ false /* is_history_navigation_in_new_child */, post_body, nullptr);
+
+ if (!request)
+ return;
+
+ render_frame_host->frame_tree_node()->navigator()->Navigate(
+ std::move(request), ReloadType::NONE, RestoreType::NONE);
}
void NavigationControllerImpl::ClearAllScreenshots() {
@@ -2189,10 +2137,11 @@ void NavigationControllerImpl::PruneOldestEntryIfFull() {
}
}
-void NavigationControllerImpl::NavigateToPendingEntry(
- ReloadType reload_type,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
+void NavigationControllerImpl::NavigateToExistingPendingEntry(
+ ReloadType reload_type) {
DCHECK(pending_entry_);
+ DCHECK(IsInitialNavigation() || pending_entry_index_ != -1);
+ DCHECK(!IsRendererDebugURL(pending_entry_->GetURL()));
needs_reload_ = false;
// If we were navigating to a slow-to-commit page, and the user performs
@@ -2201,8 +2150,7 @@ void NavigationControllerImpl::NavigateToPendingEntry(
// navigation, and won't send a message to stop the throbber. To prevent this
// from happening, we drop the navigation here and stop the slow-to-commit
// page from loading (which would normally happen during the navigation).
- if (pending_entry_index_ != -1 &&
- pending_entry_index_ == last_committed_entry_index_ &&
+ if (pending_entry_index_ == last_committed_entry_index_ &&
pending_entry_->restore_type() == RestoreType::NONE &&
pending_entry_->GetTransitionType() & ui::PAGE_TRANSITION_FORWARD_BACK) {
delegate_->Stop();
@@ -2224,64 +2172,15 @@ void NavigationControllerImpl::NavigateToPendingEntry(
return;
}
- // If an interstitial page is showing, the previous renderer is blocked and
- // cannot make new requests. Unblock (and disable) it to allow this
- // navigation to succeed. The interstitial will stay visible until the
- // resulting DidNavigate.
- if (delegate_->GetInterstitialPage()) {
- static_cast<InterstitialPageImpl*>(delegate_->GetInterstitialPage())
- ->CancelForNavigation();
- }
-
- // Convert navigations to the current URL to a reload.
- if (ShouldTreatNavigationAsReload(
- pending_entry_->GetURL(), pending_entry_->GetVirtualURL(),
- pending_entry_->GetBaseURLForDataURL(),
- pending_entry_->GetTransitionType(),
- pending_entry_->frame_tree_node_id() == -1 /* is_main_frame */,
- pending_entry_->GetHasPostData() /* is _post */,
- reload_type != ReloadType::NONE /* is_reload */,
- pending_entry_index_ != -1 /* is_navigation_to_existing_entry */,
- transient_entry_index_ != -1 /* has_interstitial */,
- GetLastCommittedEntry())) {
- reload_type = ReloadType::NORMAL;
- }
-
- // Any renderer-side debug URLs or javascript: URLs should be ignored if the
- // renderer process is not live, unless it is the initial navigation of the
- // tab.
- if (IsRendererDebugURL(pending_entry_->GetURL())) {
- // TODO(creis): Find the RVH for the correct frame.
- if (!delegate_->GetRenderViewHost()->IsRenderViewLive() &&
- !IsInitialNavigation()) {
- DiscardNonCommittedEntries();
- return;
- }
- }
-
- // This call does not support re-entrancy. See http://crbug.com/347742.
- CHECK(!in_navigate_to_pending_entry_);
- in_navigate_to_pending_entry_ = true;
- bool success = NavigateToPendingEntryInternal(reload_type,
- std::move(navigation_ui_data));
- in_navigate_to_pending_entry_ = false;
-
- if (!success)
- DiscardNonCommittedEntries();
-}
-
-bool NavigationControllerImpl::NavigateToPendingEntryInternal(
- ReloadType reload_type,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
- DCHECK(pending_entry_);
FrameTreeNode* root = delegate_->GetFrameTree()->root();
// Compare FrameNavigationEntries to see which frames in the tree need to be
// navigated.
- FrameLoadVector same_document_loads;
- FrameLoadVector different_document_loads;
+ std::vector<std::unique_ptr<NavigationRequest>> same_document_loads;
+ std::vector<std::unique_ptr<NavigationRequest>> different_document_loads;
if (GetLastCommittedEntry()) {
- FindFramesToNavigate(root, &same_document_loads, &different_document_loads);
+ FindFramesToNavigate(root, reload_type, &same_document_loads,
+ &different_document_loads);
}
if (same_document_loads.empty() && different_document_loads.empty()) {
@@ -2292,35 +2191,55 @@ bool NavigationControllerImpl::NavigateToPendingEntryInternal(
// thing to do. In the second case, we should have been able to find a
// frame to navigate based on names if this were a same document
// navigation, so we can safely assume this is the different document case.
- different_document_loads.push_back(
- std::make_pair(root, pending_entry_->GetFrameEntry(root)));
+ std::unique_ptr<NavigationRequest> navigation_request =
+ CreateNavigationRequest(
+ root, *pending_entry_, pending_entry_->GetFrameEntry(root),
+ reload_type, false /* is_same_document_history_load */,
+ false /* is_history_navigation_in_new_child */, nullptr, nullptr);
+ if (!navigation_request) {
+ // This navigation cannot start (e.g. the URL is invalid), delete the
+ // pending NavigationEntry.
+ DiscardPendingEntry(false);
+ return;
+ }
+ different_document_loads.push_back(std::move(navigation_request));
+ }
+
+ // If an interstitial page is showing, the previous renderer is blocked and
+ // cannot make new requests. Unblock (and disable) it to allow this
+ // navigation to succeed. The interstitial will stay visible until the
+ // resulting DidNavigate.
+ // TODO(clamy): See if this can be removed now that PlzNavigate has shipped.
+ // See https://crbug.com/849250
+ if (delegate_->GetInterstitialPage()) {
+ static_cast<InterstitialPageImpl*>(delegate_->GetInterstitialPage())
+ ->CancelForNavigation();
}
- // If all the frame loads fail, we will discard the pending entry.
- bool success = false;
+ // This call does not support re-entrancy. See http://crbug.com/347742.
+ CHECK(!in_navigate_to_pending_entry_);
+ in_navigate_to_pending_entry_ = true;
// Send all the same document frame loads before the different document loads.
- for (const auto& item : same_document_loads) {
- FrameTreeNode* frame = item.first;
- success |= frame->navigator()->NavigateToPendingEntry(
- frame, *item.second, reload_type, true,
- nullptr /* navigation_ui_data */);
+ for (auto& item : same_document_loads) {
+ FrameTreeNode* frame = item->frame_tree_node();
+ frame->navigator()->Navigate(std::move(item), reload_type,
+ pending_entry_->restore_type());
}
- for (const auto& item : different_document_loads) {
- FrameTreeNode* frame = item.first;
- success |= frame->navigator()->NavigateToPendingEntry(
- frame, *item.second, reload_type, false,
- // The NavigationUIData has only been initialized for main frames. Do
- // not pass it to subframes.
- frame->IsMainFrame() ? std::move(navigation_ui_data) : nullptr);
+ for (auto& item : different_document_loads) {
+ FrameTreeNode* frame = item->frame_tree_node();
+ frame->navigator()->Navigate(std::move(item), reload_type,
+ pending_entry_->restore_type());
}
- return success;
+
+ in_navigate_to_pending_entry_ = false;
}
void NavigationControllerImpl::FindFramesToNavigate(
FrameTreeNode* frame,
- FrameLoadVector* same_document_loads,
- FrameLoadVector* different_document_loads) {
+ ReloadType reload_type,
+ std::vector<std::unique_ptr<NavigationRequest>>* same_document_loads,
+ std::vector<std::unique_ptr<NavigationRequest>>* different_document_loads) {
DCHECK(pending_entry_);
DCHECK_GE(last_committed_entry_index_, 0);
FrameNavigationEntry* new_item = pending_entry_->GetFrameEntry(frame);
@@ -2348,7 +2267,16 @@ void NavigationControllerImpl::FindFramesToNavigate(
new_item->document_sequence_number() ==
old_item->document_sequence_number() &&
!frame->current_frame_host()->GetLastCommittedURL().is_empty()) {
- same_document_loads->push_back(std::make_pair(frame, new_item));
+ std::unique_ptr<NavigationRequest> navigation_request =
+ CreateNavigationRequest(
+ frame, *pending_entry_, new_item, reload_type,
+ true /* is_same_document_history_load */,
+ false /* is_history_navigation_in_new_child */, nullptr, nullptr);
+ if (navigation_request) {
+ // Only add the request if was properly created. It's possible for the
+ // creation to fail in certain cases, e.g. when the URL is invalid.
+ same_document_loads->push_back(std::move(navigation_request));
+ }
// TODO(avi, creis): This is a bug; we should not return here. Rather, we
// should continue on and navigate all child frames which have also
@@ -2365,7 +2293,16 @@ void NavigationControllerImpl::FindFramesToNavigate(
// different way that will one day allow us to fix this.
return;
} else {
- different_document_loads->push_back(std::make_pair(frame, new_item));
+ std::unique_ptr<NavigationRequest> navigation_request =
+ CreateNavigationRequest(
+ frame, *pending_entry_, new_item, reload_type,
+ false /* is_same_document_history_load */,
+ false /* is_history_navigation_in_new_child */, nullptr, nullptr);
+ if (navigation_request) {
+ // Only add the request if was properly created. It's possible for the
+ // creation to fail in certain cases, e.g. when the URL is invalid.
+ different_document_loads->push_back(std::move(navigation_request));
+ }
// For a different document, the subframes will be destroyed, so there's
// no need to consider them.
return;
@@ -2373,11 +2310,315 @@ void NavigationControllerImpl::FindFramesToNavigate(
}
for (size_t i = 0; i < frame->child_count(); i++) {
- FindFramesToNavigate(frame->child_at(i), same_document_loads,
+ FindFramesToNavigate(frame->child_at(i), reload_type, same_document_loads,
different_document_loads);
}
}
+void NavigationControllerImpl::NavigateWithoutEntry(
+ const LoadURLParams& params) {
+ // Find the appropriate FrameTreeNode.
+ FrameTreeNode* node = nullptr;
+ if (params.frame_tree_node_id != RenderFrameHost::kNoFrameTreeNodeId ||
+ !params.frame_name.empty()) {
+ node = params.frame_tree_node_id != RenderFrameHost::kNoFrameTreeNodeId
+ ? delegate_->GetFrameTree()->FindByID(params.frame_tree_node_id)
+ : delegate_->GetFrameTree()->FindByName(params.frame_name);
+ }
+
+ // If no FrameTreeNode was specified, navigate the main frame.
+ if (!node)
+ node = delegate_->GetFrameTree()->root();
+
+ // Javascript URLs should not create NavigationEntries. All other navigations
+ // do, including navigations to chrome renderer debug URLs.
+ std::unique_ptr<NavigationEntryImpl> entry;
+ if (!params.url.SchemeIs(url::kJavaScriptScheme)) {
+ entry = CreateNavigationEntryFromLoadParams(node, params);
+ DiscardPendingEntry(false);
+ SetPendingEntry(std::move(entry));
+ }
+
+ // Renderer-debug URLs are sent to the renderer process immediately for
+ // processing and don't need to create a NavigationRequest.
+ // Note: this includes navigations to JavaScript URLs, which are considered
+ // renderer-debug URLs.
+ // Note: we intentionally leave the pending entry in place for renderer debug
+ // URLs, unlike the cases below where we clear it if the navigation doesn't
+ // proceed.
+ if (IsRendererDebugURL(params.url)) {
+ HandleRendererDebugURL(node, params.url);
+ return;
+ }
+
+ // Convert navigations to the current URL to a reload.
+ // TODO(clamy): We should be using FrameTreeNode::IsMainFrame here instead of
+ // relying on the frame tree node id from LoadURLParams. Unfortunately,
+ // DevTools sometimes issues navigations to main frames that they do not
+ // expect to see treated as reload, and it only works because they pass a
+ // FrameTreeNode id in their LoadURLParams. Change this once they no longer do
+ // that. See https://crbug.com/850926.
+ ReloadType reload_type = ReloadType::NONE;
+ if (ShouldTreatNavigationAsReload(
+ params.url, pending_entry_->GetVirtualURL(),
+ params.base_url_for_data_url, params.transition_type,
+ params.frame_tree_node_id == RenderFrameHost::kNoFrameTreeNodeId,
+ params.load_type ==
+ NavigationController::LOAD_TYPE_HTTP_POST /* is_post */,
+ false /* is_reload */, false /* is_navigation_to_existing_entry */,
+ transient_entry_index_ != -1 /* has_interstitial */,
+ GetLastCommittedEntry())) {
+ reload_type = ReloadType::NORMAL;
+ }
+
+ // navigation_ui_data should only be present for main frame navigations.
+ DCHECK(node->IsMainFrame() || !params.navigation_ui_data);
+
+ // TODO(clamy): Create the NavigationRequest directly from the LoadURLParams
+ // instead of relying on the NavigationEntry.
+ DCHECK(pending_entry_);
+ std::unique_ptr<NavigationRequest> request = CreateNavigationRequest(
+ node, *pending_entry_, pending_entry_->GetFrameEntry(node), reload_type,
+ false /* is_same_document_history_load */,
+ false /* is_history_navigation_in_new_child */, nullptr,
+ params.navigation_ui_data ? params.navigation_ui_data->Clone() : nullptr);
+
+ // If the navigation couldn't start, return immediately and discard the
+ // pending NavigationEntry.
+ if (!request) {
+ DiscardPendingEntry(false);
+ return;
+ }
+
+ // If an interstitial page is showing, the previous renderer is blocked and
+ // cannot make new requests. Unblock (and disable) it to allow this
+ // navigation to succeed. The interstitial will stay visible until the
+ // resulting DidNavigate.
+ if (delegate_->GetInterstitialPage()) {
+ static_cast<InterstitialPageImpl*>(delegate_->GetInterstitialPage())
+ ->CancelForNavigation();
+ }
+
+ // This call does not support re-entrancy. See http://crbug.com/347742.
+ CHECK(!in_navigate_to_pending_entry_);
+ in_navigate_to_pending_entry_ = true;
+
+ node->navigator()->Navigate(std::move(request), reload_type,
+ RestoreType::NONE);
+
+ in_navigate_to_pending_entry_ = false;
+}
+
+void NavigationControllerImpl::HandleRendererDebugURL(
+ FrameTreeNode* frame_tree_node,
+ const GURL& url) {
+ if (!frame_tree_node->current_frame_host()->IsRenderFrameLive()) {
+ // Any renderer-side debug URLs or javascript: URLs should be ignored if
+ // the renderer process is not live, unless it is the initial navigation
+ // of the tab.
+ if (!IsInitialNavigation()) {
+ DiscardNonCommittedEntries();
+ return;
+ }
+ frame_tree_node->render_manager()->InitializeRenderFrameIfNecessary(
+ frame_tree_node->current_frame_host());
+ }
+ frame_tree_node->current_frame_host()->HandleRendererDebugURL(url);
+}
+
+std::unique_ptr<NavigationEntryImpl>
+NavigationControllerImpl::CreateNavigationEntryFromLoadParams(
+ FrameTreeNode* node,
+ const LoadURLParams& params) {
+ // Browser initiated navigations might not have a blob_url_loader_factory set
+ // in params even if the navigation is to a blob URL. If that happens, lookup
+ // the correct url loader factory to use here.
+ auto blob_url_loader_factory = params.blob_url_loader_factory;
+ if (!blob_url_loader_factory && blink::BlobUtils::MojoBlobURLsEnabled() &&
+ params.url.SchemeIsBlob()) {
+ blob_url_loader_factory = ChromeBlobStorageContext::URLLoaderFactoryForUrl(
+ GetBrowserContext(), params.url);
+ }
+
+ std::unique_ptr<NavigationEntryImpl> entry;
+
+ // For subframes, create a pending entry with a corresponding frame entry.
+ if (!node->IsMainFrame()) {
+ DCHECK(GetLastCommittedEntry());
+
+ // Create an identical NavigationEntry with a new FrameNavigationEntry for
+ // the target subframe.
+ entry = GetLastCommittedEntry()->Clone();
+ entry->AddOrUpdateFrameEntry(
+ node, -1, -1, nullptr,
+ static_cast<SiteInstanceImpl*>(params.source_site_instance.get()),
+ params.url, params.referrer, params.redirect_chain, PageState(), "GET",
+ -1, blob_url_loader_factory);
+ } else {
+ // Otherwise, create a pending entry for the main frame.
+
+ // extra_headers in params are \n separated; navigation entries want \r\n.
+ std::string extra_headers_crlf;
+ base::ReplaceChars(params.extra_headers, "\n", "\r\n", &extra_headers_crlf);
+ entry = NavigationEntryImpl::FromNavigationEntry(CreateNavigationEntry(
+ params.url, params.referrer, params.transition_type,
+ params.is_renderer_initiated, extra_headers_crlf, browser_context_,
+ blob_url_loader_factory));
+ entry->set_source_site_instance(
+ static_cast<SiteInstanceImpl*>(params.source_site_instance.get()));
+ entry->SetRedirectChain(params.redirect_chain);
+ }
+
+ // Set the FTN ID (only used in non-site-per-process, for tests).
+ entry->set_frame_tree_node_id(node->frame_tree_node_id());
+ // Don't allow an entry replacement if there is no entry to replace.
+ // http://crbug.com/457149
+ if (params.should_replace_current_entry && entries_.size() > 0)
+ entry->set_should_replace_entry(true);
+ entry->set_should_clear_history_list(params.should_clear_history_list);
+
+ bool override = false;
+ switch (params.override_user_agent) {
+ case UA_OVERRIDE_INHERIT:
+ override = ShouldKeepOverride(GetLastCommittedEntry());
+ break;
+ case UA_OVERRIDE_TRUE:
+ override = true;
+ break;
+ case UA_OVERRIDE_FALSE:
+ override = false;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ entry->SetIsOverridingUserAgent(override);
+
+// Always propagate `has_user_gesture` on Android but only when the request
+// was originated by the renderer on other platforms. This is merely for
+// backward compatibility as browser process user gestures create confusion in
+// many tests.
+#if defined(OS_ANDROID)
+ entry->set_has_user_gesture(params.has_user_gesture);
+#else
+ if (params.is_renderer_initiated)
+ entry->set_has_user_gesture(params.has_user_gesture);
+#endif
+
+ switch (params.load_type) {
+ case LOAD_TYPE_DEFAULT:
+ break;
+ case LOAD_TYPE_HTTP_POST:
+ entry->SetHasPostData(true);
+ entry->SetPostData(params.post_data);
+ break;
+ case LOAD_TYPE_DATA:
+ entry->SetBaseURLForDataURL(params.base_url_for_data_url);
+ entry->SetVirtualURL(params.virtual_url_for_data_url);
+#if defined(OS_ANDROID)
+ entry->SetDataURLAsString(params.data_url_as_string);
+#endif
+ entry->SetCanLoadLocalResources(params.can_load_local_resources);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ // TODO(clamy): NavigationEntry is meant for information that will be kept
+ // after the navigation ended and therefore is not appropriate for
+ // started_from_context_menu. Move started_from_context_menu to
+ // NavigationUIData.
+ entry->set_started_from_context_menu(params.started_from_context_menu);
+
+ return entry;
+}
+
+std::unique_ptr<NavigationRequest>
+NavigationControllerImpl::CreateNavigationRequest(
+ FrameTreeNode* frame_tree_node,
+ const NavigationEntryImpl& entry,
+ FrameNavigationEntry* frame_entry,
+ ReloadType reload_type,
+ bool is_same_document_history_load,
+ bool is_history_navigation_in_new_child,
+ const scoped_refptr<network::ResourceRequestBody>& post_body,
+ std::unique_ptr<NavigationUIData> navigation_ui_data) {
+ GURL dest_url = frame_entry->url();
+ Referrer dest_referrer = frame_entry->referrer();
+ if (reload_type == ReloadType::ORIGINAL_REQUEST_URL &&
+ entry.GetOriginalRequestURL().is_valid() && !entry.GetHasPostData()) {
+ // We may have been redirected when navigating to the current URL.
+ // Use the URL the user originally intended to visit as signaled by the
+ // ReloadType, if it's valid and if a POST wasn't involved; the latter
+ // case avoids issues with sending data to the wrong page.
+ dest_url = entry.GetOriginalRequestURL();
+ dest_referrer = Referrer();
+ }
+
+ // Don't attempt to navigate if the virtual URL is non-empty and invalid.
+ if (frame_tree_node->IsMainFrame()) {
+ const GURL& virtual_url = entry.GetVirtualURL();
+ if (!virtual_url.is_valid() && !virtual_url.is_empty()) {
+ LOG(WARNING) << "Refusing to load for invalid virtual URL: "
+ << virtual_url.possibly_invalid_spec();
+ return nullptr;
+ }
+ }
+
+ // Don't attempt to navigate to non-empty invalid URLs.
+ if (!dest_url.is_valid() && !dest_url.is_empty()) {
+ LOG(WARNING) << "Refusing to load invalid URL: "
+ << dest_url.possibly_invalid_spec();
+ return nullptr;
+ }
+
+ // 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() > url::kMaxURLChars) {
+ LOG(WARNING) << "Refusing to load URL as it exceeds " << url::kMaxURLChars
+ << " characters.";
+ return nullptr;
+ }
+
+ // Determine if Previews should be used for the navigation.
+ PreviewsState previews_state = PREVIEWS_UNSPECIFIED;
+ if (!frame_tree_node->IsMainFrame()) {
+ // For subframes, use the state of the top-level frame.
+ previews_state = frame_tree_node->frame_tree()
+ ->root()
+ ->current_frame_host()
+ ->last_navigation_previews_state();
+ }
+
+ // Give the delegate an opportunity to adjust the previews state.
+ if (delegate_)
+ delegate_->AdjustPreviewsStateForNavigation(&previews_state);
+
+ // This will be used to set the Navigation Timing API navigationStart
+ // parameter for browser navigations in new tabs (intents, tabs opened through
+ // "Open link in new tab"). If the navigation must wait on the current
+ // RenderFrameHost to execute its BeforeUnload event, the navigation start
+ // will be updated when the BeforeUnload ack is received.
+ base::TimeTicks navigation_start = base::TimeTicks::Now();
+ TRACE_EVENT_INSTANT_WITH_TIMESTAMP0(
+ "navigation,rail", "NavigationTiming navigationStart",
+ TRACE_EVENT_SCOPE_GLOBAL, navigation_start);
+
+ FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType(
+ frame_tree_node->current_url(), // old_url
+ dest_url, // new_url
+ reload_type, // reload_type
+ entry, // entry
+ *frame_entry, // frame_entry
+ is_same_document_history_load); // is_same_document_history_load
+ return NavigationRequest::CreateBrowserInitiated(
+ frame_tree_node, dest_url, dest_referrer, *frame_entry, entry,
+ navigation_type, previews_state, is_same_document_history_load,
+ is_history_navigation_in_new_child, post_body, navigation_start, this,
+ std::move(navigation_ui_data));
+}
+
void NavigationControllerImpl::NotifyNavigationEntryCommitted(
LoadCommittedDetails* details) {
details->entry = GetLastCommittedEntry();
@@ -2419,11 +2660,11 @@ void NavigationControllerImpl::LoadIfNecessary() {
// Explicitly use NavigateToPendingEntry so that the renderer uses the
// cached state.
if (pending_entry_) {
- NavigateToPendingEntry(ReloadType::NONE, nullptr /* navigation_ui_data */);
+ NavigateToExistingPendingEntry(ReloadType::NONE);
} else if (last_committed_entry_index_ != -1) {
pending_entry_ = entries_[last_committed_entry_index_].get();
pending_entry_index_ = last_committed_entry_index_;
- NavigateToPendingEntry(ReloadType::NONE, nullptr /* navigation_ui_data */);
+ NavigateToExistingPendingEntry(ReloadType::NONE);
} else {
// If there is something to reload, the successful reload will clear the
// |needs_reload_| flag. Otherwise, just do it here.
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.h b/chromium/content/browser/frame_host/navigation_controller_impl.h
index 3f1f1ceff6d..8b3502ccbc1 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.h
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.h
@@ -241,10 +241,6 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
FRIEND_TEST_ALL_PREFIXES(TimeSmoother, ManyDuplicates);
FRIEND_TEST_ALL_PREFIXES(TimeSmoother, ClockBackwardsJump);
- // Used for identifying which frames need to navigate.
- using FrameLoadVector =
- std::vector<std::pair<FrameTreeNode*, FrameNavigationEntry*>>;
-
// Helper class to smooth out runs of duplicate timestamps while still
// allowing time to jump backwards.
class CONTENT_EXPORT TimeSmoother {
@@ -259,26 +255,46 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
base::Time high_water_mark_;
};
- // Causes the controller to load the specified entry. The function assumes
- // ownership of the pointer since it is put in the navigation list.
- // NOTE: Do not pass an entry that the controller already owns!
- void LoadEntry(std::unique_ptr<NavigationEntryImpl> entry,
- std::unique_ptr<NavigationUIData> navigation_ui_data);
+ // Starts a navigation to an already existing pending NavigationEntry.
+ void NavigateToExistingPendingEntry(ReloadType reload_type);
- // Identifies which frames need to be navigated for the pending
- // NavigationEntry and instructs their Navigator to navigate them. Returns
- // whether any frame successfully started a navigation.
- bool NavigateToPendingEntryInternal(
+ // Recursively identifies which frames need to be navigated for a navigation
+ // to |pending_entry_|, starting at |frame| and exploring its children.
+ // |same_document_loads| and |different_document_loads| will be filled with
+ // the NavigationRequests needed to navigate to |pending_entry_|.
+ void FindFramesToNavigate(
+ FrameTreeNode* frame,
+ ReloadType reload_type,
+ std::vector<std::unique_ptr<NavigationRequest>>* same_document_loads,
+ std::vector<std::unique_ptr<NavigationRequest>>*
+ different_document_loads);
+
+ // Starts a new navigation based on |load_params|, that doesn't correspond to
+ // an exisiting NavigationEntry.
+ void NavigateWithoutEntry(const LoadURLParams& load_params);
+
+ // Handles a navigation to a renderer-debug URL.
+ void HandleRendererDebugURL(FrameTreeNode* frame_tree_node, const GURL& url);
+
+ // Creates and returns a NavigationEntry based on |load_params| for a
+ // navigation in |node|.
+ std::unique_ptr<NavigationEntryImpl> CreateNavigationEntryFromLoadParams(
+ FrameTreeNode* node,
+ const LoadURLParams& load_params);
+
+ // Creates and returns a NavigationRequest based on the provided parameters.
+ // Will return nullptr if the parameters are invalid and the navigation cannot
+ // start.
+ std::unique_ptr<NavigationRequest> CreateNavigationRequest(
+ FrameTreeNode* frame_tree_node,
+ const NavigationEntryImpl& entry,
+ FrameNavigationEntry* frame_entry,
ReloadType reload_type,
+ bool is_same_document_history_load,
+ bool is_history_navigation_in_new_child,
+ const scoped_refptr<network::ResourceRequestBody>& post_body,
std::unique_ptr<NavigationUIData> navigation_ui_data);
- // Recursively identifies which frames need to be navigated for the pending
- // NavigationEntry, starting at |frame| and exploring its children. Only used
- // in --site-per-process.
- void FindFramesToNavigate(FrameTreeNode* frame,
- 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;
@@ -327,11 +343,6 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params);
- // Actually issues the navigation held in pending_entry.
- void NavigateToPendingEntry(
- ReloadType reload_type,
- std::unique_ptr<NavigationUIData> navigation_ui_data);
-
// Allows the derived class to issue notifications that a load has been
// committed. This will fill in the active entry to the details structure.
void NotifyNavigationEntryCommitted(LoadCommittedDetails* details);
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 bfe29504506..b1ed11f1561 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -18,7 +18,7 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
@@ -4991,9 +4991,10 @@ void DoReplaceStateWhilePending(Shell* shell,
} // namespace
+// Flaky on Linux TSan: https://crbug.com/847326
IN_PROC_BROWSER_TEST_F(
NavigationControllerBrowserTest,
- NavigationTypeClassification_On1SameDocumentToXWhile2Pending) {
+ DISABLED_NavigationTypeClassification_On1SameDocumentToXWhile2Pending) {
GURL url1(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html"));
GURL url2(embedded_test_server()->GetURL(
@@ -5019,9 +5020,10 @@ IN_PROC_BROWSER_TEST_F(
DoReplaceStateWhilePending(shell(), url, url, "x");
}
+// Flaky on Linux TSan: https://crbug.com/847326
IN_PROC_BROWSER_TEST_F(
NavigationControllerBrowserTest,
- NavigationTypeClassification_On1SameDocumentTo1While1Pending) {
+ DISABLED_NavigationTypeClassification_On1SameDocumentTo1While1Pending) {
GURL url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html"));
DoReplaceStateWhilePending(shell(), url, url, "simple_page_1.html");
@@ -6670,7 +6672,7 @@ class HistoryNavigationBeforeCommitInjector
private:
// DidCommitProvisionalLoadInterceptor:
- void WillDispatchDidCommitProvisionalLoad(
+ bool WillDispatchDidCommitProvisionalLoad(
RenderFrameHost* render_frame_host,
::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
service_manager::mojom::InterfaceProviderRequest*
@@ -6679,6 +6681,7 @@ class HistoryNavigationBeforeCommitInjector
did_trigger_history_navigation_ = true;
web_contents()->GetController().GoBack();
}
+ return true;
}
bool did_trigger_history_navigation_;
@@ -7934,111 +7937,6 @@ class NavigationControllerControllableResponseBrowserTest
}
};
-IN_PROC_BROWSER_TEST_F(NavigationControllerControllableResponseBrowserTest,
- ReloadDisablePreviewReloadsOriginalRequestURL) {
- const std::string kOriginalPath = "/original.html";
- const std::string kRedirectPath = "/redirect.html";
- net::test_server::ControllableHttpResponse original_response1(
- embedded_test_server(), kOriginalPath);
- net::test_server::ControllableHttpResponse original_response2(
- embedded_test_server(), kOriginalPath);
- net::test_server::ControllableHttpResponse redirect_response1(
- embedded_test_server(), kRedirectPath);
- net::test_server::ControllableHttpResponse redirect_response2(
- embedded_test_server(), kRedirectPath);
-
- EXPECT_TRUE(embedded_test_server()->Start());
-
- const GURL kOriginalURL =
- embedded_test_server()->GetURL("a.com", kOriginalPath);
- const GURL kRedirectURL =
- embedded_test_server()->GetURL("b.com", kRedirectPath);
- const GURL kReloadRedirectURL =
- embedded_test_server()->GetURL("c.com", kRedirectPath);
-
- // First navigate to the initial URL. This page will have a cross-site
- // redirect to a 2nd domain.
- shell()->LoadURL(kOriginalURL);
- original_response1.WaitForRequest();
- original_response1.Send(
- "HTTP/1.1 302 FOUND\r\n"
- "Location: " +
- kRedirectURL.spec() +
- "\r\n"
- "\r\n");
- original_response1.Done();
- redirect_response1.WaitForRequest();
- redirect_response1.Send(
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html; charset=utf-8\r\n"
- "\r\n");
- redirect_response1.Send(
- "<html>"
- "<body></body>"
- "</html>");
- redirect_response1.Done();
- EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
- EXPECT_EQ(kRedirectURL, shell()->web_contents()->GetVisibleURL());
-
- if (content::AreAllSitesIsolatedForTesting()) {
- RenderFrameHostImpl* rfh =
- static_cast<WebContentsImpl*>(shell()->web_contents())->GetMainFrame();
- EXPECT_EQ(GURL("http://b.com"), rfh->GetSiteInstance()->GetSiteURL());
- }
-
- // Now simulate a 'Show original' reload via ReloadType::DISABLE_PREVIEWS.
- // This reload will have a cross-site redirect to a 3rd domain.
- TestNavigationManager reload(shell()->web_contents(), kOriginalURL);
- shell()->web_contents()->GetController().Reload(ReloadType::DISABLE_PREVIEWS,
- false);
- EXPECT_TRUE(reload.WaitForRequestStart());
-
- // Verify reload is using the original request URL and no previews allowed.
- EXPECT_EQ(kOriginalURL, reload.GetNavigationHandle()->GetURL());
- NavigationRequest* navigation_request =
- static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root()
- ->navigation_request();
- CHECK(navigation_request);
- EXPECT_EQ(content::PREVIEWS_NO_TRANSFORM,
- navigation_request->common_params().previews_state);
-
- reload.ResumeNavigation();
- original_response2.WaitForRequest();
- original_response2.Send(
- "HTTP/1.1 302 FOUND\r\n"
- "Location: " +
- kReloadRedirectURL.spec() +
- "\r\n"
- "\r\n");
- original_response2.Done();
- redirect_response2.WaitForRequest();
-
- // Verify now using new redirect URL.
- EXPECT_EQ(kReloadRedirectURL, reload.GetNavigationHandle()->GetURL());
-
- redirect_response2.Send(
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html; charset=utf-8\r\n"
- "\r\n");
- redirect_response2.Send(
- "<html>"
- "<body></body>"
- "</html>");
- redirect_response2.Done();
- EXPECT_TRUE(reload.WaitForResponse());
- reload.WaitForNavigationFinished();
- EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
- EXPECT_EQ(kReloadRedirectURL, shell()->web_contents()->GetVisibleURL());
-
- if (content::AreAllSitesIsolatedForTesting()) {
- RenderFrameHostImpl* rfh =
- static_cast<WebContentsImpl*>(shell()->web_contents())->GetMainFrame();
- EXPECT_EQ(GURL("http://c.com"), rfh->GetSiteInstance()->GetSiteURL());
- }
-}
-
// This test reproduces issue 769645. It happens when the user reloads the page
// and an "unload" event triggers a back navigation. If the reload navigation
// has reached the ReadyToCommit stage but has not committed, the back
@@ -8137,4 +8035,75 @@ IN_PROC_BROWSER_TEST_F(ContentBrowserTest, DataURLSameDocumentNavigation) {
EXPECT_TRUE(capturer.is_same_document());
}
+// Verify that a session history navigation which results in a different
+// SiteInstance from the original commit is correctly handled - classified
+// as new navigation with replacement, resulting in no new navigation
+// entries.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ SiteInstanceChangeOnHistoryNavigation) {
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ const NavigationControllerImpl& controller =
+ static_cast<const NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+ GURL url1(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ GURL url2(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ GURL url3(embedded_test_server()->GetURL("c.com", "/title3.html"));
+ GURL redirecting_url(embedded_test_server()->GetURL(
+ "a.com", "/server-redirect?" + url3.spec()));
+
+ // Start with an initial URL.
+ EXPECT_TRUE(NavigateToURL(shell(), url1));
+ EXPECT_EQ(1, controller.GetEntryCount());
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url1, controller.GetEntryAtIndex(0)->GetURL());
+ scoped_refptr<SiteInstance> initial_site_instance =
+ root->current_frame_host()->GetSiteInstance();
+
+ {
+ // history.replaceState(), pointing to a URL that would redirect to |url3|.
+ FrameNavigateParamsCapturer capturer(root);
+ std::string script =
+ "history.replaceState({}, '', '" + redirecting_url.spec() + "')";
+ EXPECT_TRUE(ExecuteScript(root, script));
+ capturer.Wait();
+ }
+ EXPECT_EQ(1, controller.GetEntryCount());
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(redirecting_url, controller.GetEntryAtIndex(0)->GetURL());
+ EXPECT_EQ(initial_site_instance,
+ root->current_frame_host()->GetSiteInstance());
+
+ // Navigate to a new URL to get new session history entry.
+ EXPECT_TRUE(NavigateToURL(shell(), url2));
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_NE(initial_site_instance,
+ root->current_frame_host()->GetSiteInstance());
+
+ // Back, which should redirect to |url3|.
+ FrameNavigateParamsCapturer capturer(root);
+ shell()->web_contents()->GetController().GoBack();
+ capturer.Wait();
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+
+ NavigationEntry* entry = controller.GetEntryAtIndex(0);
+ EXPECT_EQ(entry, controller.GetLastCommittedEntry());
+ EXPECT_EQ(url3, entry->GetURL());
+ if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_NE(initial_site_instance,
+ root->current_frame_host()->GetSiteInstance());
+ EXPECT_EQ(SiteInstance::GetSiteForURL(
+ shell()->web_contents()->GetBrowserContext(), url3),
+ root->current_frame_host()->GetSiteInstance()->GetSiteURL());
+ EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
+ } else {
+ EXPECT_EQ(initial_site_instance,
+ root->current_frame_host()->GetSiteInstance());
+ EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+ }
+}
+
} // 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 56e15a9b56f..ebff6f11cc9 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -38,6 +38,7 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents_delegate.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/page_state.h"
#include "content/public/common/page_type.h"
@@ -673,7 +674,6 @@ TEST_F(NavigationControllerTest, LoadURLWithParams) {
load_params.load_type = NavigationController::LOAD_TYPE_DEFAULT;
load_params.is_renderer_initiated = true;
load_params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
- load_params.transferred_global_request_id = GlobalRequestID(2, 3);
controller.LoadURLWithParams(load_params);
NavigationEntryImpl* entry = controller.GetPendingEntry();
@@ -1011,7 +1011,7 @@ TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {
kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
// Pretend it has bindings so we can tell if we incorrectly copy it.
- main_test_rfh()->AllowBindings(2);
+ main_test_rfh()->AllowBindings(BINDINGS_POLICY_MOJO_WEB_UI);
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigate(entry_id, true, kExistingURL1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
@@ -1306,7 +1306,7 @@ TEST_F(NavigationControllerTest, LoadURL_WithBindings) {
int entry_id = controller.GetPendingEntry()->GetUniqueID();
orig_rfh->PrepareForCommit();
TestRenderFrameHost* new_rfh = contents()->GetPendingMainFrame();
- new_rfh->AllowBindings(1);
+ new_rfh->AllowBindings(BINDINGS_POLICY_WEB_UI);
new_rfh->SendNavigate(entry_id, true, url2);
// The second load should be committed, and bindings should be remembered.
@@ -1508,49 +1508,6 @@ TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
EXPECT_FALSE(controller.CanGoForward());
}
-TEST_F(NavigationControllerTest,
- ReloadDisablePreviewReloadsOriginalRequestURL) {
- NavigationControllerImpl& controller = controller_impl();
-
- const GURL original_url("http://foo1");
- const GURL final_url("http://foo2");
- auto set_original_url_callback = base::Bind(SetOriginalURL, original_url);
-
- // Load up the original URL, but get redirected.
- controller.LoadURL(original_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
- std::string());
- int entry_id = controller.GetPendingEntry()->GetUniqueID();
- EXPECT_EQ(0U, navigation_entry_changed_counter_);
- EXPECT_EQ(0U, navigation_list_pruned_counter_);
- main_test_rfh()->PrepareForCommitWithServerRedirect(final_url);
- main_test_rfh()->SendNavigateWithModificationCallback(
- entry_id, true, final_url, std::move(set_original_url_callback));
- EXPECT_EQ(1U, navigation_entry_committed_counter_);
- navigation_entry_committed_counter_ = 0;
- entry_id = controller.GetLastCommittedEntry()->GetUniqueID();
-
- // The NavigationEntry should save both the original URL and the final
- // redirected URL.
- EXPECT_EQ(original_url,
- controller.GetVisibleEntry()->GetOriginalRequestURL());
- EXPECT_EQ(final_url, controller.GetVisibleEntry()->GetURL());
-
- // Reload with previews disabled.
- controller.Reload(ReloadType::DISABLE_PREVIEWS, false);
- EXPECT_EQ(0U, navigation_entry_changed_counter_);
- EXPECT_EQ(0U, navigation_list_pruned_counter_);
-
- // The reload is pending. The request should point to the original URL.
- EXPECT_EQ(original_url, navigated_url());
- EXPECT_EQ(controller.GetEntryCount(), 1);
- EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 0);
- EXPECT_EQ(controller.GetPendingEntryIndex(), 0);
- EXPECT_TRUE(controller.GetLastCommittedEntry());
- EXPECT_TRUE(controller.GetPendingEntry());
- EXPECT_TRUE(HasNavigationRequest());
- EXPECT_EQ(content::PREVIEWS_NO_TRANSFORM, GetLastNavigationPreviewsState());
-}
-
// Test that certain non-persisted NavigationEntryImpl values get reset after
// commit.
TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
@@ -1574,19 +1531,16 @@ TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
// Set up some sample values.
const char* raw_data = "post\n\n\0data";
const int length = 11;
- GlobalRequestID transfer_id(3, 4);
// Set non-persisted values on the pending entry.
NavigationEntryImpl* pending_entry = controller.GetPendingEntry();
pending_entry->SetPostData(
network::ResourceRequestBody::CreateFromBytes(raw_data, length));
pending_entry->set_is_renderer_initiated(true);
- pending_entry->set_transferred_global_request_id(transfer_id);
pending_entry->set_should_replace_entry(true);
pending_entry->set_should_clear_history_list(true);
EXPECT_TRUE(pending_entry->GetPostData());
EXPECT_TRUE(pending_entry->is_renderer_initiated());
- EXPECT_EQ(transfer_id, pending_entry->transferred_global_request_id());
EXPECT_TRUE(pending_entry->should_replace_entry());
EXPECT_TRUE(pending_entry->should_clear_history_list());
@@ -1599,8 +1553,6 @@ TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
NavigationEntryImpl* committed_entry = controller.GetLastCommittedEntry();
EXPECT_FALSE(committed_entry->GetPostData());
EXPECT_FALSE(committed_entry->is_renderer_initiated());
- EXPECT_EQ(GlobalRequestID(-1, -1),
- committed_entry->transferred_global_request_id());
EXPECT_FALSE(committed_entry->should_replace_entry());
EXPECT_FALSE(committed_entry->should_clear_history_list());
}
@@ -4540,17 +4492,19 @@ TEST_F(NavigationControllerTest, CopyRestoredStateAndNavigate) {
// Go back to the first entry one at a time and
// verify that it works as expected.
EXPECT_EQ(2, controller_impl().GetCurrentEntryIndex());
- EXPECT_EQ(kInitialUrl, controller_impl().GetActiveEntry()->GetURL());
+ EXPECT_EQ(kInitialUrl, controller_impl().GetLastCommittedEntry()->GetURL());
controller_impl().GoBack();
contents()->CommitPendingNavigation();
EXPECT_EQ(1, controller_impl().GetCurrentEntryIndex());
- EXPECT_EQ(kRestoredUrls[1], controller_impl().GetActiveEntry()->GetURL());
+ EXPECT_EQ(kRestoredUrls[1],
+ controller_impl().GetLastCommittedEntry()->GetURL());
controller_impl().GoBack();
contents()->CommitPendingNavigation();
EXPECT_EQ(0, controller_impl().GetCurrentEntryIndex());
- EXPECT_EQ(kRestoredUrls[0], controller_impl().GetActiveEntry()->GetURL());
+ EXPECT_EQ(kRestoredUrls[0],
+ controller_impl().GetLastCommittedEntry()->GetURL());
}
// Tests that navigations initiated from the page (with the history object)
@@ -5333,7 +5287,14 @@ TEST_F(NavigationControllerTest, MainFrameNavigationUIData) {
controller.LoadURLWithParams(params);
int entry_id = controller.GetPendingEntry()->GetUniqueID();
+ NavigationRequest* request =
+ main_test_rfh()->frame_tree_node()->navigation_request();
+ CHECK(request);
+
main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SimulateCommitProcessed(
+ request->navigation_handle()->GetNavigationId(),
+ true /* was_successful */);
main_test_rfh()->SendNavigate(entry_id, true, url1);
EXPECT_TRUE(observer.is_main_frame());
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.cc b/chromium/content/browser/frame_host/navigation_entry_impl.cc
index c434d64daa7..aa9c80e2ce7 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.cc
@@ -12,6 +12,7 @@
#include <utility>
#include "base/containers/queue.h"
+#include "base/files/file_path.h"
#include "base/i18n/rtl.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
@@ -28,6 +29,10 @@
#include "content/public/common/url_constants.h"
#include "ui/gfx/text_elider.h"
+#if defined(OS_ANDROID)
+#include "base/android/content_uri_utils.h"
+#endif
+
using base::UTF16ToUTF8;
namespace content {
@@ -457,6 +462,16 @@ const base::string16& NavigationEntryImpl::GetTitleForDisplay() const {
base::i18n::WrapStringWithLTRFormatting(&title);
}
+#if defined(OS_ANDROID)
+ if (GetURL().SchemeIs(url::kContentScheme)) {
+ base::string16 file_display_name;
+ if (base::MaybeGetFileDisplayName(base::FilePath(GetURL().spec()),
+ &file_display_name)) {
+ title = file_display_name;
+ }
+ }
+#endif
+
gfx::ElideString(title, kMaxTitleChars, &cached_display_title_);
return cached_display_title_;
}
@@ -653,11 +668,9 @@ std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::CloneAndReplace(
#endif
// ResetForCommit: is_renderer_initiated_
copy->cached_display_title_ = cached_display_title_;
- // ResetForCommit: transferred_global_request_id_
// ResetForCommit: should_replace_entry_
// ResetForCommit: should_clear_history_list_
// ResetForCommit: frame_tree_node_id_
- // ResetForCommit: intent_received_timestamp_
copy->has_user_gesture_ = has_user_gesture_;
// ResetForCommit: reload_type_
copy->extra_data_ = extra_data_;
@@ -674,30 +687,11 @@ CommonNavigationParams NavigationEntryImpl::ConstructCommonNavigationParams(
FrameMsg_Navigate_Type::Value navigation_type,
PreviewsState previews_state,
const base::TimeTicks& navigation_start) const {
- FrameMsg_UILoadMetricsReportType::Value report_type =
- FrameMsg_UILoadMetricsReportType::NO_REPORT;
- base::TimeTicks ui_timestamp = base::TimeTicks();
-
-#if defined(OS_ANDROID)
- if (!intent_received_timestamp().is_null())
- report_type = FrameMsg_UILoadMetricsReportType::REPORT_INTENT;
- ui_timestamp = intent_received_timestamp();
-#endif
-
- std::string method;
-
- // TODO(clamy): Consult the FrameNavigationEntry in all modes that use
- // subframe navigation entries.
- if (IsBrowserSideNavigationEnabled())
- method = frame_entry.method();
- else
- method = (post_body.get() || GetHasPostData()) ? "POST" : "GET";
-
return CommonNavigationParams(
dest_url, dest_referrer, GetTransitionType(), navigation_type,
- !IsViewSourceMode(), should_replace_entry(), ui_timestamp, report_type,
- GetBaseURLForDataURL(), GetHistoryURLForDataURL(), previews_state,
- navigation_start, method, post_body ? post_body : post_data_,
+ !IsViewSourceMode(), should_replace_entry(), GetBaseURLForDataURL(),
+ GetHistoryURLForDataURL(), previews_state, navigation_start,
+ frame_entry.method(), post_body ? post_body : post_data_,
base::Optional<SourceLocation>(),
CSPDisposition::CHECK /* should_check_main_world_csp */,
has_started_from_context_menu(), has_user_gesture(),
@@ -765,7 +759,6 @@ void NavigationEntryImpl::ResetForCommit(FrameNavigationEntry* frame_entry) {
// PlzNavigate is enabled.
SetPostData(nullptr);
set_is_renderer_initiated(false);
- set_transferred_global_request_id(GlobalRequestID());
set_should_replace_entry(false);
set_should_clear_history_list(false);
@@ -776,12 +769,6 @@ void NavigationEntryImpl::ResetForCommit(FrameNavigationEntry* frame_entry) {
frame_entry->set_source_site_instance(nullptr);
frame_entry->set_blob_url_loader_factory(nullptr);
}
-
-#if defined(OS_ANDROID)
- // Reset the time stamp so that the metrics are not reported if this entry is
- // loaded again in the future.
- set_intent_received_timestamp(base::TimeTicks());
-#endif
}
NavigationEntryImpl::TreeNode* NavigationEntryImpl::GetTreeNode(
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.h b/chromium/content/browser/frame_host/navigation_entry_impl.h
index edfec89b1bc..8c398afe158 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.h
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.h
@@ -358,15 +358,6 @@ class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry {
void set_reload_type(ReloadType type) { reload_type_ = type; }
ReloadType reload_type() const { return reload_type_; }
- void set_transferred_global_request_id(
- const GlobalRequestID& transferred_global_request_id) {
- transferred_global_request_id_ = transferred_global_request_id;
- }
-
- GlobalRequestID transferred_global_request_id() const {
- return transferred_global_request_id_;
- }
-
// Whether this (pending) navigation needs to replace current entry.
// Resets to false after commit.
bool should_replace_entry() const {
@@ -408,17 +399,6 @@ class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry {
void set_ssl_error(bool error) { ssl_error_ = error; }
bool ssl_error() const { return ssl_error_; }
-#if defined(OS_ANDROID)
- base::TimeTicks intent_received_timestamp() const {
- return intent_received_timestamp_;
- }
-
- void set_intent_received_timestamp(
- const base::TimeTicks intent_received_timestamp) {
- intent_received_timestamp_ = intent_received_timestamp;
- }
-#endif
-
bool has_user_gesture() const {
return has_user_gesture_;
}
@@ -505,16 +485,6 @@ class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry {
// cleared to force a refresh.
mutable base::string16 cached_display_title_;
- // In case a navigation is transferred to a new RVH but the request has
- // been generated in the renderer already, this identifies the old request so
- // that it can be resumed. The old request is stored until the
- // ResourceDispatcher receives the navigation from the renderer which
- // carries this |transferred_global_request_id_| annotation. Once the request
- // is transferred to the new process, this is cleared and the request
- // continues as normal.
- // Cleared in |ResetForCommit|.
- GlobalRequestID transferred_global_request_id_;
-
// This is set to true when this entry is being reloaded and due to changes in
// the state of the URL, it has to be reloaded in a different site instance.
// In such case, we must treat it as an existing navigation in the new site
@@ -544,12 +514,6 @@ class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry {
// TODO(creis): Move this to FrameNavigationEntry.
int frame_tree_node_id_;
-#if defined(OS_ANDROID)
- // The time at which Chrome received the Android Intent that triggered this
- // URL load operation. Reset at commit and not persisted.
- base::TimeTicks intent_received_timestamp_;
-#endif
-
// Whether the URL load carries a user gesture.
bool has_user_gesture_;
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 c592771aa78..a95cedbd6cb 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
@@ -2,12 +2,15 @@
// 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_entry_impl.h"
+
+#include "base/path_service.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/test_file_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/public/browser/ssl_status.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -328,4 +331,22 @@ TEST_F(NavigationEntryTest, NavigationEntryExtraData) {
EXPECT_EQ(ASCIIToUTF16(""), output2);
}
+#if defined(OS_ANDROID)
+// Test that content URIs correctly show the file display name as the title.
+TEST_F(NavigationEntryTest, NavigationEntryContentUri) {
+ base::FilePath image_path;
+ EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &image_path));
+ image_path = image_path.Append(FILE_PATH_LITERAL("content"));
+ image_path = image_path.Append(FILE_PATH_LITERAL("test"));
+ image_path = image_path.Append(FILE_PATH_LITERAL("data"));
+ image_path = image_path.Append(FILE_PATH_LITERAL("blank.jpg"));
+ EXPECT_TRUE(base::PathExists(image_path));
+
+ base::FilePath content_uri = base::InsertImageIntoMediaStore(image_path);
+
+ entry1_->SetURL(GURL(content_uri.value()));
+ EXPECT_EQ(ASCIIToUTF16("blank.jpg"), entry1_->GetTitleForDisplay());
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.cc b/chromium/content/browser/frame_host/navigation_handle_impl.cc
index b23698013a0..201f23b9b42 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.cc
@@ -22,6 +22,7 @@
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/navigator_delegate.h"
+#include "content/browser/frame_host/origin_policy_throttle.h"
#include "content/browser/frame_host/webui_navigation_throttle.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -950,8 +951,7 @@ void NavigationHandleImpl::DidCommitNavigation(
subframe_entry_committed_ = navigation_entry_committed;
// For successful navigations, ensure the frame owner element is no longer
- // collapsed as a result of a prior navigation having been blocked with
- // BLOCK_REQUEST_AND_COLLAPSE.
+ // collapsed as a result of a prior navigation.
if (!IsErrorPage() && !frame_tree_node()->IsMainFrame()) {
// The last committed load in collapsed frames will be an error page with
// |kUnreachableWebDataURL|. Same-document navigation should not be
@@ -1022,8 +1022,6 @@ NavigationHandleImpl::CheckWillStartRequest() {
continue;
case NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE:
- frame_tree_node_->SetCollapsed(true);
- FALLTHROUGH;
case NavigationThrottle::BLOCK_REQUEST:
case NavigationThrottle::CANCEL:
case NavigationThrottle::CANCEL_AND_IGNORE:
@@ -1070,8 +1068,6 @@ NavigationHandleImpl::CheckWillRedirectRequest() {
continue;
case NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE:
- frame_tree_node_->SetCollapsed(true);
- FALLTHROUGH;
case NavigationThrottle::BLOCK_REQUEST:
case NavigationThrottle::CANCEL:
case NavigationThrottle::CANCEL_AND_IGNORE:
@@ -1250,9 +1246,6 @@ void NavigationHandleImpl::CancelDeferredNavigationInternal(
DCHECK(result.action() != NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE ||
state_ == DEFERRING_START || state_ == DEFERRING_REDIRECT);
- if (result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE)
- frame_tree_node_->SetCollapsed(true);
-
TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this,
"CancelDeferredNavigation");
state_ = CANCELING;
@@ -1309,6 +1302,9 @@ void NavigationHandleImpl::RegisterNavigationThrottles() {
AddThrottle(
MixedContentNavigationThrottle::CreateThrottleForNavigation(this));
+ // Handle Origin Policy (if enabled)
+ AddThrottle(OriginPolicyThrottle::MaybeCreateThrottleFor(this));
+
for (auto& throttle :
RenderFrameDevToolsAgentHost::CreateNavigationThrottles(this)) {
AddThrottle(std::move(throttle));
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.h b/chromium/content/browser/frame_host/navigation_handle_impl.h
index f11fe8d88e0..fe477a944b9 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.h
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.h
@@ -160,6 +160,11 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
bool IsDownload() override;
bool IsFormSubmission() override;
+ const std::string& origin_policy() const { return origin_policy_; }
+ void set_origin_policy(const std::string& origin_policy) {
+ origin_policy_ = origin_policy;
+ }
+
// Resume and CancelDeferredNavigation must only be called by the
// NavigationThrottle that is currently deferring the navigation.
// |resuming_throttle| and |cancelling_throttle| are the throttles calling
@@ -368,6 +373,10 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// url we're navigating to.
void SetExpectedProcess(RenderProcessHost* expected_process);
+ NavigationThrottle* GetDeferringThrottleForTesting() const {
+ return GetDeferringThrottle();
+ }
+
private:
friend class NavigationHandleImplTest;
@@ -557,6 +566,9 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// in it.
int expected_render_process_host_id_;
+ // The origin policy that applies to this navigation. Empty if none applies.
+ std::string origin_policy_;
+
// Whether the navigation is in the middle of a transfer. Set to false when
// the DidStartProvisionalLoad is received from the new renderer.
bool is_transferring_;
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
index fd806c769b3..c199bfb8bb9 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -6,7 +6,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/stringprintf.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigation_request.h"
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
index ecc9736c95c..7fab20e8173 100644
--- a/chromium/content/browser/frame_host/navigation_request.cc
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -24,6 +24,7 @@
#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/frame_host/origin_policy_throttle.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/loader/navigation_url_loader.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -66,7 +67,9 @@
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
+#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
+#include "url/url_constants.h"
namespace content {
@@ -207,13 +210,21 @@ void AddAdditionalRequestHeaders(
}
}
std::string value = base::StringPrintf(
- "cause=%s, destination=document, target=%s, site=%s",
+ "cause=\"%s\", destination=\"document\", target=\"%s\", site=\"%s\"",
has_user_gesture ? "user-activated" : "forced",
frame_tree_node->IsMainFrame() ? "top-level" : "nested",
site_value.c_str());
headers->SetHeaderIfMissing("Sec-Metadata", value);
}
+ // Ask whether we should request a policy.
+ std::string origin_policy_request;
+ if (OriginPolicyThrottle::ShouldRequestOriginPolicy(url,
+ &origin_policy_request)) {
+ headers->SetHeader(net::HttpRequestHeaders::kSecOriginPolicy,
+ origin_policy_request);
+ }
+
// Next, set the HTTP Origin if needed.
if (!NeedsHTTPOrigin(headers, method))
return;
@@ -335,7 +346,7 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
GURL() /* client_side_redirect_url */,
base::nullopt /* devtools_initiator_info */),
request_params, browser_initiated, false /* from_begin_navigation */,
- &frame_entry, &entry, std::move(navigation_ui_data)));
+ &frame_entry, &entry, std::move(navigation_ui_data), nullptr));
navigation_request->blob_url_loader_factory_ =
frame_entry.blob_url_loader_factory();
return navigation_request;
@@ -350,7 +361,8 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
int current_history_list_offset,
int current_history_list_length,
bool override_user_agent,
- scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client) {
// Only normal navigations to a different document or reloads are expected.
// - Renderer-initiated fragment-navigations never take place in the browser,
// even with PlzNavigate.
@@ -384,7 +396,8 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
false, // browser_initiated
true, // from_begin_navigation
nullptr, entry,
- nullptr)); // navigation_ui_data
+ nullptr, // navigation_ui_data
+ std::move(navigation_client)));
navigation_request->blob_url_loader_factory_ =
std::move(blob_url_loader_factory);
return navigation_request;
@@ -399,7 +412,8 @@ NavigationRequest::NavigationRequest(
bool from_begin_navigation,
const FrameNavigationEntry* frame_entry,
const NavigationEntryImpl* entry,
- std::unique_ptr<NavigationUIData> navigation_ui_data)
+ std::unique_ptr<NavigationUIData> navigation_ui_data,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client)
: frame_tree_node_(frame_tree_node),
common_params_(common_params),
begin_params_(std::move(begin_params)),
@@ -416,6 +430,8 @@ NavigationRequest::NavigationRequest(
has_stale_copy_in_cache_(false),
net_error_(net::OK),
devtools_navigation_token_(base::UnguessableToken::Create()),
+ request_navigation_client_(nullptr),
+ commit_navigation_client_(nullptr),
weak_factory_(this) {
DCHECK(!browser_initiated || (entry != nullptr && frame_entry != nullptr));
DCHECK(!IsRendererDebugURL(common_params_.url));
@@ -433,7 +449,19 @@ NavigationRequest::NavigationRequest(
// initiating renderer.
source_site_instance_ =
frame_tree_node->current_frame_host()->GetSiteInstance();
+
+ if (IsPerNavigationMojoInterfaceEnabled()) {
+ DCHECK(navigation_client.is_valid());
+ request_navigation_client_ = mojom::NavigationClientAssociatedPtr();
+ request_navigation_client_.Bind(std::move(navigation_client));
+ // Binds the OnAbort callback
+ request_navigation_client_.set_connection_error_handler(
+ base::BindOnce(&NavigationRequest::OnRendererAbortedNavigation,
+ base::Unretained(this)));
+ associated_site_instance_id_ = source_site_instance_->GetId();
+ }
} else {
+ DCHECK(!navigation_client.is_valid());
FrameNavigationEntry* frame_navigation_entry =
entry->GetFrameEntry(frame_tree_node);
if (frame_navigation_entry) {
@@ -551,7 +579,10 @@ void NavigationRequest::BeginNavigation() {
// Don't create a NavigationHandle here to simulate what happened with the
// old navigation code path (i.e. doesn't fire onPageFinished notification
// for aborted loads).
- OnRequestFailed(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(net::ERR_ABORTED),
+ false /*skip_throttles*/, base::nullopt /*error_page_content*/,
+ false /*collapse_frame*/);
return;
}
#endif
@@ -561,16 +592,18 @@ void NavigationRequest::BeginNavigation() {
// otherwise block. Similarly, the NavigationHandle is created afterwards, so
// that it gets the request URL after potentially being modified by CSP.
net::Error net_error = CheckContentSecurityPolicy(
- false /* is redirect */, false /* is_response_check */);
+ false /* is redirect */, false /* url_upgraded_after_redirect */,
+ false /* is_response_check */);
if (net_error != net::OK) {
// Create a navigation handle so that the correct error code can be set on
- // it by OnRequestFailed().
+ // it by OnRequestFailedInternal().
CreateNavigationHandle();
OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error),
false /* skip_throttles */,
- base::nullopt /* error_page_content */);
- // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
- // destroyed the NavigationRequest.
+ base::nullopt /* error_page_content */,
+ false /* collapse_frame */);
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
@@ -579,14 +612,15 @@ void NavigationRequest::BeginNavigation() {
CheckLegacyProtocolInSubresource() ==
LegacyProtocolInSubresourceCheckResult::BLOCK_REQUEST) {
// Create a navigation handle so that the correct error code can be set on
- // it by OnRequestFailed().
+ // it by OnRequestFailedInternal().
CreateNavigationHandle();
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
- false /* skip_throttles */, base::nullopt /* error_page_content */);
+ false /* skip_throttles */, base::nullopt /* error_page_content */,
+ false /* collapse_frame */);
- // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
- // destroyed the NavigationRequest.
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
@@ -692,7 +726,9 @@ void NavigationRequest::ResetForCrossDocumentRestart() {
FrameMsg_Navigate_Type::IsSameDocument(common_params_.navigation_type));
// Reset the NavigationHandle, which is now incorrectly marked as
- // same-document.
+ // same-document. Ensure |loader_| does not exist as it can hold raw pointers
+ // to objects owned by the handle (see the comment in the header).
+ DCHECK(!loader_);
navigation_handle_.reset();
// Convert the navigation type to the appropriate cross-document one.
@@ -718,6 +754,12 @@ void NavigationRequest::RegisterSubresourceOverride(
subresource_overrides_->push_back(std::move(transferrable_loader));
}
+mojom::NavigationClient* NavigationRequest::GetCommitNavigationClient() {
+ if (commit_navigation_client_ && commit_navigation_client_.is_bound())
+ return commit_navigation_client_.get();
+ return nullptr;
+}
+
void NavigationRequest::OnRequestRedirected(
const net::RedirectInfo& redirect_info,
const scoped_refptr<network::ResourceResponse>& response) {
@@ -760,7 +802,6 @@ void NavigationRequest::OnRequestRedirected(
return;
}
#endif
-
if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRedirectToURL(
redirect_info.new_url)) {
DVLOG(1) << "Denied redirect for "
@@ -784,10 +825,6 @@ void NavigationRequest::OnRequestRedirected(
return;
}
- // If a redirect occurs, the original site instance we thought is the
- // destination could change.
- dest_site_instance_ = nullptr;
-
// For now, DevTools needs the POST data sent to the renderer process even if
// it is no longer a POST after the redirect.
if (redirect_info.new_method != "POST")
@@ -815,12 +852,15 @@ void NavigationRequest::OnRequestRedirected(
// gives CSP a chance to modify requests that NavigationThrottles would
// otherwise block.
net::Error net_error = CheckContentSecurityPolicy(
- true /* is redirect */, false /* is_response_check */);
+ true /* is redirect */, redirect_info.insecure_scheme_was_upgraded,
+ false /* is_response_check */);
if (net_error != net::OK) {
- OnRequestFailed(network::URLLoaderCompletionStatus(net_error));
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(net_error), false /*skip_throttles*/,
+ base::nullopt /*error_page_content*/, false /*collapse_frame*/);
- // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
- // destroyed the NavigationRequest.
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
@@ -828,10 +868,13 @@ void NavigationRequest::OnRequestRedirected(
CredentialedSubresourceCheckResult::BLOCK_REQUEST ||
CheckLegacyProtocolInSubresource() ==
LegacyProtocolInSubresourceCheckResult::BLOCK_REQUEST) {
- OnRequestFailed(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(net::ERR_ABORTED),
+ false /*skip_throttles*/, base::nullopt /*error_page_content*/,
+ false /*collapse_frame*/);
- // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
- // destroyed the NavigationRequest.
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
@@ -1039,14 +1082,16 @@ void NavigationRequest::OnResponseStarted(
// redirect or not in order to perform its checks. This is the reason
// why we need to check the CSP both on request and response.
net::Error net_error = CheckContentSecurityPolicy(
- navigation_handle_->WasServerRedirect(), true /* is_response_check */);
+ navigation_handle_->WasServerRedirect(),
+ false /* url_upgraded_after_redirect */, true /* is_response_check */);
if (net_error != net::OK) {
OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error),
false /* skip_throttles */,
- base::nullopt /* error_page_content */);
+ base::nullopt /* error_page_content */,
+ false /* collapse_frame */);
- // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
- // destroyed the NavigationRequest.
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
@@ -1062,15 +1107,19 @@ void NavigationRequest::OnResponseStarted(
void NavigationRequest::OnRequestFailed(
const network::URLLoaderCompletionStatus& status) {
- NavigationRequest::OnRequestFailedInternal(
- status, false /* skip_throttles */,
- base::nullopt /* error_page_content */);
+ bool collapse_frame =
+ status.extended_error_code ==
+ static_cast<int>(blink::ResourceRequestBlockedReason::kCollapsedByClient);
+ OnRequestFailedInternal(status, false /* skip_throttles */,
+ base::nullopt /* error_page_content */,
+ collapse_frame);
}
void NavigationRequest::OnRequestFailedInternal(
const network::URLLoaderCompletionStatus& status,
bool skip_throttles,
- const base::Optional<std::string>& error_page_content) {
+ const base::Optional<std::string>& error_page_content,
+ bool collapse_frame) {
DCHECK(state_ == STARTED || state_ == RESPONSE_STARTED);
DCHECK(!(status.error_code == net::ERR_ABORTED &&
error_page_content.has_value()));
@@ -1099,6 +1148,12 @@ void NavigationRequest::OnRequestFailedInternal(
return;
}
+ if (collapse_frame) {
+ DCHECK(!frame_tree_node_->IsMainFrame());
+ DCHECK_EQ(net::ERR_BLOCKED_BY_CLIENT, status.error_code);
+ frame_tree_node_->SetCollapsed(true);
+ }
+
RenderFrameHostImpl* render_frame_host = nullptr;
if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(
frame_tree_node_->IsMainFrame())) {
@@ -1125,10 +1180,6 @@ void NavigationRequest::OnRequestFailedInternal(
DCHECK(render_frame_host);
- // Don't ask the renderer to commit an URL if the browser will kill it when
- // it does.
- DCHECK(render_frame_host->CanCommitURL(common_params_.url));
-
NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL(render_frame_host,
common_params_.url);
@@ -1202,6 +1253,9 @@ void NavigationRequest::OnStartChecksComplete(
}
#endif
+ bool collapse_frame =
+ result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
+
// If the start checks completed synchronously, which could happen if there
// is no onbeforeunload handler or if a NavigationThrottle cancelled it,
// then this could cause reentrancy into NavigationController. So use a
@@ -1212,10 +1266,11 @@ void NavigationRequest::OnStartChecksComplete(
&NavigationRequest::OnRequestFailedInternal,
weak_factory_.GetWeakPtr(),
network::URLLoaderCompletionStatus(result.net_error_code()),
- true /* skip_throttles */, result.error_page_content()));
+ true /* skip_throttles */, result.error_page_content(),
+ collapse_frame));
- // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
- // destroyed the NavigationRequest.
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
@@ -1237,6 +1292,11 @@ void NavigationRequest::OnStartChecksComplete(
browser_context, navigating_frame_host->GetSiteInstance());
DCHECK(partition);
+ // |loader_| should not exist if the service worker handle and app cache
+ // handles will be destroyed, since it holds raw pointers to them. See the
+ // comment in the header for |loader_|.
+ DCHECK(!loader_);
+
// Only initialize the ServiceWorkerNavigationHandle if it can be created for
// this frame.
bool can_create_service_worker =
@@ -1326,9 +1386,11 @@ void NavigationRequest::OnStartChecksComplete(
report_raw_headers,
navigating_frame_host->GetVisibilityState() ==
blink::mojom::PageVisibilityState::kPrerender,
+ upgrade_if_insecure_,
blob_url_loader_factory_ ? blob_url_loader_factory_->Clone()
: nullptr,
- devtools_navigation_token()),
+ devtools_navigation_token(),
+ frame_tree_node_->devtools_frame_token()),
std::move(navigation_ui_data),
navigation_handle_->service_worker_handle(),
navigation_handle_->appcache_handle(), this);
@@ -1339,6 +1401,9 @@ void NavigationRequest::OnRedirectChecksComplete(
DCHECK(result.action() != NavigationThrottle::DEFER);
DCHECK(result.action() != NavigationThrottle::BLOCK_RESPONSE);
+ bool collapse_frame =
+ result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
+
// Abort the request if needed. This will destroy the NavigationRequest.
if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
result.action() == NavigationThrottle::CANCEL) {
@@ -1347,10 +1412,10 @@ void NavigationRequest::OnRedirectChecksComplete(
result.net_error_code() == net::ERR_ABORTED);
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(result.net_error_code()),
- true /* skip_throttles */, result.error_page_content());
+ true /* skip_throttles */, result.error_page_content(), collapse_frame);
- // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
- // destroyed the NavigationRequest.
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
@@ -1360,15 +1425,21 @@ void NavigationRequest::OnRedirectChecksComplete(
result.net_error_code() == net::ERR_BLOCKED_BY_ADMINISTRATOR);
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(result.net_error_code()),
- true /* skip_throttles */, result.error_page_content());
- // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
- // destroyed the NavigationRequest.
+ true /* skip_throttles */, result.error_page_content(), collapse_frame);
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
RenderFrameDevToolsAgentHost::OnNavigationRequestWillBeSent(*this);
- loader_->FollowRedirect();
+ base::Optional<net::HttpRequestHeaders> embedder_additional_headers;
+ GetContentClient()->browser()->NavigationRequestRedirected(
+ frame_tree_node_->frame_tree_node_id(), common_params_.url,
+ &embedder_additional_headers);
+
+ loader_->FollowRedirect(base::nullopt,
+ std::move(embedder_additional_headers));
}
void NavigationRequest::OnFailureChecksComplete(
@@ -1436,7 +1507,10 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
response_, std::move(url_loader_client_endpoints_),
ssl_info_.cert_status, frame_tree_node_->frame_tree_node_id());
- OnRequestFailed(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(net::ERR_ABORTED),
+ false /*skip_throttles*/, base::nullopt /*error_page_content*/,
+ false /*collapse_frame*/);
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
return;
@@ -1471,7 +1545,8 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
// destroyed the NavigationRequest.
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
- true /* skip_throttles */, base::nullopt /* error_page_content */);
+ true /* skip_throttles */, base::nullopt /* error_page_content */,
+ false /* collapse_frame */);
return;
}
@@ -1479,10 +1554,11 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
result.net_error_code() == net::ERR_ABORTED);
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(result.net_error_code()),
- true /* skip_throttles */, result.error_page_content());
+ true /* skip_throttles */, result.error_page_content(),
+ false /* collapse_frame */);
- // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
- // destroyed the NavigationRequest.
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
@@ -1490,9 +1566,10 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
DCHECK_EQ(net::ERR_BLOCKED_BY_RESPONSE, result.net_error_code());
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(result.net_error_code()),
- true /* skip_throttles */, result.error_page_content());
- // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
- // destroyed the NavigationRequest.
+ true /* skip_throttles */, result.error_page_content(),
+ false /* collapse_frame */);
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
@@ -1507,10 +1584,28 @@ void NavigationRequest::CommitErrorPage(
const base::Optional<std::string>& error_page_content) {
UpdateRequestNavigationParamsHistory();
frame_tree_node_->TransferNavigationRequestOwnership(render_frame_host);
+ if (IsPerNavigationMojoInterfaceEnabled() && request_navigation_client_ &&
+ request_navigation_client_.is_bound()) {
+ // Two cases are possible here:
+ // Either we have a same-site navigation in which case the navigation
+ // request needs to be canceled in the RFH, so we need to rebind the handler
+ // to a post-ReadyToCommit handler.
+ // TODO(ahemery): Implement this second abort handler.
+ // Or this navigation is cross-site: the original document should no longer
+ // be able to cancel it.
+ IgnorePipeDisconnection();
+ if (associated_site_instance_id_ ==
+ render_frame_host->GetSiteInstance()->GetId()) {
+ // Reuse the request NavigationClient for commit.
+ commit_navigation_client_ = std::move(request_navigation_client_);
+ }
+ associated_site_instance_id_.reset();
+ }
+
navigation_handle_->ReadyToCommitNavigation(render_frame_host, true);
- render_frame_host->FailedNavigation(common_params_, request_params_,
- has_stale_copy_in_cache_, net_error_,
- error_page_content);
+ render_frame_host->FailedNavigation(
+ navigation_handle_->GetNavigationId(), common_params_, request_params_,
+ has_stale_copy_in_cache_, net_error_, error_page_content);
}
void NavigationRequest::CommitNavigation() {
@@ -1519,6 +1614,11 @@ void NavigationRequest::CommitNavigation() {
navigation_handle_->IsSameDocument());
DCHECK(!common_params_.url.SchemeIs(url::kJavaScriptScheme));
+ // Send the applicable origin policy (if any) along with the request.
+ // (The policy is fetched by a throttle and is thus available only now.)
+ DCHECK(common_params_.origin_policy.empty());
+ common_params_.origin_policy = navigation_handle_->origin_policy();
+
// Retrieve the RenderFrameHost that needs to commit the navigation.
RenderFrameHostImpl* render_frame_host =
navigation_handle_->GetRenderFrameHost();
@@ -1528,9 +1628,27 @@ void NavigationRequest::CommitNavigation() {
frame_tree_node_->render_manager()->speculative_frame_host());
frame_tree_node_->TransferNavigationRequestOwnership(render_frame_host);
+ if (IsPerNavigationMojoInterfaceEnabled() && request_navigation_client_ &&
+ request_navigation_client_.is_bound()) {
+ // Two cases are possible here:
+ // Either we have a same-site navigation in which case the navigation
+ // request needs to be canceled in the RFH, so we need to rebind the handler
+ // to a post-ReadyToCommit handler.
+ // TODO(ahemery): Implement this second abort handler.
+ // Or this navigation is cross-site: the original document should no longer
+ // be able to cancel it.
+ IgnorePipeDisconnection();
+ if (associated_site_instance_id_ ==
+ render_frame_host->GetSiteInstance()->GetId()) {
+ // Reuse the request NavigationClient for commit.
+ commit_navigation_client_ = std::move(request_navigation_client_);
+ }
+ associated_site_instance_id_.reset();
+ }
render_frame_host->CommitNavigation(
- response_.get(), std::move(url_loader_client_endpoints_), common_params_,
- request_params_, is_view_source_, std::move(subresource_loader_params_),
+ navigation_handle_->GetNavigationId(), response_.get(),
+ std::move(url_loader_client_endpoints_), common_params_, request_params_,
+ is_view_source_, std::move(subresource_loader_params_),
std::move(subresource_overrides_), devtools_navigation_token_);
// Give SpareRenderProcessHostManager a heads-up about the most recently used
@@ -1544,10 +1662,23 @@ bool NavigationRequest::IsAllowedByCSPDirective(
CSPContext* context,
CSPDirective::Name directive,
bool is_redirect,
+ bool url_upgraded_after_redirect,
bool is_response_check,
CSPContext::CheckCSPDisposition disposition) {
+ GURL url;
+ // If this request was upgraded in the net stack, downgrade the URL back to
+ // HTTP before checking report only policies.
+ if (url_upgraded_after_redirect &&
+ disposition == CSPContext::CheckCSPDisposition::CHECK_REPORT_ONLY_CSP &&
+ common_params_.url.SchemeIs(url::kHttpsScheme)) {
+ GURL::Replacements replacements;
+ replacements.SetSchemeStr(url::kHttpScheme);
+ url = common_params_.url.ReplaceComponents(replacements);
+ } else {
+ url = common_params_.url;
+ }
return context->IsAllowedByCsp(
- directive, common_params_.url, is_redirect, is_response_check,
+ directive, url, is_redirect, is_response_check,
common_params_.source_location.value_or(SourceLocation()), disposition,
begin_params_->is_form_submission);
}
@@ -1555,17 +1686,18 @@ bool NavigationRequest::IsAllowedByCSPDirective(
net::Error NavigationRequest::CheckCSPDirectives(
RenderFrameHostImpl* parent,
bool is_redirect,
+ bool url_upgraded_after_redirect,
bool is_response_check,
CSPContext::CheckCSPDisposition disposition) {
bool navigate_to_allowed = IsAllowedByCSPDirective(
initiator_csp_context_.get(), CSPDirective::NavigateTo, is_redirect,
- is_response_check, disposition);
+ url_upgraded_after_redirect, is_response_check, disposition);
bool frame_src_allowed = true;
if (parent) {
- frame_src_allowed =
- IsAllowedByCSPDirective(parent, CSPDirective::FrameSrc, is_redirect,
- is_response_check, disposition);
+ frame_src_allowed = IsAllowedByCSPDirective(
+ parent, CSPDirective::FrameSrc, is_redirect,
+ url_upgraded_after_redirect, is_response_check, disposition);
}
if (navigate_to_allowed && frame_src_allowed)
@@ -1585,6 +1717,7 @@ net::Error NavigationRequest::CheckCSPDirectives(
net::Error NavigationRequest::CheckContentSecurityPolicy(
bool is_redirect,
+ bool url_upgraded_after_redirect,
bool is_response_check) {
if (common_params_.url.SchemeIs(url::kAboutScheme))
return net::OK;
@@ -1616,23 +1749,23 @@ net::Error NavigationRequest::CheckContentSecurityPolicy(
// requests that are upgraded in step 2.
net::Error report_only_csp_status =
- CheckCSPDirectives(parent, is_redirect, is_response_check,
- CSPContext::CHECK_REPORT_ONLY_CSP);
+ CheckCSPDirectives(parent, is_redirect, url_upgraded_after_redirect,
+ is_response_check, CSPContext::CHECK_REPORT_ONLY_CSP);
- // TODO(mkwst,estark): upgrade-insecure-requests does not work when following
- // redirects. Trying to uprade the new URL on redirect here is fruitless: the
- // redirect URL cannot be changed at this point. upgrade-insecure-requests
- // needs to move to the net stack to resolve this. https://crbug.com/615885
+ // upgrade-insecure-requests is handled in the network code for redirects,
+ // only do the upgrade here if this is not a redirect.
if (!is_redirect && !frame_tree_node()->IsMainFrame()) {
if (parent &&
parent->ShouldModifyRequestUrlForCsp(true /* is subresource */)) {
+ upgrade_if_insecure_ = true;
parent->ModifyRequestUrlForCsp(&common_params_.url);
request_params_.original_url = common_params_.url;
}
}
- net::Error enforced_csp_status = CheckCSPDirectives(
- parent, is_redirect, is_response_check, CSPContext::CHECK_ENFORCED_CSP);
+ net::Error enforced_csp_status =
+ CheckCSPDirectives(parent, is_redirect, url_upgraded_after_redirect,
+ is_response_check, CSPContext::CHECK_ENFORCED_CSP);
if (enforced_csp_status != net::OK)
return enforced_csp_status;
return report_only_csp_status;
@@ -1713,4 +1846,15 @@ void NavigationRequest::UpdateRequestNavigationParamsHistory() {
navigation_controller->GetEntryCount();
}
+void NavigationRequest::OnRendererAbortedNavigation() {
+ frame_tree_node_->navigator()->CancelNavigation(frame_tree_node_, false);
+
+ // Do not add code after this, NavigationRequest has been destroyed.
+}
+
+void NavigationRequest::IgnorePipeDisconnection() {
+ return request_navigation_client_.set_connection_error_handler(
+ base::DoNothing());
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_request.h b/chromium/content/browser/frame_host/navigation_request.h
index 164401d6db4..10440a4a70c 100644
--- a/chromium/content/browser/frame_host/navigation_request.h
+++ b/chromium/content/browser/frame_host/navigation_request.h
@@ -108,7 +108,8 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
int current_history_list_offset,
int current_history_list_length,
bool override_user_agent,
- scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client);
~NavigationRequest() override;
@@ -208,6 +209,11 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
void RegisterSubresourceOverride(
mojom::TransferrableURLLoaderPtr transferrable_loader);
+ // Returns the NavigationClient held by this navigation request that is ready
+ // to commit, or nullptr if there isn't any.
+ // Only used with PerNavigationMojoInterface enabled.
+ mojom::NavigationClient* GetCommitNavigationClient();
+
private:
NavigationRequest(FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
@@ -217,7 +223,8 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
bool from_begin_navigation,
const FrameNavigationEntry* frame_navigation_entry,
const NavigationEntryImpl* navitation_entry,
- std::unique_ptr<NavigationUIData> navigation_ui_data);
+ std::unique_ptr<NavigationUIData> navigation_ui_data,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client);
// NavigationURLLoaderDelegate implementation.
void OnRequestRedirected(
@@ -236,13 +243,17 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
const network::URLLoaderCompletionStatus& status) override;
void OnRequestStarted(base::TimeTicks timestamp) override;
- // A version of OnRequestFailed() that allows skipping throttles, to be used
- // when a request failed due to a throttle result itself. |error_page_content|
- // is only used when |skip_throttles| is true.
+ // To be called whenever a navigation request fails. If |skip_throttles| is
+ // true, the registered NavigationThrottle(s) won't get a chance to intercept
+ // NavigationThrottle::WillFailRequest. It should be used when a request
+ // failed due to a throttle result itself. |error_page_content| is only used
+ // when |skip_throttles| is true. If |collapse_frame| is true, the associated
+ // frame tree node is collapsed.
void OnRequestFailedInternal(
const network::URLLoaderCompletionStatus& status,
bool skip_throttles,
- const base::Optional<std::string>& error_page_content);
+ const base::Optional<std::string>& error_page_content,
+ bool collapse_frame);
// Helper to determine whether an error page for the provided error code
// should stay in the current process.
@@ -273,6 +284,7 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
bool IsAllowedByCSPDirective(CSPContext* context,
CSPDirective::Name directive,
bool is_redirect,
+ bool url_upgraded_after_redirect,
bool is_response_check,
CSPContext::CheckCSPDisposition disposition);
@@ -282,6 +294,7 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// net::ERR_BLOCKED_BY_CLIENT depending on which checks fail.
net::Error CheckCSPDirectives(RenderFrameHostImpl* parent,
bool is_redirect,
+ bool url_upgraded_after_redirect,
bool is_response_check,
CSPContext::CheckCSPDisposition disposition);
@@ -292,6 +305,7 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// - The navigation request may be upgraded from HTTP to HTTPS if a CSP is
// configured to upgrade insecure requests.
net::Error CheckContentSecurityPolicy(bool is_redirect,
+ bool url_upgraded_after_redirect,
bool is_response_check);
// This enum describes the result of the credentialed subresource check for
@@ -323,6 +337,17 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// renderer process.
void UpdateRequestNavigationParamsHistory();
+ // Called when an ongoing renderer-initiated navigation is aborted.
+ // Only used with PerNavigationMojoInterface enabled.
+ void OnRendererAbortedNavigation();
+
+ // When called, this NavigationRequest will no longer interpret the pipe
+ // disconnection on the renderer side as an AbortNavigation.
+ // TODO(ahemery): remove this function when NavigationRequest properly handles
+ // pipe disconnection in all cases. Only used with PerNavigationMojoInterface
+ // enabled.
+ void IgnorePipeDisconnection();
+
FrameTreeNode* frame_tree_node_;
// Initialized on creation of the NavigationRequest. Sent to the renderer when
@@ -349,6 +374,12 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
NavigationState state_;
+ // It's important to ensure |navigation_handle_| outlives |loader_|, since the
+ // loader holds raw pointers to objects owned by the navigation handle
+ // (namely, the AppCache and service worker handles). The destruction order
+ // matters because it occurs over separate tasks on the IO thread. So, declare
+ // the handle before the loader.
+ std::unique_ptr<NavigationHandleImpl> navigation_handle_;
std::unique_ptr<NavigationURLLoader> loader_;
// These next items are used in browser-initiated navigations to store
@@ -380,8 +411,6 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// process expects to be notified if the navigation is aborted.
bool from_begin_navigation_;
- std::unique_ptr<NavigationHandleImpl> navigation_handle_;
-
// Holds objects received from OnResponseStarted while the WillProcessResponse
// checks are performed by the NavigationHandle. Once the checks have been
// completed, these objects will be used to continue the navigation.
@@ -409,6 +438,24 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>>
subresource_overrides_;
+ // The NavigationClient interface for that requested this navigation in the
+ // case of a renderer initiated navigation. It is expected to be bound until
+ // this navigation commits or is canceled.
+ // Only valid when PerNavigationMojoInterface is enabled.
+ mojom::NavigationClientAssociatedPtr request_navigation_client_;
+ base::Optional<int32_t> associated_site_instance_id_;
+
+ // The NavigationClient interface used to commit the navigation. For now, this
+ // is only used for same-site renderer-initiated navigation.
+ // TODO(clamy, ahemery): Extend to all types of navigation.
+ // Only valid when PerNavigationMojoInterface is enabled.
+ mojom::NavigationClientAssociatedPtr commit_navigation_client_;
+
+ // If set, any redirects to HTTP for this navigation will be upgraded to
+ // HTTPS. This is used only on subframe navigations, when
+ // upgrade-insecure-requests is set as a CSP policy.
+ bool upgrade_if_insecure_ = false;
+
base::WeakPtrFactory<NavigationRequest> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NavigationRequest);
diff --git a/chromium/content/browser/frame_host/navigation_request_info.cc b/chromium/content/browser/frame_host/navigation_request_info.cc
index 51d8563db09..f02f9a18f6a 100644
--- a/chromium/content/browser/frame_host/navigation_request_info.cc
+++ b/chromium/content/browser/frame_host/navigation_request_info.cc
@@ -18,9 +18,11 @@ NavigationRequestInfo::NavigationRequestInfo(
bool is_for_guests_only,
bool report_raw_headers,
bool is_prerendering,
+ bool upgrade_if_insecure,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
blob_url_loader_factory,
- const base::UnguessableToken& devtools_navigation_token)
+ const base::UnguessableToken& devtools_navigation_token,
+ const base::UnguessableToken& devtools_frame_token)
: common_params(common_params),
begin_params(std::move(begin_params)),
site_for_cookies(site_for_cookies),
@@ -31,8 +33,10 @@ NavigationRequestInfo::NavigationRequestInfo(
is_for_guests_only(is_for_guests_only),
report_raw_headers(report_raw_headers),
is_prerendering(is_prerendering),
+ upgrade_if_insecure(upgrade_if_insecure),
blob_url_loader_factory(std::move(blob_url_loader_factory)),
- devtools_navigation_token(devtools_navigation_token) {}
+ devtools_navigation_token(devtools_navigation_token),
+ devtools_frame_token(devtools_frame_token) {}
NavigationRequestInfo::NavigationRequestInfo(const NavigationRequestInfo& other)
: common_params(other.common_params),
@@ -45,7 +49,8 @@ NavigationRequestInfo::NavigationRequestInfo(const NavigationRequestInfo& other)
is_for_guests_only(other.is_for_guests_only),
report_raw_headers(other.report_raw_headers),
is_prerendering(other.is_prerendering),
- devtools_navigation_token(other.devtools_navigation_token) {}
+ upgrade_if_insecure(other.upgrade_if_insecure),
+ devtools_frame_token(other.devtools_frame_token) {}
NavigationRequestInfo::~NavigationRequestInfo() {}
diff --git a/chromium/content/browser/frame_host/navigation_request_info.h b/chromium/content/browser/frame_host/navigation_request_info.h
index 304502f0a25..8b6a81c92d9 100644
--- a/chromium/content/browser/frame_host/navigation_request_info.h
+++ b/chromium/content/browser/frame_host/navigation_request_info.h
@@ -23,20 +23,21 @@ namespace content {
// ResourceDispatcherHost. It is initialized on the UI thread, and then passed
// to the IO thread by a NavigationRequest object.
struct CONTENT_EXPORT NavigationRequestInfo {
- NavigationRequestInfo(
- const CommonNavigationParams& common_params,
- mojom::BeginNavigationParamsPtr begin_params,
- const GURL& site_for_cookies,
- bool is_main_frame,
- bool parent_is_main_frame,
- bool are_ancestors_secure,
- int frame_tree_node_id,
- bool is_for_guests_only,
- bool report_raw_headers,
- bool is_prerendering,
- std::unique_ptr<network::SharedURLLoaderFactoryInfo>
- blob_url_loader_factory,
- const base::UnguessableToken& devtools_navigation_token);
+ NavigationRequestInfo(const CommonNavigationParams& common_params,
+ mojom::BeginNavigationParamsPtr begin_params,
+ const GURL& site_for_cookies,
+ bool is_main_frame,
+ bool parent_is_main_frame,
+ bool are_ancestors_secure,
+ int frame_tree_node_id,
+ bool is_for_guests_only,
+ bool report_raw_headers,
+ bool is_prerendering,
+ bool upgrade_if_insecure,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ blob_url_loader_factory,
+ const base::UnguessableToken& devtools_navigation_token,
+ const base::UnguessableToken& devtools_frame_token);
NavigationRequestInfo(const NavigationRequestInfo& other);
~NavigationRequestInfo();
@@ -62,10 +63,16 @@ struct CONTENT_EXPORT NavigationRequestInfo {
const bool is_prerendering;
+ // If set to true, any HTTP redirects of this request will be upgraded to
+ // HTTPS. This only applies for subframe navigations.
+ const bool upgrade_if_insecure;
+
// URLLoaderFactory to facilitate loading blob URLs.
std::unique_ptr<network::SharedURLLoaderFactoryInfo> blob_url_loader_factory;
const base::UnguessableToken devtools_navigation_token;
+
+ const base::UnguessableToken devtools_frame_token;
};
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator.cc b/chromium/content/browser/frame_host/navigator.cc
index 0876a3899ad..59cea6fbf74 100644
--- a/chromium/content/browser/frame_host/navigator.cc
+++ b/chromium/content/browser/frame_host/navigator.cc
@@ -17,28 +17,6 @@ NavigationController* Navigator::GetController() {
return nullptr;
}
-bool Navigator::NavigateToPendingEntry(
- FrameTreeNode* frame_tree_node,
- const FrameNavigationEntry& frame_entry,
- ReloadType reload_type,
- bool is_same_document_history_load,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
- return false;
-}
-
-bool Navigator::NavigateToEntry(
- FrameTreeNode* frame_tree_node,
- const FrameNavigationEntry& frame_entry,
- const NavigationEntryImpl& entry,
- ReloadType reload_type,
- bool is_same_document_history_load,
- bool is_history_navigation_in_new_child,
- bool is_pending_entry,
- const scoped_refptr<network::ResourceRequestBody>& post_body,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
- return false;
-}
-
bool Navigator::StartHistoryNavigationInNewSubframe(
RenderFrameHostImpl* render_frame_host,
const GURL& default_url) {
@@ -53,6 +31,7 @@ void Navigator::OnBeginNavigation(
FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
- scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {}
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client) {}
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator.h b/chromium/content/browser/frame_host/navigator.h
index 5290287896d..fe5fe87f06f 100644
--- a/chromium/content/browser/frame_host/navigator.h
+++ b/chromium/content/browser/frame_host/navigator.h
@@ -84,37 +84,6 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
std::unique_ptr<NavigationHandleImpl> navigation_handle,
bool was_within_same_document) {}
- // Called by the NavigationController to cause the Navigator to navigate
- // to the current pending entry. The NavigationController should be called
- // back with RendererDidNavigate on success or DiscardPendingEntry on failure.
- // The callbacks can be inside of this function, or at some future time.
- //
- // If this method returns false, then the navigation is discarded (equivalent
- // to calling DiscardPendingEntry on the NavigationController).
- //
- // TODO(nasko): Remove this method from the interface, since Navigator and
- // NavigationController know about each other. This will be possible once
- // initialization of Navigator and NavigationController is properly done.
- virtual bool NavigateToPendingEntry(
- FrameTreeNode* frame_tree_node,
- const FrameNavigationEntry& frame_entry,
- ReloadType reload_type,
- bool is_same_document_history_load,
- std::unique_ptr<NavigationUIData> navigation_ui_data);
- // DEPRECATED. Callers should use NavigateToPendingEntry instead.
- // TODO(clamy): This is only briefly exposed to facilitate a larger
- // refactoring of NavigationController and will go away soon.
- virtual bool NavigateToEntry(
- FrameTreeNode* frame_tree_node,
- const FrameNavigationEntry& frame_entry,
- const NavigationEntryImpl& entry,
- ReloadType reload_type,
- bool is_same_document_history_load,
- bool is_history_navigation_in_new_child,
- bool is_pending_entry,
- const scoped_refptr<network::ResourceRequestBody>& post_body,
- std::unique_ptr<NavigationUIData> navigation_ui_data);
-
// Called on a newly created subframe during a history navigation. The browser
// process looks up the corresponding FrameNavigationEntry for the new frame
// navigates it in the correct process. Returns false if the
@@ -127,6 +96,14 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
// Navigation requests -------------------------------------------------------
+ // Called by the NavigationController to cause the Navigator to navigate to
+ // |navigation_request|. The NavigationController should be called back with
+ // RendererDidNavigate on success or DiscardPendingEntry on failure. The
+ // callbacks should be called in a future iteration of the message loop.
+ virtual void Navigate(std::unique_ptr<NavigationRequest> request,
+ ReloadType reload_type,
+ RestoreType restore_type) {}
+
virtual base::TimeTicks GetCurrentLoadStart();
// The RenderFrameHostImpl has received a request to open a URL with the
@@ -173,7 +150,8 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
- scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client);
// Used to restart a navigation that was thought to be same-document in
// cross-document mode.
@@ -181,6 +159,7 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
std::unique_ptr<NavigationRequest> navigation_request) {}
// Used to abort an ongoing renderer-initiated navigation.
+ // Only used with PerNavigationMojoInterface disabled.
virtual void OnAbortNavigation(FrameTreeNode* frame_tree_node) {}
// Cancel a NavigationRequest for |frame_tree_node|. If the request is
diff --git a/chromium/content/browser/frame_host/navigator_delegate.cc b/chromium/content/browser/frame_host/navigator_delegate.cc
index 11b17d4f597..5ab06ef5a4b 100644
--- a/chromium/content/browser/frame_host/navigator_delegate.cc
+++ b/chromium/content/browser/frame_host/navigator_delegate.cc
@@ -34,7 +34,4 @@ std::unique_ptr<NavigationUIData> NavigatorDelegate::GetNavigationUIData(
return nullptr;
}
-void NavigatorDelegate::AdjustPreviewsStateForNavigation(
- PreviewsState* previews_state) {}
-
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator_delegate.h b/chromium/content/browser/frame_host/navigator_delegate.h
index fe0275288b5..cc58d99bfe5 100644
--- a/chromium/content/browser/frame_host/navigator_delegate.h
+++ b/chromium/content/browser/frame_host/navigator_delegate.h
@@ -11,7 +11,6 @@
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/browser/reload_type.h"
-#include "content/public/common/previews_state.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
@@ -134,13 +133,6 @@ class CONTENT_EXPORT NavigatorDelegate {
// Whether the delegate is displaying an interstitial page over the current
// page.
virtual bool ShowingInterstitialPage() const = 0;
-
- // Gives the delegate a chance to adjust the previews state during navigation.
- // When called, previews_state will be pointing to a valid set of previews, or
- // an enum value disabling previews. The call will change the value of
- // previews_state in place, and must change it to either a value disabling
- // previews, or a subset of the previews passed in.
- virtual void AdjustPreviewsStateForNavigation(PreviewsState* previews_state);
};
} // namspace content
diff --git a/chromium/content/browser/frame_host/navigator_impl.cc b/chromium/content/browser/frame_host/navigator_impl.cc
index e098e1bc69e..f53badc0816 100644
--- a/chromium/content/browser/frame_host/navigator_impl.cc
+++ b/chromium/content/browser/frame_host/navigator_impl.cc
@@ -39,6 +39,7 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/stream_handle.h"
#include "content/public/common/bindings_policy.h"
+#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/url_utils.h"
@@ -50,67 +51,6 @@
namespace content {
-namespace {
-
-FrameMsg_Navigate_Type::Value GetNavigationType(
- const GURL& old_url,
- const GURL& new_url,
- ReloadType reload_type,
- const NavigationEntryImpl& entry,
- const FrameNavigationEntry& frame_entry,
- bool is_same_document_history_load) {
- // Reload navigations
- switch (reload_type) {
- case ReloadType::NORMAL:
- return FrameMsg_Navigate_Type::RELOAD;
- case ReloadType::BYPASSING_CACHE:
- case ReloadType::DISABLE_PREVIEWS:
- return FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE;
- case ReloadType::ORIGINAL_REQUEST_URL:
- return FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
- case ReloadType::NONE:
- break; // Fall through to rest of function.
- }
-
- // |RenderViewImpl::PopulateStateFromPendingNavigationParams| differentiates
- // between |RESTORE_WITH_POST| and |RESTORE|.
- if (entry.restore_type() == RestoreType::LAST_SESSION_EXITED_CLEANLY) {
- if (entry.GetHasPostData())
- return FrameMsg_Navigate_Type::RESTORE_WITH_POST;
- else
- return FrameMsg_Navigate_Type::RESTORE;
- }
-
- // History navigations.
- if (frame_entry.page_state().IsValid()) {
- if (is_same_document_history_load)
- return FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT;
- else
- return FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
- }
- DCHECK(!is_same_document_history_load);
-
- // A same-document fragment-navigation happens when the only part of the url
- // that is modified is after the '#' character.
- //
- // Be careful not to consider history navigations. For instance, if the
- // history is: 'A#bar' -> 'B' -> 'A#foo'. Then an history navigation from
- // 'A#foo' to 'A#bar' is not a same-document navigation, but a
- // different-document one! The two FrameNavigationEntry doesn't share the same
- // document_sequence_number.
- //
- // When modifying this condition, please take a look at:
- // FrameLoader::shouldPerformFragmentNavigation.
- if (new_url.has_ref() && old_url.EqualsIgnoringRef(new_url) &&
- frame_entry.method() == "GET") {
- return FrameMsg_Navigate_Type::SAME_DOCUMENT;
- } else {
- return FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
- }
-}
-
-} // namespace
-
struct NavigatorImpl::NavigationMetricsData {
NavigationMetricsData(base::TimeTicks start_time,
GURL url,
@@ -146,7 +86,7 @@ void NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL(
->GetController()
->GetBrowserContext(),
url);
- if ((enabled_bindings & BINDINGS_POLICY_WEB_UI) &&
+ if ((enabled_bindings & kWebUIBindingsPolicyMask) &&
!is_allowed_in_web_ui_renderer) {
// Log the URL to help us diagnose any future failures of this CHECK.
FrameTreeNode* root_node =
@@ -255,142 +195,6 @@ void NavigatorImpl::DidFailLoadWithError(
}
}
-bool NavigatorImpl::NavigateToEntry(
- FrameTreeNode* frame_tree_node,
- const FrameNavigationEntry& frame_entry,
- const NavigationEntryImpl& entry,
- ReloadType reload_type,
- bool is_same_document_history_load,
- bool is_history_navigation_in_new_child,
- bool is_pending_entry,
- const scoped_refptr<network::ResourceRequestBody>& post_body,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
- TRACE_EVENT0("browser,navigation", "NavigatorImpl::NavigateToEntry");
-
- GURL dest_url = frame_entry.url();
- Referrer dest_referrer = frame_entry.referrer();
- if ((reload_type == ReloadType::ORIGINAL_REQUEST_URL ||
- reload_type == ReloadType::DISABLE_PREVIEWS) &&
- entry.GetOriginalRequestURL().is_valid() && !entry.GetHasPostData()) {
- // We may have been redirected when navigating to the current URL.
- // Use the URL the user originally intended to visit as signaled by the
- // ReloadType, if it's valid and if a POST wasn't involved; the latter
- // case avoids issues with sending data to the wrong page. The
- // DISABLE_PREVIEWS case is triggered from a user action to view the
- // original URL without any preview intervention treatment.
- dest_url = entry.GetOriginalRequestURL();
- dest_referrer = Referrer();
- }
-
- // Don't attempt to navigate if the virtual URL is non-empty and invalid.
- if (frame_tree_node->IsMainFrame()) {
- const GURL& virtual_url = entry.GetVirtualURL();
- if (!virtual_url.is_valid() && !virtual_url.is_empty()) {
- LOG(WARNING) << "Refusing to load for invalid virtual URL: "
- << virtual_url.possibly_invalid_spec();
- return false;
- }
- }
-
- // Don't attempt to navigate to non-empty invalid URLs.
- if (!dest_url.is_valid() && !dest_url.is_empty()) {
- LOG(WARNING) << "Refusing to load invalid URL: "
- << dest_url.possibly_invalid_spec();
- return false;
- }
-
- // 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() > url::kMaxURLChars) {
- LOG(WARNING) << "Refusing to load URL as it exceeds " << url::kMaxURLChars
- << " characters.";
- return false;
- }
-
- // This will be used to set the Navigation Timing API navigationStart
- // parameter for browser navigations in new tabs (intents, tabs opened through
- // "Open link in new tab"). We need to keep it above RFHM::Navigate() call to
- // capture the time needed for the RenderFrameHost initialization.
- base::TimeTicks navigation_start = base::TimeTicks::Now();
- base::TimeTicks tracing_navigation_start = TRACE_TIME_TICKS_NOW();
- TRACE_EVENT_INSTANT_WITH_TIMESTAMP0(
- "navigation,rail", "NavigationTiming navigationStart",
- TRACE_EVENT_SCOPE_GLOBAL, tracing_navigation_start);
-
- // Determine if Previews should be used for the navigation.
- PreviewsState previews_state = PREVIEWS_UNSPECIFIED;
- if (!frame_tree_node->IsMainFrame()) {
- // For subframes, use the state of the top-level frame.
- previews_state = frame_tree_node->frame_tree()
- ->root()
- ->current_frame_host()
- ->last_navigation_previews_state();
- } else if (reload_type == ReloadType::DISABLE_PREVIEWS) {
- // Disable LoFi when asked for it explicitly.
- previews_state = PREVIEWS_NO_TRANSFORM;
- }
-
- // Give the delegate an opportunity to adjust the previews state.
- if (delegate_)
- delegate_->AdjustPreviewsStateForNavigation(&previews_state);
-
- 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, previews_state,
- is_same_document_history_load,
- is_history_navigation_in_new_child, post_body,
- navigation_start, std::move(navigation_ui_data));
- if (frame_tree_node->IsMainFrame() && frame_tree_node->navigation_request()) {
- // For the trace below we're using the navigation handle as the async
- // trace id, |navigation_start| as the timestamp and reporting the
- // FrameTreeNode id as a parameter. For navigations where no network
- // request is made (data URLs, JavaScript URLs, etc) there is no handle
- // and so no tracing is done.
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
- "navigation", "Navigation timeToNetworkStack",
- frame_tree_node->navigation_request()->navigation_handle(),
- tracing_navigation_start, "FrameTreeNode id",
- frame_tree_node->frame_tree_node_id());
- }
-
- // Make sure no code called via RFH::Navigate clears the pending entry.
- if (is_pending_entry)
- CHECK_EQ(controller_->GetPendingEntry(), &entry);
-
- if (controller_->GetPendingEntryIndex() == -1 &&
- dest_url.SchemeIs(url::kJavaScriptScheme)) {
- // If the pending entry index is -1 (which means a new navigation rather
- // than a history one), and the user typed in a javascript: URL, don't add
- // it to the session history.
- //
- // This is a hack. What we really want is to avoid adding to the history
- // any URL that doesn't generate content, and what would be great would be
- // if we had a message from the renderer telling us that a new page was
- // not created. The same message could be used for mailto: URLs and the
- // like.
- return false;
- }
-
- // Notify observers about navigation.
- if (delegate_ && is_pending_entry)
- delegate_->DidStartNavigationToPendingEntry(dest_url, reload_type);
-
- return true;
-}
-
-bool NavigatorImpl::NavigateToPendingEntry(
- FrameTreeNode* frame_tree_node,
- const FrameNavigationEntry& frame_entry,
- ReloadType reload_type,
- bool is_same_document_history_load,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
- return NavigateToEntry(frame_tree_node, frame_entry,
- *controller_->GetPendingEntry(), reload_type,
- is_same_document_history_load, false, true, nullptr,
- std::move(navigation_ui_data));
-}
-
bool NavigatorImpl::StartHistoryNavigationInNewSubframe(
RenderFrameHostImpl* render_frame_host,
const GURL& default_url) {
@@ -545,6 +349,77 @@ void NavigatorImpl::DidNavigate(
}
}
+void NavigatorImpl::Navigate(std::unique_ptr<NavigationRequest> request,
+ ReloadType reload_type,
+ RestoreType restore_type) {
+ TRACE_EVENT0("browser,navigation", "NavigatorImpl::Navigate");
+
+ const GURL& dest_url = request->common_params().url;
+ FrameTreeNode* frame_tree_node = request->frame_tree_node();
+
+ navigation_data_.reset(new NavigationMetricsData(
+ request->common_params().navigation_start, dest_url, restore_type));
+
+ // Check if the BeforeUnload event needs to execute before assigning the
+ // NavigationRequest to the FrameTreeNode. Assigning it to the FrameTreeNode
+ // has the side effect of initializing the current RenderFrameHost, which will
+ // return that it should execute the BeforeUnload event (even though we don't
+ // need to wait for it in the case of a brand new RenderFrameHost).
+ //
+ // We don't want to dispatch a beforeunload handler if
+ // is_history_navigation_in_new_child is true. This indicates a newly created
+ // child frame which does not have a beforeunload handler.
+ bool should_dispatch_beforeunload =
+ !FrameMsg_Navigate_Type::IsSameDocument(
+ request->common_params().navigation_type) &&
+ !request->request_params().is_history_navigation_in_new_child &&
+ frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(
+ false /* check_subframes_only */);
+
+ int nav_entry_id = request->nav_entry_id();
+ bool is_pending_entry =
+ controller_->GetPendingEntry() &&
+ (nav_entry_id == controller_->GetPendingEntry()->GetUniqueID());
+ frame_tree_node->CreatedNavigationRequest(std::move(request));
+ DCHECK(frame_tree_node->navigation_request());
+
+ // Have the current renderer execute its beforeunload event if needed. If it
+ // is not needed then NavigationRequest::BeginNavigation should be directly
+ // called instead.
+ if (should_dispatch_beforeunload) {
+ frame_tree_node->navigation_request()->SetWaitingForRendererResponse();
+ frame_tree_node->current_frame_host()->DispatchBeforeUnload(
+ RenderFrameHostImpl::BeforeUnloadType::BROWSER_INITIATED_NAVIGATION,
+ reload_type != ReloadType::NONE);
+ } else {
+ frame_tree_node->navigation_request()->BeginNavigation();
+ // WARNING: The NavigationRequest might have been destroyed in
+ // BeginNavigation(). Do not use |frame_tree_node->navigation_request()|
+ // after this point without null checking it first.
+ }
+
+ if (frame_tree_node->IsMainFrame() && frame_tree_node->navigation_request()) {
+ // For the trace below we're using the navigation handle as the async
+ // trace id, |navigation_start| as the timestamp and reporting the
+ // FrameTreeNode id as a parameter. For navigations where no network
+ // request is made (data URLs, JavaScript URLs, etc) there is no handle
+ // and so no tracing is done.
+ TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
+ "navigation", "Navigation timeToNetworkStack",
+ frame_tree_node->navigation_request()->navigation_handle(),
+ frame_tree_node->navigation_request()->common_params().navigation_start,
+ "FrameTreeNode id", frame_tree_node->frame_tree_node_id());
+ }
+
+ // Make sure no code called via RFH::Navigate clears the pending entry.
+ if (is_pending_entry)
+ CHECK_EQ(nav_entry_id, controller_->GetPendingEntry()->GetUniqueID());
+
+ // Notify observers about navigation.
+ if (delegate_ && is_pending_entry)
+ delegate_->DidStartNavigationToPendingEntry(dest_url, reload_type);
+}
+
void NavigatorImpl::RequestOpenURL(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
@@ -748,7 +623,8 @@ void NavigatorImpl::OnBeginNavigation(
FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
- scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client) {
// TODO(clamy): the url sent by the renderer should be validated with
// FilterURL.
// This is a renderer-initiated navigation.
@@ -773,10 +649,12 @@ void NavigatorImpl::OnBeginNavigation(
if (ongoing_navigation_request &&
ongoing_navigation_request->browser_initiated() &&
!common_params.has_user_gesture) {
- RenderFrameHost* current_frame_host =
- frame_tree_node->render_manager()->current_frame_host();
- current_frame_host->Send(
- new FrameMsg_DroppedNavigation(current_frame_host->GetRoutingID()));
+ if (!IsPerNavigationMojoInterfaceEnabled()) {
+ RenderFrameHost* current_frame_host =
+ frame_tree_node->render_manager()->current_frame_host();
+ current_frame_host->Send(
+ new FrameMsg_DroppedNavigation(current_frame_host->GetRoutingID()));
+ }
return;
}
@@ -809,7 +687,7 @@ void NavigatorImpl::OnBeginNavigation(
frame_tree_node, pending_entry, common_params,
std::move(begin_params), controller_->GetLastCommittedEntryIndex(),
controller_->GetEntryCount(), override_user_agent,
- std::move(blob_url_loader_factory)));
+ std::move(blob_url_loader_factory), std::move(navigation_client)));
NavigationRequest* navigation_request = frame_tree_node->navigation_request();
// This frame has already run beforeunload before it sent this IPC. See if
@@ -854,6 +732,7 @@ void NavigatorImpl::RestartNavigationAsCrossDocument(
}
void NavigatorImpl::OnAbortNavigation(FrameTreeNode* frame_tree_node) {
+ DCHECK(!IsPerNavigationMojoInterfaceEnabled());
NavigationRequest* ongoing_navigation_request =
frame_tree_node->navigation_request();
if (!ongoing_navigation_request ||
@@ -940,82 +819,6 @@ void NavigatorImpl::DiscardPendingEntryIfNeeded(int expected_pending_entry_id) {
}
}
-void NavigatorImpl::RequestNavigation(
- FrameTreeNode* frame_tree_node,
- const GURL& dest_url,
- const Referrer& dest_referrer,
- const FrameNavigationEntry& frame_entry,
- const NavigationEntryImpl& entry,
- ReloadType reload_type,
- PreviewsState previews_state,
- bool is_same_document_history_load,
- bool is_history_navigation_in_new_child,
- const scoped_refptr<network::ResourceRequestBody>& post_body,
- base::TimeTicks navigation_start,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
- DCHECK(frame_tree_node);
-
- // This is not a real navigation. Send the URL to the renderer process
- // immediately for handling.
- // Note: this includes navigations to JavaScript URLs, which are considered
- // renderer-debug URLs.
- if (IsRendererDebugURL(dest_url)) {
- RenderFrameHostImpl* render_frame_host =
- frame_tree_node->current_frame_host();
- frame_tree_node->render_manager()->InitializeRenderFrameIfNecessary(
- render_frame_host);
- render_frame_host->HandleRendererDebugURL(dest_url);
- return;
- }
-
- // This value must be set here because creating a NavigationRequest might
- // change the renderer live/non-live status and change this result.
- // We don't want to dispatch a beforeunload handler if
- // is_history_navigation_in_new_child is true. This indicates a newly created
- // child frame which does not have a beforunload handler.
- FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType(
- frame_tree_node->current_url(), // old_url
- dest_url, // new_url
- reload_type, // reload_type
- entry, // entry
- frame_entry, // frame_entry
- is_same_document_history_load); // is_same_document_history_load
- bool is_same_document =
- FrameMsg_Navigate_Type::IsSameDocument(navigation_type);
- bool should_dispatch_beforeunload =
- !is_same_document && !is_history_navigation_in_new_child &&
- frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(
- false /* check_subframes_only */);
- std::unique_ptr<NavigationRequest> scoped_request =
- NavigationRequest::CreateBrowserInitiated(
- frame_tree_node, dest_url, dest_referrer, frame_entry, entry,
- navigation_type, previews_state, is_same_document_history_load,
- is_history_navigation_in_new_child, post_body, navigation_start,
- controller_, std::move(navigation_ui_data));
-
- frame_tree_node->CreatedNavigationRequest(std::move(scoped_request));
-
- NavigationRequest* navigation_request = frame_tree_node->navigation_request();
- if (!navigation_request)
- return; // Navigation was synchronously stopped.
-
- // Have the current renderer execute its beforeunload event if needed. If it
- // is not needed then NavigationRequest::BeginNavigation should be directly
- // called instead.
- if (should_dispatch_beforeunload) {
- navigation_request->SetWaitingForRendererResponse();
- frame_tree_node->current_frame_host()->DispatchBeforeUnload(
- RenderFrameHostImpl::BeforeUnloadType::BROWSER_INITIATED_NAVIGATION,
- reload_type != ReloadType::NONE);
- } else {
- navigation_request->BeginNavigation();
- // DO NOT USE |navigation_request| BEYOND THIS POINT. It might have been
- // destroyed in BeginNavigation().
- // See https://crbug.com/770157.
- return;
- }
-}
-
void NavigatorImpl::RecordNavigationMetrics(
const LoadCommittedDetails& details,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
@@ -1072,10 +875,11 @@ void NavigatorImpl::DidStartMainFrameNavigation(
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
- // know the referrer or extra headers at this point, but the referrer will
- // be set properly upon commit.
+ // is not for the error URL, create a pending entry and ensure the address bar
+ // updates accordingly. We don't know the referrer or extra headers at this
+ // point, but the referrer will be set properly upon commit. This does not
+ // set the SiteInstance for the pending entry, because it may change
+ // before the URL commits.
NavigationEntryImpl* pending_entry = controller_->GetPendingEntry();
bool has_browser_initiated_pending_entry =
pending_entry && !pending_entry->is_renderer_initiated();
@@ -1100,13 +904,10 @@ void NavigatorImpl::DidStartMainFrameNavigation(
true /* is_renderer_initiated */, std::string(),
controller_->GetBrowserContext(),
nullptr /* blob_url_loader_factory */));
- 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());
}
diff --git a/chromium/content/browser/frame_host/navigator_impl.h b/chromium/content/browser/frame_host/navigator_impl.h
index 21557ba9c0c..b97af7081e4 100644
--- a/chromium/content/browser/frame_host/navigator_impl.h
+++ b/chromium/content/browser/frame_host/navigator_impl.h
@@ -57,25 +57,12 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
std::unique_ptr<NavigationHandleImpl> navigation_handle,
bool was_within_same_document) override;
- bool NavigateToPendingEntry(
- FrameTreeNode* frame_tree_node,
- const FrameNavigationEntry& frame_entry,
- ReloadType reload_type,
- bool is_same_document_history_load,
- std::unique_ptr<NavigationUIData> navigation_ui_data) override;
- bool NavigateToEntry(
- FrameTreeNode* frame_tree_node,
- const FrameNavigationEntry& frame_entry,
- const NavigationEntryImpl& entry,
- ReloadType reload_type,
- bool is_same_document_history_load,
- bool is_history_navigation_in_new_child,
- bool is_pending_entry,
- const scoped_refptr<network::ResourceRequestBody>& post_body,
- std::unique_ptr<NavigationUIData> navigation_ui_data) override;
bool StartHistoryNavigationInNewSubframe(
RenderFrameHostImpl* render_frame_host,
const GURL& default_url) override;
+ void Navigate(std::unique_ptr<NavigationRequest> request,
+ ReloadType reload_type,
+ RestoreType restore_type) override;
void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
const GURL& url,
bool uses_post,
@@ -103,11 +90,12 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
void OnBeforeUnloadACK(FrameTreeNode* frame_tree_node,
bool proceed,
const base::TimeTicks& proceed_time) override;
- void OnBeginNavigation(FrameTreeNode* frame_tree_node,
- const CommonNavigationParams& common_params,
- mojom::BeginNavigationParamsPtr begin_params,
- scoped_refptr<network::SharedURLLoaderFactory>
- blob_url_loader_factory) override;
+ void OnBeginNavigation(
+ FrameTreeNode* frame_tree_node,
+ const CommonNavigationParams& common_params,
+ mojom::BeginNavigationParamsPtr begin_params,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client) override;
void RestartNavigationAsCrossDocument(
std::unique_ptr<NavigationRequest> navigation_request) override;
void OnAbortNavigation(FrameTreeNode* frame_tree_node) override;
@@ -127,22 +115,6 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
friend class NavigatorTestWithBrowserSideNavigation;
~NavigatorImpl() override;
- // If needed, sends a BeforeUnload IPC to the renderer to ask it to execute
- // the beforeUnload event. Otherwise, the navigation request will be started.
- void RequestNavigation(
- FrameTreeNode* frame_tree_node,
- const GURL& dest_url,
- const Referrer& dest_referrer,
- const FrameNavigationEntry& frame_entry,
- const NavigationEntryImpl& entry,
- ReloadType reload_type,
- PreviewsState previews_state,
- bool is_same_document_history_load,
- bool is_history_navigation_in_new_child,
- const scoped_refptr<network::ResourceRequestBody>& post_body,
- base::TimeTicks navigation_start,
- std::unique_ptr<NavigationUIData> navigation_ui_data);
-
void RecordNavigationMetrics(
const LoadCommittedDetails& details,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
diff --git a/chromium/content/browser/frame_host/navigator_impl_unittest.cc b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
index 3f560d4d333..78c1a044c48 100644
--- a/chromium/content/browser/frame_host/navigator_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
@@ -117,17 +117,20 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_EQ(NavigationRequest::STARTED, request->state());
ASSERT_TRUE(GetLoaderForNavigationRequest(request));
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ int64_t navigation_id = request->navigation_handle()->GetNavigationId();
// Have the current RenderFrameHost commit the navigation.
scoped_refptr<network::ResourceResponse> response(
new network::ResourceResponse);
GetLoaderForNavigationRequest(request)->CallOnResponseStarted(response,
nullptr);
- EXPECT_TRUE(main_test_rfh()->navigation_request());
EXPECT_TRUE(main_test_rfh()->is_loading());
EXPECT_FALSE(node->navigation_request());
// Commit the navigation.
+ main_test_rfh()->SimulateCommitProcessed(navigation_id,
+ true /* was_successful */);
+ EXPECT_TRUE(main_test_rfh()->navigation_request());
main_test_rfh()->SendNavigate(entry_id, true, kUrl);
EXPECT_TRUE(main_test_rfh()->is_active());
EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
@@ -178,7 +181,6 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Have the current RenderFrameHost commit the navigation
navigation->ReadyToCommit();
- EXPECT_TRUE(main_test_rfh()->navigation_request());
EXPECT_TRUE(main_test_rfh()->is_loading());
EXPECT_FALSE(node->navigation_request());
@@ -231,9 +233,6 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
if (AreAllSitesIsolatedForTesting()) {
EXPECT_EQ(navigation->GetFinalRenderFrameHost(),
GetSpeculativeRenderFrameHost(node));
- EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
- } else {
- EXPECT_TRUE(main_test_rfh()->navigation_request());
}
EXPECT_FALSE(node->navigation_request());
@@ -444,6 +443,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
// Receive the beforeUnload ACK.
main_test_rfh()->SendBeforeUnloadACK(true);
+ int64_t navigation_id = main_request->navigation_handle()->GetNavigationId();
EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
scoped_refptr<network::ResourceResponse> response(
@@ -451,9 +451,12 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
GetLoaderForNavigationRequest(main_request)
->CallOnResponseStarted(response, nullptr);
EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
- EXPECT_TRUE(speculative_rfh->navigation_request());
EXPECT_FALSE(main_test_rfh()->navigation_request());
+ speculative_rfh->SimulateCommitProcessed(navigation_id,
+ true /* was_successful */);
+ EXPECT_TRUE(speculative_rfh->navigation_request());
+
speculative_rfh->SendNavigate(entry_id, true, kUrl2);
RenderFrameHostImpl* final_rfh = main_test_rfh();
@@ -489,6 +492,8 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, RedirectCrossSite) {
EXPECT_EQ(1, GetLoaderForNavigationRequest(main_request)->redirect_count());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ int64_t navigation_id = main_request->navigation_handle()->GetNavigationId();
+
// Have the RenderFrameHost commit the navigation.
scoped_refptr<network::ResourceResponse> response(
new network::ResourceResponse);
@@ -497,9 +502,11 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, RedirectCrossSite) {
TestRenderFrameHost* final_speculative_rfh =
GetSpeculativeRenderFrameHost(node);
EXPECT_TRUE(final_speculative_rfh);
- EXPECT_TRUE(final_speculative_rfh->navigation_request());
// Commit the navigation.
+ final_speculative_rfh->SimulateCommitProcessed(navigation_id,
+ true /* was_successful */);
+ EXPECT_TRUE(final_speculative_rfh->navigation_request());
final_speculative_rfh->SendNavigate(entry_id, true, kUrl2);
RenderFrameHostImpl* final_rfh = main_test_rfh();
ASSERT_TRUE(final_rfh);
@@ -548,6 +555,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
int entry_id = RequestNavigation(node, kUrl2);
main_test_rfh()->SendBeforeUnloadACK(true);
NavigationRequest* request2 = node->navigation_request();
+ int64_t navigation_id = request2->navigation_handle()->GetNavigationId();
ASSERT_TRUE(request2);
EXPECT_EQ(kUrl2, request2->common_params().url);
EXPECT_TRUE(request2->browser_initiated());
@@ -566,10 +574,11 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
new network::ResourceResponse);
GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(response,
nullptr);
+ // Commit the navigation.
+ speculative_rfh->SimulateCommitProcessed(navigation_id,
+ true /* was_successful */);
EXPECT_TRUE(speculative_rfh->navigation_request());
EXPECT_FALSE(main_test_rfh()->navigation_request());
-
- // Commit the navigation.
speculative_rfh->SendNavigate(entry_id, true, kUrl2);
// Confirm that the commit corresponds to the new request.
@@ -633,14 +642,6 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}
- // Have the RenderFrameHost commit the navigation.
- navigation->ReadyToCommit();
- if (AreAllSitesIsolatedForTesting()) {
- EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
- } else {
- EXPECT_TRUE(main_test_rfh()->navigation_request());
- }
-
// Commit the navigation.
navigation->Commit();
@@ -700,14 +701,6 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}
- // Have the RenderFrameHost commit the navigation.
- non_user_initiated_navigation->ReadyToCommit();
- if (AreAllSitesIsolatedForTesting()) {
- EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
- } else {
- EXPECT_TRUE(main_test_rfh()->navigation_request());
- }
-
// Commit the navigation.
non_user_initiated_navigation->Commit();
EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
@@ -747,6 +740,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Now receive the beforeUnload ACK from the still ongoing navigation.
main_test_rfh()->SendBeforeUnloadACK(true);
+ int64_t navigation_id = request1->navigation_handle()->GetNavigationId();
TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
ASSERT_TRUE(speculative_rfh);
@@ -755,6 +749,8 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
new network::ResourceResponse);
GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(response,
nullptr);
+ speculative_rfh->SimulateCommitProcessed(navigation_id,
+ true /* was_successful */);
EXPECT_TRUE(speculative_rfh->navigation_request());
EXPECT_FALSE(main_test_rfh()->navigation_request());
@@ -818,14 +814,6 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Confirm that the first loader got destroyed.
EXPECT_FALSE(loader1);
- // Have the RenderFrameHost commit the navigation.
- navigation2->ReadyToCommit();
- if (AreAllSitesIsolatedForTesting()) {
- EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
- } else {
- EXPECT_TRUE(main_test_rfh()->navigation_request());
- }
-
// Commit the navigation.
navigation2->Commit();
EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
@@ -893,6 +881,8 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
speculative_rfh->GetSiteInstance()->GetSiteURL());
int32_t site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
+ int64_t navigation_id =
+ node->navigation_request()->navigation_handle()->GetNavigationId();
// Ask Navigator to commit the navigation by simulating a call to
// OnResponseStarted.
@@ -901,10 +891,12 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
GetLoaderForNavigationRequest(node->navigation_request())
->CallOnResponseStarted(response, nullptr);
EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
- EXPECT_TRUE(speculative_rfh->navigation_request());
EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
// Invoke DidCommitProvisionalLoad.
+ speculative_rfh->SimulateCommitProcessed(navigation_id,
+ true /* was_successful */);
+ EXPECT_TRUE(speculative_rfh->navigation_request());
speculative_rfh->SendNavigate(entry_id, true, kUrl);
EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
@@ -940,6 +932,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// It then redirects to yet another site.
NavigationRequest* main_request = node->navigation_request();
+ int64_t navigation_id = main_request->navigation_handle()->GetNavigationId();
ASSERT_TRUE(main_request);
const GURL kUrlRedirect("https://www.google.com/");
GetLoaderForNavigationRequest(main_request)
@@ -962,7 +955,6 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
->CallOnResponseStarted(response, nullptr);
speculative_rfh = GetSpeculativeRenderFrameHost(node);
ASSERT_TRUE(speculative_rfh);
- EXPECT_TRUE(speculative_rfh->navigation_request());
EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
EXPECT_TRUE(rfh_deleted_observer.deleted());
@@ -976,6 +968,9 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_NE(site_instance_id, redirect_site_instance_id);
// Invoke DidCommitProvisionalLoad.
+ speculative_rfh->SimulateCommitProcessed(navigation_id,
+ true /* was_successful */);
+ EXPECT_TRUE(speculative_rfh->navigation_request());
speculative_rfh->SendNavigate(entry_id, true, kUrlRedirect);
// Check that the speculative RenderFrameHost was swapped in.
@@ -1309,4 +1304,31 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, FeaturePolicyNewChild) {
ASSERT_FALSE(subframe_feature_policy->GetOriginForTest().unique());
}
+TEST_F(NavigatorTestWithBrowserSideNavigation, TwoNavigationsRacingCommit) {
+ const GURL kUrl1("http://www.chromium.org/");
+ const GURL kUrl2("http://www.chromium.org/Home");
+
+ EXPECT_EQ(0u, contents()->GetMainFrame()->navigation_requests_.size());
+
+ // Have the first navigation reach ReadyToCommit.
+ auto first_navigation =
+ NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
+ first_navigation->ReadyToCommit();
+ EXPECT_EQ(1u, contents()->GetMainFrame()->navigation_requests_.size());
+
+ // A second navigation starts and reaches ReadyToCommit.
+ auto second_navigation =
+ NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
+ second_navigation->ReadyToCommit();
+ EXPECT_EQ(2u, contents()->GetMainFrame()->navigation_requests_.size());
+
+ // The first navigation commits.
+ first_navigation->Commit();
+ EXPECT_EQ(1u, contents()->GetMainFrame()->navigation_requests_.size());
+
+ // The second navigation commits.
+ second_navigation->Commit();
+ EXPECT_EQ(0u, contents()->GetMainFrame()->navigation_requests_.size());
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/origin_policy_throttle.cc b/chromium/content/browser/frame_host/origin_policy_throttle.cc
new file mode 100644
index 00000000000..ab137232754
--- /dev/null
+++ b/chromium/content/browser/frame_host/origin_policy_throttle.cc
@@ -0,0 +1,249 @@
+// Copyright 2018 The Chromium Authors. All rights 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/origin_policy_throttle.h"
+
+#include "base/command_line.h"
+#include "base/feature_list.h"
+#include "base/no_destructor.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/network_service_instance.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "net/http/http_request_headers.h"
+#include "services/network/network_context.h"
+#include "services/network/network_service.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "url/origin.h"
+
+namespace {
+// Constants derived from the spec, https://github.com/WICG/origin-policy
+static const char* kDefaultPolicy = "1";
+static const char* kDeletePolicy = "0";
+static const char* kWellKnown = "/.well-known/origin-policy/";
+
+// Maximum policy size (implementation-defined limit in bytes).
+// (Limit copied from network::SimpleURLLoader::kMaxBoundedStringDownloadSize.)
+static const size_t kMaxPolicySize = 1024 * 1024;
+} // namespace
+
+namespace content {
+
+// static
+bool OriginPolicyThrottle::ShouldRequestOriginPolicy(
+ const GURL& url,
+ std::string* request_version) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (!base::FeatureList::IsEnabled(features::kOriginPolicy))
+ return false;
+
+ if (!url.SchemeIs(url::kHttpsScheme))
+ return false;
+
+ if (request_version) {
+ const KnownVersionMap& versions = GetKnownVersions();
+ const auto iter = versions.find(url::Origin::Create(url));
+ *request_version =
+ iter == versions.end() ? std::string(kDefaultPolicy) : iter->second;
+ }
+ return true;
+}
+
+// static
+std::unique_ptr<NavigationThrottle>
+OriginPolicyThrottle::MaybeCreateThrottleFor(NavigationHandle* handle) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK(handle);
+
+ // We use presence of the origin policy request header to determine
+ // whether we should create the throttle.
+ if (!handle->GetRequestHeaders().HasHeader(
+ net::HttpRequestHeaders::kSecOriginPolicy))
+ return nullptr;
+
+ DCHECK(base::FeatureList::IsEnabled(features::kOriginPolicy));
+ return base::WrapUnique(new OriginPolicyThrottle(handle));
+}
+
+OriginPolicyThrottle::~OriginPolicyThrottle() {}
+
+NavigationThrottle::ThrottleCheckResult
+OriginPolicyThrottle::WillStartRequest() {
+ // TODO(vogelheim): It might be faster in the common case to optimistically
+ // fetch the policy indicated in the request already here. This would
+ // be faster if the last known version is the current version, but
+ // slower (and wasteful of bandwidth) if the server sends us a new
+ // version. It's unclear how much the upside is, though.
+ return NavigationThrottle::PROCEED;
+}
+
+NavigationThrottle::ThrottleCheckResult
+OriginPolicyThrottle::WillProcessResponse() {
+ DCHECK(navigation_handle());
+
+ // Per spec, Origin Policies are only fetched for https:-requests. So we
+ // should always have HTTP headers at this point.
+ // However, some unit tests generate responses without headers, so we still
+ // need to check.
+ if (!navigation_handle()->GetResponseHeaders())
+ return NavigationThrottle::PROCEED;
+
+ // This determines whether and which policy version applies and fetches it.
+ //
+ // Inputs are the kSecOriginPolicy HTTP header, and the version
+ // we've last seen from this particular origin.
+ //
+ // - header with kDeletePolicy received: No policy applies, and delete the
+ // last-known policy for this origin.
+ // - header received: Use header version and update last-known policy.
+ // - no header received, last-known version exists: Use last-known version
+ // - no header, no last-known version: No policy applies.
+
+ std::string response_version;
+ bool header_found =
+ navigation_handle()->GetResponseHeaders()->GetNormalizedHeader(
+ net::HttpRequestHeaders::kSecOriginPolicy, &response_version);
+
+ url::Origin origin = GetRequestOrigin();
+ DCHECK(!origin.Serialize().empty());
+ DCHECK(!origin.unique());
+ KnownVersionMap& versions = GetKnownVersions();
+ KnownVersionMap::iterator iter = versions.find(origin);
+
+ // Process policy deletion first!
+ if (header_found && response_version == kDeletePolicy) {
+ if (iter != versions.end())
+ versions.erase(iter);
+ return NavigationThrottle::PROCEED;
+ }
+
+ // No policy applies to this request?
+ if (!header_found && iter == versions.end()) {
+ return NavigationThrottle::PROCEED;
+ }
+
+ if (!header_found)
+ response_version = iter->second;
+ else if (iter == versions.end())
+ versions.insert(std::make_pair(origin, response_version));
+ else
+ iter->second = response_version;
+
+ GURL policy = GURL(origin.Serialize() + kWellKnown + response_version);
+ FetchCallback done =
+ base::BindOnce(&OriginPolicyThrottle::OnTheGloriousPolicyHasArrived,
+ base::Unretained(this));
+ FetchPolicy(policy, std::move(done));
+ return NavigationThrottle::DEFER;
+}
+
+const char* OriginPolicyThrottle::GetNameForLogging() {
+ return "OriginPolicyThrottle";
+}
+
+// static
+OriginPolicyThrottle::KnownVersionMap&
+OriginPolicyThrottle::GetKnownVersionsForTesting() {
+ return GetKnownVersions();
+}
+
+OriginPolicyThrottle::OriginPolicyThrottle(NavigationHandle* handle)
+ : NavigationThrottle(handle) {}
+
+OriginPolicyThrottle::KnownVersionMap&
+OriginPolicyThrottle::GetKnownVersions() {
+ static base::NoDestructor<KnownVersionMap> map_instance;
+ return *map_instance;
+}
+
+const url::Origin OriginPolicyThrottle::GetRequestOrigin() {
+ return url::Origin::Create(navigation_handle()->GetURL());
+}
+
+void OriginPolicyThrottle::FetchPolicy(const GURL& url, FetchCallback done) {
+ // Obtain a network context from the network service.
+ network::mojom::NetworkContextParamsPtr context_params =
+ network::mojom::NetworkContextParams::New();
+ content::GetNetworkService()->CreateNetworkContext(
+ mojo::MakeRequest(&network_context_ptr_), std::move(context_params));
+
+ // Create URLLoaderFactory
+ network::mojom::URLLoaderFactoryParamsPtr url_loader_factory_params =
+ network::mojom::URLLoaderFactoryParams::New();
+ url_loader_factory_params->process_id = network::mojom::kBrowserProcessId;
+ url_loader_factory_params->is_corb_enabled = false;
+ url_loader_factory_params->disable_web_security =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity);
+ network_context_ptr_->CreateURLLoaderFactory(
+ mojo::MakeRequest(&url_loader_factory_),
+ std::move(url_loader_factory_params));
+
+ // Create the traffic annotation
+ net::NetworkTrafficAnnotationTag traffic_annotation =
+ net::DefineNetworkTrafficAnnotation("origin_policy_loader", R"(
+ semantics {
+ sender: "Origin Policy URL Loader Throttle"
+ description:
+ "Fetches the Origin Policy with a given version from an origin."
+ trigger:
+ "In case the Origin Policy with a given version does not "
+ "exist in the cache, it is fetched from the origin at a "
+ "well-known location."
+ data:
+ "None, the URL itself contains the origin and Origin Policy "
+ "version."
+ destination: OTHER
+ }
+ policy {
+ cookies_allowed: NO
+ setting: "This feature cannot be disabled by settings. Server "
+ "opt-in or out of this mechanism."
+ policy_exception_justification:
+ "Not implemented, considered not useful."})");
+
+ // Create the SimpleURLLoader for the policy.
+ std::unique_ptr<network::ResourceRequest> policy_request =
+ std::make_unique<network::ResourceRequest>();
+ policy_request->url = url;
+ policy_request->fetch_redirect_mode =
+ network::mojom::FetchRedirectMode::kError;
+ url_loader_ = network::SimpleURLLoader::Create(std::move(policy_request),
+ traffic_annotation);
+ url_loader_->SetAllowHttpErrorResults(false);
+
+ // Start the download, and pass the callback for when we're finished.
+ url_loader_->DownloadToString(url_loader_factory_.get(), std::move(done),
+ kMaxPolicySize);
+}
+
+void OriginPolicyThrottle::InjectPolicyForTesting(
+ const std::string& policy_content) {
+ OnTheGloriousPolicyHasArrived(std::make_unique<std::string>(policy_content));
+}
+
+void OriginPolicyThrottle::OnTheGloriousPolicyHasArrived(
+ std::unique_ptr<std::string> policy_content) {
+ // Release resources associated with the loading.
+ url_loader_.reset();
+ url_loader_factory_.reset();
+ network_context_ptr_.reset();
+
+ // Fail hard if the policy could not be loaded.
+ if (!policy_content) {
+ CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
+ return;
+ }
+
+ // TODO(vogelheim): Determine whether we need to parse or sanity check
+ // the policy content at this point.
+
+ static_cast<NavigationHandleImpl*>(navigation_handle())
+ ->set_origin_policy(*policy_content);
+ Resume();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/origin_policy_throttle.h b/chromium/content/browser/frame_host/origin_policy_throttle.h
new file mode 100644
index 00000000000..ac200046c8c
--- /dev/null
+++ b/chromium/content/browser/frame_host/origin_policy_throttle.h
@@ -0,0 +1,86 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_FRAME_HOST_ORIGIN_POLICY_THROTTLE_H_
+#define CONTENT_BROWSER_FRAME_HOST_ORIGIN_POLICY_THROTTLE_H_
+
+#include <map>
+#include <string>
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "content/public/browser/navigation_throttle.h"
+#include "services/network/public/mojom/network_service.mojom.h"
+
+class GURL;
+
+namespace url {
+class Origin;
+}
+namespace network {
+class SimpleURLLoader;
+} // namespace network
+
+namespace content {
+class NavigationHandle;
+
+// The OriginPolicyThrottle is responsible for deciding whether an origin
+// policy should be fetched, and doing so when that is positive.
+//
+// The intended use is that the navigation request will
+// - call OriginPolicyThrottle::ShouldRequestOriginPolicy to determine whether
+// a policy should be requested and which version, and should add the
+// appropriate SecOriginPolicy: header.
+// - call OriginPolicyThrottle::MaybeCreateThrottleFor a given navigation.
+// This will use presence of the header to decide whether to create a
+// throttle or not.
+class CONTENT_EXPORT OriginPolicyThrottle : public NavigationThrottle {
+ public:
+ // Determine whether to request a policy (or advertise origin policy
+ // support) and which version.
+ // Returns whether the policy header should be sent. It it returns true,
+ // |version| will contain the policy version to use.
+ static bool ShouldRequestOriginPolicy(const GURL& url, std::string* version);
+
+ // Create a throttle (if the request contains the appropriate header.
+ // The throttle will handle fetching of the policy and updating the
+ // navigation request with the result.
+ static std::unique_ptr<NavigationThrottle> MaybeCreateThrottleFor(
+ NavigationHandle* handle);
+
+ ~OriginPolicyThrottle() override;
+
+ ThrottleCheckResult WillStartRequest() override;
+ ThrottleCheckResult WillProcessResponse() override;
+ const char* GetNameForLogging() override;
+
+ using KnownVersionMap = std::map<url::Origin, std::string>;
+ static KnownVersionMap& GetKnownVersionsForTesting();
+
+ void InjectPolicyForTesting(const std::string& policy_content);
+
+ private:
+ using FetchCallback = base::OnceCallback<void(std::unique_ptr<std::string>)>;
+
+ explicit OriginPolicyThrottle(NavigationHandle* handle);
+
+ static KnownVersionMap& GetKnownVersions();
+
+ const url::Origin GetRequestOrigin();
+ void FetchPolicy(const GURL& url, FetchCallback done);
+ void OnTheGloriousPolicyHasArrived(
+ std::unique_ptr<std::string> policy_content);
+
+ // We may need the SimpleURLLoader to download the policy.
+ // The network context and url loader must be kept alive while the load is
+ // ongoing.
+ network::mojom::NetworkContextPtr network_context_ptr_;
+ network::mojom::URLLoaderFactoryPtr url_loader_factory_;
+ std::unique_ptr<network::SimpleURLLoader> url_loader_;
+
+ DISALLOW_COPY_AND_ASSIGN(OriginPolicyThrottle);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_ORIGIN_POLICY_THROTTLE_H_
diff --git a/chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc b/chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc
new file mode 100644
index 00000000000..859a318dfc7
--- /dev/null
+++ b/chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc
@@ -0,0 +1,155 @@
+// Copyright 2018 The Chromium Authors. All rights 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/origin_policy_throttle.h"
+
+#include "base/feature_list.h"
+#include "base/macros.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/common/content_features.h"
+#include "content/public/test/test_renderer_host.h"
+#include "net/http/http_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class OriginPolicyThrottleTest : public RenderViewHostTestHarness,
+ public testing::WithParamInterface<bool> {
+ public:
+ void SetUp() override {
+ // Some tests below should be run with the feature en- and disabled, since
+ // they test the feature functionality when enabled and feature
+ // non-funcionality (that is, that the feature is inert) when disabled.
+ // Hence, we run this test in both variants.
+ features_.InitWithFeatureState(features::kOriginPolicy, GetParam());
+
+ RenderViewHostTestHarness::SetUp();
+ OriginPolicyThrottle::GetKnownVersionsForTesting().clear();
+ }
+ void TearDown() override {
+ OriginPolicyThrottle::GetKnownVersionsForTesting().clear();
+ nav_handle_.reset();
+ RenderViewHostTestHarness::TearDown();
+ }
+ bool enabled() {
+ return base::FeatureList::IsEnabled(features::kOriginPolicy);
+ }
+
+ void CreateHandleFor(const GURL& url) {
+ net::HttpRequestHeaders headers;
+ if (OriginPolicyThrottle::ShouldRequestOriginPolicy(url, nullptr))
+ headers.SetHeader(net::HttpRequestHeaders::kSecOriginPolicy, "1");
+
+ // Except for url and headers (which are determined by the test case)
+ // all parameters below are cargo-culted from
+ // NavigationHandleImplTest::CreateNavigationHandle.
+ nav_handle_ = NavigationHandleImpl::Create(
+ url, // url, as requested by caller
+ std::vector<GURL>(), // redirect chain
+ static_cast<WebContentsImpl*>(web_contents())
+ ->GetFrameTree()
+ ->root(), // render_tree_node
+ true, // is_renderer_initialized
+ false, // is_same_document
+ base::TimeTicks::Now(), // navigation_start
+ 0, // pending_nav_entry_id
+ false, // started_from_context_menu
+ CSPDisposition::CHECK, // should_check_main_world_csp
+ false, // is_form_submission
+ nullptr, // navigation_ui_data
+ "GET", // HTTP method
+ headers); // headers, as created above
+ }
+
+ protected:
+ std::unique_ptr<NavigationHandleImpl> nav_handle_;
+ base::test::ScopedFeatureList features_;
+};
+
+INSTANTIATE_TEST_CASE_P(OriginPolicyThrottleTests,
+ OriginPolicyThrottleTest,
+ testing::Bool());
+
+TEST_P(OriginPolicyThrottleTest, ShouldRequestOriginPolicy) {
+ struct {
+ const char* url;
+ bool expect;
+ } test_cases[] = {
+ {"https://example.org/bla", true},
+ {"http://example.org/bla", false},
+ {"file:///etc/passwd", false},
+ };
+
+ for (const auto& test_case : test_cases) {
+ SCOPED_TRACE(testing::Message() << "URL: " << test_case.url);
+ EXPECT_EQ(enabled() && test_case.expect,
+ OriginPolicyThrottle::ShouldRequestOriginPolicy(
+ GURL(test_case.url), nullptr));
+ }
+}
+
+TEST_P(OriginPolicyThrottleTest, ShouldRequestLastKnownVersion) {
+ if (!enabled())
+ return;
+
+ GURL url("https://example.org/bla");
+ EXPECT_TRUE(OriginPolicyThrottle::ShouldRequestOriginPolicy(url, nullptr));
+
+ std::string version;
+
+ OriginPolicyThrottle::ShouldRequestOriginPolicy(url, &version);
+ EXPECT_EQ(version, "1");
+
+ OriginPolicyThrottle::GetKnownVersionsForTesting()[url::Origin::Create(url)] =
+ "abcd";
+ OriginPolicyThrottle::ShouldRequestOriginPolicy(url, &version);
+ EXPECT_EQ(version, "abcd");
+}
+
+TEST_P(OriginPolicyThrottleTest, MaybeCreateThrottleFor) {
+ CreateHandleFor(GURL("https://example.org/bla"));
+ EXPECT_EQ(enabled(),
+ !!OriginPolicyThrottle::MaybeCreateThrottleFor(nav_handle_.get()));
+
+ CreateHandleFor(GURL("http://insecure.org/bla"));
+ EXPECT_FALSE(
+ !!OriginPolicyThrottle::MaybeCreateThrottleFor(nav_handle_.get()));
+}
+
+TEST_P(OriginPolicyThrottleTest, RunRequestEndToEnd) {
+ if (!enabled())
+ return;
+
+ // Create a handle and start the request.
+ CreateHandleFor(GURL("https://example.org/bla"));
+ EXPECT_EQ(NavigationThrottle::PROCEED,
+ nav_handle_->CallWillStartRequestForTesting().action());
+
+ // Fake a response with a policy header. Check whether the navigation
+ // is deferred.
+ const char* headers = "HTTP/1.1 200 OK\nSec-Origin-Policy: policy-1\n\n";
+ EXPECT_EQ(NavigationThrottle::DEFER,
+ nav_handle_
+ ->CallWillProcessResponseForTesting(
+ main_rfh(),
+ net::HttpUtil::AssembleRawHeaders(headers, strlen(headers)))
+ .action());
+ EXPECT_EQ(NavigationHandleImpl::DEFERRING_RESPONSE,
+ nav_handle_->state_for_testing());
+
+ // For the purpose of this unit test we don't care about policy content,
+ // only that it's non-empty. We check whether the throttle will pass it on.
+ const char* policy = "{}";
+ static_cast<OriginPolicyThrottle*>(
+ nav_handle_->GetDeferringThrottleForTesting())
+ ->InjectPolicyForTesting(policy);
+
+ // At the end of the navigation, the navigation handle should have a copy
+ // of the origin policy.
+ EXPECT_EQ(policy, nav_handle_->origin_policy());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_android.cc b/chromium/content/browser/frame_host/render_frame_host_android.cc
index 8ef72144652..63de23c20a9 100644
--- a/chromium/content/browser/frame_host/render_frame_host_android.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_android.cc
@@ -4,6 +4,8 @@
#include "content/browser/frame_host/render_frame_host_android.h"
+#include <utility>
+
#include "base/android/callback_android.h"
#include "base/android/jni_string.h"
#include "base/android/unguessable_token_android.h"
@@ -28,12 +30,12 @@ void OnGetCanonicalUrlForSharing(
const base::android::JavaRef<jobject>& jcallback,
const base::Optional<GURL>& url) {
if (!url) {
- base::android::RunCallbackAndroid(jcallback, ScopedJavaLocalRef<jstring>());
+ base::android::RunObjectCallbackAndroid(jcallback,
+ ScopedJavaLocalRef<jstring>());
return;
}
- base::android::RunCallbackAndroid(
- jcallback, ConvertUTF8ToJavaString(AttachCurrentThread(), url->spec()));
+ base::android::RunStringCallbackAndroid(jcallback, url->spec());
}
} // namespace
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 390bcf09995..26b8eec2bb7 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
@@ -43,11 +43,11 @@ InterstitialPage* RenderFrameHostDelegate::GetAsInterstitialPage() {
void RenderFrameHostDelegate::RequestMediaAccessPermission(
const MediaStreamRequest& request,
- const MediaResponseCallback& callback) {
+ MediaResponseCallback callback) {
LOG(ERROR) << "RenderFrameHostDelegate::RequestMediaAccessPermission: "
<< "Not supported.";
- callback.Run(MediaStreamDevices(), MEDIA_DEVICE_NOT_SUPPORTED,
- std::unique_ptr<MediaStreamUI>());
+ std::move(callback).Run(MediaStreamDevices(), MEDIA_DEVICE_NOT_SUPPORTED,
+ std::unique_ptr<MediaStreamUI>());
}
bool RenderFrameHostDelegate::CheckMediaAccessPermission(
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 cd4a295dfa3..7919ac1e579 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.h
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -177,9 +177,8 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// The render frame has requested access to media devices listed in
// |request|, and the client should grant or deny that permission by
// calling |callback|.
- virtual void RequestMediaAccessPermission(
- const MediaStreamRequest& request,
- const MediaResponseCallback& callback);
+ virtual void RequestMediaAccessPermission(const MediaStreamRequest& request,
+ MediaResponseCallback callback);
// Checks if we have permission to access the microphone or camera. Note that
// this does not query the user. |type| must be MEDIA_DEVICE_AUDIO_CAPTURE
@@ -200,7 +199,7 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// from a render frame, when the accessibility mode has the
// ui::AXMode::kWebContents flag set.
virtual void AccessibilityEventReceived(
- const std::vector<AXEventNotificationDetails>& details) {}
+ const AXEventNotificationDetails& details) {}
virtual void AccessibilityLocationChangesReceived(
const std::vector<AXLocationChangeNotificationDetails>& details) {}
@@ -233,6 +232,10 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// browser fullscreen.
virtual void ExitFullscreenMode(bool will_cause_resize) {}
+ // Notification that this frame has changed fullscreen state.
+ virtual void FullscreenStateChanged(RenderFrameHost* rfh,
+ bool is_fullscreen) {}
+
// Let the delegate decide whether postMessage should be delivered to
// |target_rfh| from a source frame in the given SiteInstance. This defaults
// to false and overrides the RenderFrameHost's decision if true.
diff --git a/chromium/content/browser/frame_host/render_frame_host_feature_policy_unittest.cc b/chromium/content/browser/frame_host/render_frame_host_feature_policy_unittest.cc
index 687bd02154e..b730cee3bcb 100644
--- a/chromium/content/browser/frame_host/render_frame_host_feature_policy_unittest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_feature_policy_unittest.cc
@@ -30,7 +30,7 @@ class RenderFrameHostFeaturePolicyTest
static constexpr const char* kOrigin4 = "https://test.com";
static const blink::mojom::FeaturePolicyFeature kDefaultEnabledFeature =
- blink::mojom::FeaturePolicyFeature::kDocumentStreamInsertion;
+ blink::mojom::FeaturePolicyFeature::kDocumentWrite;
static const blink::mojom::FeaturePolicyFeature kDefaultSelfFeature =
blink::mojom::FeaturePolicyFeature::kGeolocation;
@@ -113,7 +113,7 @@ TEST_F(RenderFrameHostFeaturePolicyTest, HeaderPolicy) {
EXPECT_TRUE(parent->IsFeatureEnabled(kDefaultSelfFeature));
EXPECT_TRUE(child->IsFeatureEnabled(kDefaultSelfFeature));
- // Set an empty whitelist in the child to test that the policies combine
+ // Set an empty allowlist in the child to test that the policies combine
// correctly.
RefreshPageAndSetHeaderPolicy(&child, kDefaultSelfFeature,
std::vector<std::string>());
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 cd755cbc3f2..8e5af3e3b9c 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -22,6 +22,7 @@
#include "base/metrics/user_metrics.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/kill.h"
+#include "base/stl_util.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -64,6 +65,7 @@
#include "content/browser/media/media_interface_proxy.h"
#include "content/browser/media/session/media_session_service_impl.h"
#include "content/browser/payments/payment_app_context_impl.h"
+#include "content/browser/permissions/permission_controller_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"
@@ -116,14 +118,15 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/permission_manager.h"
#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/stream_handle.h"
#include "content/public/browser/webvr_service_provider.h"
#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"
@@ -134,6 +137,7 @@
#include "content/public/common/service_names.mojom.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
+#include "device/gamepad/gamepad_monitor.h"
#include "device/vr/public/mojom/vr_service.mojom.h"
#include "media/audio/audio_manager.h"
#include "media/base/media_switches.h"
@@ -142,6 +146,7 @@
#include "media/mojo/interfaces/remoting.mojom.h"
#include "media/mojo/services/media_interface_provider.h"
#include "media/mojo/services/media_metrics_provider.h"
+#include "media/mojo/services/video_decode_perf_history.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -153,12 +158,12 @@
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/network_service.mojom.h"
-#include "services/network/restricted_cookie_manager.h"
#include "services/resource_coordinator/public/cpp/frame_resource_coordinator.h"
#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "storage/browser/blob/blob_storage_context.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
@@ -390,17 +395,16 @@ base::Histogram::Sample HashInterfaceNameToHistogramSample(
static_cast<int32_t>(base::HashMetricName(name) & 0x7fffffffull));
}
-} // namespace
-
-RenderFrameHostImpl::PendingNavigation::PendingNavigation(
- const CommonNavigationParams& common_params,
- mojom::BeginNavigationParamsPtr begin_params,
- scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory)
- : common_params(common_params),
- begin_params(std::move(begin_params)),
- blob_url_loader_factory(std::move(blob_url_loader_factory)) {}
+// Set crash keys that will help understand the circumstances of a renderer
+// kill. Note that the commit URL is already reported in a crash key, and
+// additional keys are logged in RenderProcessHostImpl::ShutdownForBadMessage.
+void LogRendererKillCrashKeys(const GURL& site_url) {
+ static auto* site_url_key = base::debug::AllocateCrashKeyString(
+ "current_site_url", base::debug::CrashKeySize::Size64);
+ base::debug::SetCrashKeyString(site_url_key, site_url.spec());
+}
-RenderFrameHostImpl::PendingNavigation::~PendingNavigation() = default;
+} // namespace
class RenderFrameHostImpl::DroppedInterfaceRequestLogger
: public service_manager::mojom::InterfaceProvider {
@@ -436,6 +440,29 @@ class RenderFrameHostImpl::DroppedInterfaceRequestLogger
DISALLOW_COPY_AND_ASSIGN(DroppedInterfaceRequestLogger);
};
+struct PendingNavigation {
+ CommonNavigationParams common_params;
+ mojom::BeginNavigationParamsPtr begin_navigation_params;
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
+ mojom::NavigationClientAssociatedPtrInfo navigation_client;
+
+ PendingNavigation(
+ CommonNavigationParams common_params,
+ mojom::BeginNavigationParamsPtr begin_navigation_params,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client);
+};
+
+PendingNavigation::PendingNavigation(
+ CommonNavigationParams common_params,
+ mojom::BeginNavigationParamsPtr begin_navigation_params,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client)
+ : common_params(common_params),
+ begin_navigation_params(std::move(begin_navigation_params)),
+ blob_url_loader_factory(std::move(blob_url_loader_factory)),
+ navigation_client(std::move(navigation_client)) {}
+
// static
RenderFrameHost* RenderFrameHost::FromID(int render_process_id,
int render_frame_id) {
@@ -544,9 +571,8 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
weak_ptr_factory_(this) {
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));
+ g_routing_id_frame_map.Get().emplace(
+ RenderFrameHostID(GetProcess()->GetID(), routing_id_), this);
site_instance_->AddObserver(this);
GetSiteInstance()->IncrementActiveFrameCount();
@@ -681,8 +707,8 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
// the dtor has run. (It may also be null in tests.)
swapout_event_monitor_timeout_.reset();
- for (const auto& iter : visual_state_callbacks_)
- iter.second.Run(false);
+ for (auto& iter : visual_state_callbacks_)
+ std::move(iter.second).Run(false);
if (render_widget_host_ &&
render_widget_host_->owned_by_render_frame_host()) {
@@ -725,6 +751,14 @@ const base::UnguessableToken& RenderFrameHostImpl::GetOverlayRoutingToken() {
return *overlay_routing_token_;
}
+void RenderFrameHostImpl::DidCommitProvisionalLoadForTesting(
+ std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
+ service_manager::mojom::InterfaceProviderRequest
+ interface_provider_request) {
+ DidCommitProvisionalLoad(std::move(params),
+ std::move(interface_provider_request));
+}
+
SiteInstanceImpl* RenderFrameHostImpl::GetSiteInstance() {
return site_instance_.get();
}
@@ -774,6 +808,56 @@ void RenderFrameHostImpl::GetCanonicalUrlForSharing(
}
}
+blink::mojom::PauseSubresourceLoadingHandlePtr
+RenderFrameHostImpl::PauseSubresourceLoading() {
+ DCHECK(frame_);
+ blink::mojom::PauseSubresourceLoadingHandlePtr
+ pause_subresource_loading_handle;
+ GetRemoteInterfaces()->GetInterface(&pause_subresource_loading_handle);
+
+ return pause_subresource_loading_handle;
+}
+
+void RenderFrameHostImpl::ExecuteMediaPlayerActionAtLocation(
+ const gfx::Point& location,
+ const blink::WebMediaPlayerAction& action) {
+ gfx::PointF point_in_view = GetView()->TransformRootPointToViewCoordSpace(
+ gfx::PointF(location.x(), location.y()));
+ Send(new FrameMsg_MediaPlayerActionAt(routing_id_, point_in_view, action));
+}
+
+void RenderFrameHostImpl::CreateNetworkServiceDefaultFactory(
+ network::mojom::URLLoaderFactoryRequest default_factory_request) {
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = GetProcess()->GetID();
+ params->disable_web_security =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity);
+ SiteIsolationPolicy::PopulateURLLoaderFactoryParamsPtrForCORB(params.get());
+
+ auto* context = GetSiteInstance()->GetBrowserContext();
+ GetContentClient()->browser()->WillCreateURLLoaderFactory(
+ context, this, false /* is_navigation */, &default_factory_request);
+ // Keep DevTools proxy lasy, i.e. closest to the network.
+ RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
+ this, false /* is_navigation */, false /* is_download */,
+ &default_factory_request);
+ StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetStoragePartition(context, GetSiteInstance()));
+ if (g_create_network_factory_callback_for_test.Get().is_null()) {
+ storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
+ std::move(default_factory_request), std::move(params));
+ } else {
+ network::mojom::URLLoaderFactoryPtr original_factory;
+ storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
+ mojo::MakeRequest(&original_factory), std::move(params));
+ g_create_network_factory_callback_for_test.Get().Run(
+ std::move(default_factory_request), GetProcess()->GetID(),
+ original_factory.PassInterface());
+ }
+}
+
gfx::NativeView RenderFrameHostImpl::GetNativeView() {
RenderWidgetHostView* view = render_view_host_->GetWidget()->GetView();
if (!view)
@@ -802,7 +886,7 @@ void RenderFrameHostImpl::ExecuteJavaScript(
Send(new FrameMsg_JavaScriptExecuteRequest(routing_id_,
javascript,
key, true));
- javascript_callbacks_.insert(std::make_pair(key, callback));
+ javascript_callbacks_.emplace(key, callback);
}
void RenderFrameHostImpl::ExecuteJavaScriptForTests(
@@ -818,7 +902,7 @@ void RenderFrameHostImpl::ExecuteJavaScriptForTests(
int key = g_next_javascript_callback_id++;
Send(new FrameMsg_JavaScriptExecuteRequestForTests(routing_id_, javascript,
key, true, false));
- javascript_callbacks_.insert(std::make_pair(key, callback));
+ javascript_callbacks_.emplace(key, callback);
}
@@ -845,7 +929,7 @@ void RenderFrameHostImpl::ExecuteJavaScriptInIsolatedWorld(
if (!callback.is_null()) {
request_reply = true;
key = g_next_javascript_callback_id++;
- javascript_callbacks_.insert(std::make_pair(key, callback));
+ javascript_callbacks_.emplace(key, callback);
}
Send(new FrameMsg_JavaScriptExecuteRequestInIsolatedWorld(
@@ -1007,7 +1091,7 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnForwardResourceTimingToParent)
IPC_MESSAGE_HANDLER(FrameHostMsg_TextSurroundingSelectionResponse,
OnTextSurroundingSelectionResponse)
- IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Events, OnAccessibilityEvents)
+ IPC_MESSAGE_HANDLER(AccessibilityHostMsg_EventBundle, OnAccessibilityEvents)
IPC_MESSAGE_HANDLER(AccessibilityHostMsg_LocationChanges,
OnAccessibilityLocationChanges)
IPC_MESSAGE_HANDLER(AccessibilityHostMsg_FindInPageResult,
@@ -1028,8 +1112,8 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnSerializeAsMHTMLResponse)
IPC_MESSAGE_HANDLER(FrameHostMsg_SelectionChanged, OnSelectionChanged)
IPC_MESSAGE_HANDLER(FrameHostMsg_FocusedNodeChanged, OnFocusedNodeChanged)
- IPC_MESSAGE_HANDLER(FrameHostMsg_SetHasReceivedUserGesture,
- OnSetHasReceivedUserGesture)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateUserActivationState,
+ OnUpdateUserActivationState)
IPC_MESSAGE_HANDLER(FrameHostMsg_SetHasReceivedUserGestureBeforeNavigation,
OnSetHasReceivedUserGestureBeforeNavigation)
IPC_MESSAGE_HANDLER(FrameHostMsg_ScrollRectToVisibleInParentFrame,
@@ -1210,8 +1294,7 @@ bool RenderFrameHostImpl::SchemeShouldBypassCSP(
// TODO(arthursonzogni): url::GetBypassingCSPScheme() is used instead of the
// blink::SchemeRegistry. It contains 1) but not 2).
const auto& bypassing_schemes = url::GetCSPBypassingSchemes();
- return std::find(bypassing_schemes.begin(), bypassing_schemes.end(),
- scheme) != bypassing_schemes.end();
+ return base::ContainsValue(bypassing_schemes, scheme);
}
mojom::FrameInputHandler* RenderFrameHostImpl::GetFrameInputHandler() {
@@ -1232,7 +1315,7 @@ bool RenderFrameHostImpl::CreateRenderFrame(int proxy_routing_id,
if (!GetProcess()->Init())
return false;
- DCHECK(GetProcess()->HasConnection());
+ DCHECK(GetProcess()->IsInitializedAndNotDead());
service_manager::mojom::InterfaceProviderPtr interface_provider;
BindInterfaceProviderRequest(mojo::MakeRequest(&interface_provider));
@@ -1364,8 +1447,9 @@ void RenderFrameHostImpl::Init() {
if (pending_navigate_) {
frame_tree_node()->navigator()->OnBeginNavigation(
frame_tree_node(), pending_navigate_->common_params,
- std::move(pending_navigate_->begin_params),
- std::move(pending_navigate_->blob_url_loader_factory));
+ std::move(pending_navigate_->begin_navigation_params),
+ std::move(pending_navigate_->blob_url_loader_factory),
+ std::move(pending_navigate_->navigation_client));
pending_navigate_.reset();
}
}
@@ -1551,20 +1635,7 @@ void RenderFrameHostImpl::CancelInitialHistoryLoad() {
NOTIMPLEMENTED();
}
-void RenderFrameHostImpl::OnDocumentOnLoadCompleted(
- FrameMsg_UILoadMetricsReportType::Value report_type,
- base::TimeTicks ui_timestamp) {
- if (report_type == FrameMsg_UILoadMetricsReportType::REPORT_LINK) {
- UMA_HISTOGRAM_CUSTOM_TIMES("Navigation.UI_OnLoadComplete.Link",
- base::TimeTicks::Now() - ui_timestamp,
- base::TimeDelta::FromMilliseconds(10),
- base::TimeDelta::FromMinutes(10), 100);
- } else if (report_type == FrameMsg_UILoadMetricsReportType::REPORT_INTENT) {
- UMA_HISTOGRAM_CUSTOM_TIMES("Navigation.UI_OnLoadComplete.Intent",
- base::TimeTicks::Now() - ui_timestamp,
- base::TimeDelta::FromMilliseconds(10),
- base::TimeDelta::FromMinutes(10), 100);
- }
+void RenderFrameHostImpl::OnDocumentOnLoadCompleted() {
// This message is only sent for top-level frames. TODO(avi): when frame tree
// mirroring works correctly, add a check here to enforce it.
delegate_->DocumentOnLoadCompleted(this);
@@ -1806,6 +1877,7 @@ NavigationHandleImpl* RenderFrameHostImpl::GetNavigationHandle() {
void RenderFrameHostImpl::ResetNavigationRequests() {
navigation_request_.reset();
same_document_navigation_request_.reset();
+ navigation_requests_.clear();
}
void RenderFrameHostImpl::SetNavigationRequest(
@@ -1816,7 +1888,8 @@ void RenderFrameHostImpl::SetNavigationRequest(
same_document_navigation_request_ = std::move(navigation_request);
return;
}
- navigation_request_ = std::move(navigation_request);
+ navigation_requests_[navigation_request->navigation_handle()
+ ->GetNavigationId()] = std::move(navigation_request);
}
void RenderFrameHostImpl::SwapOut(
@@ -1852,6 +1925,10 @@ void RenderFrameHostImpl::SwapOut(
proxy->frame_tree_node()->current_replication_state();
Send(new FrameMsg_SwapOut(routing_id_, proxy->GetRoutingID(), is_loading,
replication_state));
+
+ // Remember that a RenderFrameProxy was created as part of processing the
+ // SwapOut message above.
+ proxy->set_render_frame_proxy_created(true);
}
if (web_ui())
@@ -2188,7 +2265,7 @@ void RenderFrameHostImpl::OnSmartClipDataExtracted(int32_t callback_id,
void RenderFrameHostImpl::OnVisualStateResponse(uint64_t id) {
auto it = visual_state_callbacks_.find(id);
if (it != visual_state_callbacks_.end()) {
- it->second.Run(true);
+ std::move(it->second).Run(true);
visual_state_callbacks_.erase(it);
} else {
NOTREACHED() << "Received script response for unknown request";
@@ -2210,13 +2287,6 @@ void RenderFrameHostImpl::OnRunJavaScriptDialog(
return;
}
- int32_t message_length = static_cast<int32_t>(message.length());
- if (GetParent()) {
- UMA_HISTOGRAM_COUNTS("JSDialogs.CharacterCount.Subframe", message_length);
- } else {
- UMA_HISTOGRAM_COUNTS("JSDialogs.CharacterCount.MainFrame", message_length);
- }
-
// While a JS message dialog is showing, tabs in the same process shouldn't
// process input events.
GetProcess()->SetIgnoreInputEvents(true);
@@ -2324,10 +2394,11 @@ void RenderFrameHostImpl::AllowBindings(int bindings_flags) {
"frame_tree_node", frame_tree_node_->frame_tree_node_id(),
"bindings flags", bindings_flags);
+ int webui_bindings = bindings_flags & kWebUIBindingsPolicyMask;
+
// Ensure we aren't granting WebUI bindings to a process that has already
// been used for non-privileged views.
- if (bindings_flags & BINDINGS_POLICY_WEB_UI &&
- GetProcess()->HasConnection() &&
+ if (webui_bindings && GetProcess()->IsInitializedAndNotDead() &&
!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
GetProcess()->GetID())) {
// This process has no bindings yet. Make sure it does not have more
@@ -2339,9 +2410,9 @@ void RenderFrameHostImpl::AllowBindings(int bindings_flags) {
return;
}
- if (bindings_flags & BINDINGS_POLICY_WEB_UI) {
+ if (webui_bindings) {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
- GetProcess()->GetID());
+ GetProcess()->GetID(), webui_bindings);
}
enabled_bindings_ |= bindings_flags;
@@ -2533,6 +2604,12 @@ void RenderFrameHostImpl::FrameSizeChanged(const gfx::Size& frame_size) {
frame_size_ = frame_size;
}
+void RenderFrameHostImpl::FullscreenStateChanged(bool is_fullscreen) {
+ if (!is_active())
+ return;
+ delegate_->FullscreenStateChanged(this, is_fullscreen);
+}
+
void RenderFrameHostImpl::OnDidBlockFramebust(const GURL& url) {
delegate_->OnDidBlockFramebust(url);
}
@@ -2604,13 +2681,14 @@ RenderWidgetHostViewBase* RenderFrameHostImpl::GetViewForAccessibility() {
}
void RenderFrameHostImpl::OnAccessibilityEvents(
- const std::vector<AccessibilityHostMsg_EventParams>& params,
- int reset_token, int ack_token) {
+ const AccessibilityHostMsg_EventBundleParams& bundle,
+ int reset_token,
+ int ack_token) {
// Don't process this IPC if either we're waiting on a reset and this
// IPC doesn't have the matching token ID, or if we're not waiting on a
// reset but this message includes a reset token.
if (accessibility_reset_token_ != reset_token) {
- Send(new AccessibilityMsg_Events_ACK(routing_id_, ack_token));
+ Send(new AccessibilityMsg_EventBundle_ACK(routing_id_, ack_token));
return;
}
accessibility_reset_token_ = 0;
@@ -2621,29 +2699,27 @@ void RenderFrameHostImpl::OnAccessibilityEvents(
if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs))
GetOrCreateBrowserAccessibilityManager();
- std::vector<AXEventNotificationDetails> details;
- details.reserve(params.size());
- for (size_t i = 0; i < params.size(); ++i) {
- const AccessibilityHostMsg_EventParams& param = params[i];
- AXEventNotificationDetails detail;
- detail.event_type = param.event_type;
- detail.id = param.id;
- detail.ax_tree_id = GetAXTreeID();
- detail.event_from = param.event_from;
- detail.action_request_id = param.action_request_id;
- if (param.update.has_tree_data) {
- detail.update.has_tree_data = true;
- ax_content_tree_data_ = param.update.tree_data;
- AXContentTreeDataToAXTreeData(&detail.update.tree_data);
+ AXEventNotificationDetails details;
+ details.ax_tree_id = GetAXTreeID();
+ details.events = bundle.events;
+
+ details.updates.resize(bundle.updates.size());
+ for (size_t i = 0; i < bundle.updates.size(); ++i) {
+ const AXContentTreeUpdate& src_update = bundle.updates[i];
+ ui::AXTreeUpdate* dst_update = &details.updates[i];
+ if (src_update.has_tree_data) {
+ dst_update->has_tree_data = true;
+ ax_content_tree_data_ = src_update.tree_data;
+ AXContentTreeDataToAXTreeData(&dst_update->tree_data);
}
- detail.update.root_id = param.update.root_id;
- detail.update.node_id_to_clear = param.update.node_id_to_clear;
- detail.update.nodes.resize(param.update.nodes.size());
- for (size_t j = 0; j < param.update.nodes.size(); ++j) {
- AXContentNodeDataToAXNodeData(param.update.nodes[j],
- &detail.update.nodes[j]);
+ dst_update->root_id = src_update.root_id;
+ dst_update->node_id_to_clear = src_update.node_id_to_clear;
+ dst_update->event_from = src_update.event_from;
+ dst_update->nodes.resize(src_update.nodes.size());
+ for (size_t j = 0; j < src_update.nodes.size(); ++j) {
+ AXContentNodeDataToAXNodeData(src_update.nodes[j],
+ &dst_update->nodes[j]);
}
- details.push_back(detail);
}
if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs)) {
@@ -2655,31 +2731,36 @@ void RenderFrameHostImpl::OnAccessibilityEvents(
// For testing only.
if (!accessibility_testing_callback_.is_null()) {
- for (size_t i = 0; i < details.size(); i++) {
- const AXEventNotificationDetails& detail = details[i];
- if (static_cast<int>(detail.event_type) < 0)
- continue;
-
+ // Apply tree updates to test tree.
+ for (size_t i = 0; i < details.updates.size(); i++) {
if (!ax_tree_for_testing_) {
if (browser_accessibility_manager_) {
ax_tree_for_testing_.reset(new ui::AXTree(
browser_accessibility_manager_->SnapshotAXTreeForTesting()));
} else {
ax_tree_for_testing_.reset(new ui::AXTree());
- CHECK(ax_tree_for_testing_->Unserialize(detail.update))
+ CHECK(ax_tree_for_testing_->Unserialize(details.updates[i]))
<< ax_tree_for_testing_->error();
}
} else {
- CHECK(ax_tree_for_testing_->Unserialize(detail.update))
+ CHECK(ax_tree_for_testing_->Unserialize(details.updates[i]))
<< ax_tree_for_testing_->error();
}
- accessibility_testing_callback_.Run(this, detail.event_type, detail.id);
+ }
+
+ // Call testing callback functions for each event to fire.
+ for (size_t i = 0; i < details.events.size(); i++) {
+ if (static_cast<int>(details.events[i].event_type) < 0)
+ continue;
+
+ accessibility_testing_callback_.Run(this, details.events[i].event_type,
+ details.events[i].id);
}
}
}
// Always send an ACK or the renderer can be in a bad state.
- Send(new AccessibilityMsg_Events_ACK(routing_id_, ack_token));
+ Send(new AccessibilityMsg_EventBundle_ACK(routing_id_, ack_token));
}
void RenderFrameHostImpl::OnAccessibilityLocationChanges(
@@ -2817,6 +2898,7 @@ void RenderFrameHostImpl::OnEnterFullscreen(
// TODO(alexmos): See if this can use the last committed origin instead.
delegate_->EnterFullscreenMode(GetLastCommittedURL().GetOrigin(), options);
+ delegate_->FullscreenStateChanged(this, true /* is_fullscreen */);
// The previous call might change the fullscreen state. We need to make sure
// the renderer is aware of that, which is done via the resize message.
@@ -2898,7 +2980,6 @@ void RenderFrameHostImpl::OnDidStopLoading() {
was_discarded_ = false;
is_loading_ = false;
- navigation_request_.reset();
// Only inform the FrameTreeNode of a change in load state if the load state
// of this RenderFrameHost is being tracked.
@@ -2945,8 +3026,11 @@ void RenderFrameHostImpl::NotifyUserActivation() {
Send(new FrameMsg_NotifyUserActivation(routing_id_));
}
-void RenderFrameHostImpl::OnSetHasReceivedUserGesture() {
- frame_tree_node_->OnSetHasReceivedUserGesture();
+void RenderFrameHostImpl::OnUpdateUserActivationState(
+ blink::UserActivationUpdateType update_type) {
+ if (!is_active())
+ return;
+ frame_tree_node_->UpdateUserActivationState(update_type);
}
void RenderFrameHostImpl::OnSetHasReceivedUserGestureBeforeNavigation(
@@ -3069,6 +3153,11 @@ void RenderFrameHostImpl::CreateNewWindow(
params->target_url = GURL(url::kAboutBlankURL);
}
+ bool effective_transient_activation_state =
+ params->mimic_user_gesture ||
+ (base::FeatureList::IsEnabled(features::kUserActivationV2) &&
+ frame_tree_node_->HasTransientUserActivation());
+
// Ignore window creation when sent from a frame that's not current or
// created.
bool can_create_window =
@@ -3078,8 +3167,16 @@ void RenderFrameHostImpl::CreateNewWindow(
frame_tree_node_->frame_tree()->GetMainFrame()->GetLastCommittedURL(),
last_committed_origin_.GetURL(), params->window_container_type,
params->target_url, params->referrer, params->frame_name,
- params->disposition, *params->features, params->user_gesture,
- params->opener_suppressed, &no_javascript_access);
+ params->disposition, *params->features,
+ effective_transient_activation_state, params->opener_suppressed,
+ &no_javascript_access);
+
+ if (can_create_window) {
+ // Consume activation even w/o User Activation v2, to sync other renderers
+ // with calling renderer.
+ frame_tree_node_->UpdateUserActivationState(
+ blink::UserActivationUpdateType::kConsumeTransientActivation);
+ }
if (!can_create_window) {
std::move(callback).Run(mojom::CreateNewWindowStatus::kIgnore, nullptr);
@@ -3102,18 +3199,10 @@ void RenderFrameHostImpl::CreateNewWindow(
static_cast<DOMStorageContextWrapper*>(
storage_partition->GetDOMStorageContext());
- scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace;
- if (base::FeatureList::IsEnabled(features::kMojoSessionStorage)) {
- // Any cloning should / will happen using the
- // SessionStorageNamespace::Clone in storage_partition_service.mojom.
- cloned_namespace = SessionStorageNamespaceImpl::CloneFrom(
- dom_storage_context, params->session_storage_namespace_id,
- params->clone_from_session_storage_namespace_id);
- } else {
- cloned_namespace = SessionStorageNamespaceImpl::CloneFrom(
- dom_storage_context, params->session_storage_namespace_id,
- params->clone_from_session_storage_namespace_id);
- }
+ scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace =
+ SessionStorageNamespaceImpl::CloneFrom(
+ dom_storage_context, params->session_storage_namespace_id,
+ params->clone_from_session_storage_namespace_id);
// If the opener is suppressed or script access is disallowed, we should
// open the window in a new BrowsingInstance, and thus a new process. That
@@ -3127,10 +3216,7 @@ void RenderFrameHostImpl::CreateNewWindow(
if (!params->opener_suppressed && !no_javascript_access) {
render_view_route_id = GetProcess()->GetNextRoutingID();
main_frame_route_id = GetProcess()->GetNextRoutingID();
- // TODO(avi): When RenderViewHostImpl has-a RenderWidgetHostImpl, this
- // should be updated to give the widget a distinct routing ID.
- // https://crbug.com/545684
- main_frame_widget_route_id = render_view_route_id;
+ main_frame_widget_route_id = GetProcess()->GetNextRoutingID();
// 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
@@ -3207,12 +3293,12 @@ void RenderFrameHostImpl::IssueKeepAliveHandle(
keep_alive_handle_factory_->Create(std::move(request));
}
-// TODO(ahemery): Move message checks to a StructTraits file when possible,
-// otherwise mojo bad message reporting.
+// TODO(ahemery): Move checks to mojo bad message reporting.
void RenderFrameHostImpl::BeginNavigation(
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
- blink::mojom::BlobURLTokenPtr blob_url_token) {
+ blink::mojom::BlobURLTokenPtr blob_url_token,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client) {
if (!is_active())
return;
@@ -3220,6 +3306,8 @@ void RenderFrameHostImpl::BeginNavigation(
"frame_tree_node", frame_tree_node_->frame_tree_node_id(), "url",
common_params.url.possibly_invalid_spec());
+ DCHECK(IsPerNavigationMojoInterfaceEnabled() == navigation_client.is_valid());
+
CommonNavigationParams validated_params = common_params;
GetProcess()->FilterURL(false, &validated_params.url);
if (!validated_params.base_url_for_data_url.is_empty()) {
@@ -3243,6 +3331,12 @@ void RenderFrameHostImpl::BeginNavigation(
return;
}
+ // If the request was for a blob URL, but the validated URL is no longer a
+ // blob URL, reset the blob_url_token to prevent hitting the ReportBadMessage
+ // below, and to make sure we don't incorrectly try to use the blob_url_token.
+ if (common_params.url.SchemeIsBlob() && !validated_params.url.SchemeIsBlob())
+ blob_url_token = nullptr;
+
if (blob_url_token && !validated_params.url.SchemeIsBlob()) {
mojo::ReportBadMessage("Blob URL Token, but not a blob: URL");
return;
@@ -3254,16 +3348,27 @@ void RenderFrameHostImpl::BeginNavigation(
GetSiteInstance()->GetBrowserContext(), std::move(blob_url_token));
}
+ // If the request was for a blob URL, but no blob_url_token was passed in this
+ // is not necessarily an error. Renderer initiated reloads for example are one
+ // situation where a renderer currently doesn't have an easy way of resolving
+ // the blob URL. For those situations resolve the blob URL here, as we don't
+ // care about ordering with other blob URL manipulation anyway.
+ if (blink::BlobUtils::MojoBlobURLsEnabled() &&
+ validated_params.url.SchemeIsBlob() && !blob_url_loader_factory) {
+ blob_url_loader_factory = ChromeBlobStorageContext::URLLoaderFactoryForUrl(
+ GetSiteInstance()->GetBrowserContext(), validated_params.url);
+ }
+
if (waiting_for_init_) {
pending_navigate_ = std::make_unique<PendingNavigation>(
validated_params, std::move(begin_params),
- std::move(blob_url_loader_factory));
+ std::move(blob_url_loader_factory), std::move(navigation_client));
return;
}
frame_tree_node()->navigator()->OnBeginNavigation(
frame_tree_node(), validated_params, std::move(begin_params),
- std::move(blob_url_loader_factory));
+ std::move(blob_url_loader_factory), std::move(navigation_client));
}
void RenderFrameHostImpl::SubresourceResponseStarted(
@@ -3277,30 +3382,6 @@ void RenderFrameHostImpl::ResourceLoadComplete(
delegate_->ResourceLoadComplete(this, std::move(resource_load_info));
}
-namespace {
-
-void GetRestrictedCookieManager(
- RenderFrameHostImpl* render_frame_host_impl,
- network::mojom::RestrictedCookieManagerRequest request) {
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableExperimentalWebPlatformFeatures)) {
- return;
- }
-
- BrowserContext* browser_context =
- render_frame_host_impl->GetProcess()->GetBrowserContext();
- StoragePartition* storage_partition =
- BrowserContext::GetDefaultStoragePartition(browser_context);
- network::mojom::NetworkContext* network_context =
- storage_partition->GetNetworkContext();
- uint32_t render_process_id = render_frame_host_impl->GetProcess()->GetID();
- uint32_t render_frame_id = render_frame_host_impl->GetRoutingID();
- network_context->GetRestrictedCookieManager(
- std::move(request), render_process_id, render_frame_id);
-}
-
-} // anonymous namespace
-
void RenderFrameHostImpl::RegisterMojoInterfaces() {
#if !defined(OS_ANDROID)
// The default (no-op) implementation of InstalledAppProvider. On Android, the
@@ -3308,14 +3389,14 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
registry_->AddInterface(base::Bind(&InstalledAppProviderImplDefault::Create));
#endif // !defined(OS_ANDROID)
- PermissionManager* permission_manager =
- GetProcess()->GetBrowserContext()->GetPermissionManager();
-
+ PermissionControllerImpl* permission_controller =
+ PermissionControllerImpl::FromBrowserContext(
+ GetProcess()->GetBrowserContext());
if (delegate_) {
auto* geolocation_context = delegate_->GetGeolocationContext();
- if (geolocation_context && permission_manager) {
+ if (geolocation_context) {
geolocation_service_.reset(new GeolocationServiceImpl(
- geolocation_context, permission_manager, this));
+ geolocation_context, permission_controller, this));
// NOTE: Both the |interface_registry_| and |geolocation_service_| are
// owned by |this|, so their destruction will be triggered together.
// |interface_registry_| is declared after |geolocation_service_|, so it
@@ -3374,6 +3455,8 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
registry_->AddInterface(base::Bind(&SharedWorkerConnectorImpl::Create,
process_->GetID(), routing_id_));
+ registry_->AddInterface(base::BindRepeating(&device::GamepadMonitor::Create));
+
registry_->AddInterface<device::mojom::VRService>(base::Bind(
&WebvrServiceProvider::BindWebvrService, base::Unretained(this)));
@@ -3437,22 +3520,23 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
}
#endif // !defined(OS_ANDROID)
- if (permission_manager) {
- sensor_provider_proxy_.reset(
- new SensorProviderProxyImpl(permission_manager, this));
- registry_->AddInterface(
- base::Bind(&SensorProviderProxyImpl::Bind,
- base::Unretained(sensor_provider_proxy_.get())));
+ sensor_provider_proxy_.reset(
+ new SensorProviderProxyImpl(permission_controller, this));
+ registry_->AddInterface(
+ base::Bind(&SensorProviderProxyImpl::Bind,
+ base::Unretained(sensor_provider_proxy_.get())));
+
+ // Only save decode stats when BrowserContext provides a VideoPerfHistory.
+ // Off-the-record contexts will internally use an ephemeral history DB.
+ media::VideoDecodePerfHistory::SaveCallback save_stats_cb;
+ if (GetSiteInstance()->GetBrowserContext()->GetVideoDecodePerfHistory()) {
+ save_stats_cb = GetSiteInstance()
+ ->GetBrowserContext()
+ ->GetVideoDecodePerfHistory()
+ ->GetSaveCallback();
}
-
registry_->AddInterface(base::BindRepeating(
- &media::MediaMetricsProvider::Create,
- // Only save decode stats when on-the-record.
- GetSiteInstance()->GetBrowserContext()->IsOffTheRecord()
- ? nullptr
- : GetSiteInstance()
- ->GetBrowserContext()
- ->GetVideoDecodePerfHistory()));
+ &media::MediaMetricsProvider::Create, std::move(save_stats_cb)));
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
cc::switches::kEnableGpuBenchmarking)) {
@@ -3460,37 +3544,14 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
base::Bind(&InputInjectorImpl::Create, weak_ptr_factory_.GetWeakPtr()));
}
- registry_->AddInterface(
- base::BindRepeating(GetRestrictedCookieManager, base::Unretained(this)));
-
// TODO(crbug.com/775792): Move to RendererInterfaceBinders.
registry_->AddInterface(base::BindRepeating(
&QuotaDispatcherHost::CreateForFrame, GetProcess(), routing_id_));
registry_->AddInterface(
- base::BindRepeating(
- SpeechRecognitionDispatcherHost::Create, GetProcess()->GetID(),
- routing_id_,
- base::WrapRefCounted(
- GetProcess()->GetStoragePartition()->GetURLRequestContext())),
+ base::BindRepeating(SpeechRecognitionDispatcherHost::Create,
+ GetProcess()->GetID(), routing_id_),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
-
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- StoragePartitionImpl* storage_partition =
- static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
- GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
- // TODO(https://crbug.com/813479): Investigate why we need to explicitly
- // specify task runner for BrowserThread::IO here.
- // Bind calls to the BindRegistry should come on to the IO thread by
- // default, but it looks we need this in browser tests (but not in full
- // chrome build), i.e. in content/browser/loader/prefetch_browsertest.cc.
- registry_->AddInterface(
- base::BindRepeating(
- &PrefetchURLLoaderService::ConnectToService,
- base::RetainedRef(storage_partition->GetPrefetchURLLoaderService()),
- frame_tree_node_->frame_tree_node_id()),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
- }
}
void RenderFrameHostImpl::ResetWaitingState() {
@@ -3554,14 +3615,13 @@ void RenderFrameHostImpl::NavigateToInterstitialURL(const GURL& data_url) {
CommonNavigationParams common_params(
data_url, Referrer(), ui::PAGE_TRANSITION_LINK,
FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, false, false,
- base::TimeTicks::Now(), FrameMsg_UILoadMetricsReportType::NO_REPORT,
GURL(), GURL(), PREVIEWS_OFF, base::TimeTicks::Now(), "GET", nullptr,
base::Optional<SourceLocation>(),
CSPDisposition::CHECK /* should_check_main_world_csp */,
false /* started_from_context_menu */, false /* has_user_gesture */,
std::vector<ContentSecurityPolicy>() /* initiator_csp */,
CSPSource() /* initiator_self_source */);
- CommitNavigation(nullptr, network::mojom::URLLoaderClientEndpointsPtr(),
+ CommitNavigation(0, nullptr, network::mojom::URLLoaderClientEndpointsPtr(),
common_params, RequestNavigationParams(), false,
base::nullopt, base::nullopt /* subresource_overrides */,
base::UnguessableToken::Create() /* not traced */);
@@ -3829,6 +3889,7 @@ void RenderFrameHostImpl::SendJavaScriptDialogReply(
}
void RenderFrameHostImpl::CommitNavigation(
+ int64_t navigation_id,
network::ResourceResponse* response,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
const CommonNavigationParams& common_params,
@@ -3880,9 +3941,6 @@ void RenderFrameHostImpl::CommitNavigation(
// however only do this for cross-document navigations, because the
// alternative would be redundant effort.
network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
- StoragePartitionImpl* storage_partition =
- static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
- browser_context, GetSiteInstance()));
if (subresource_loader_params &&
subresource_loader_params->loader_factory_info.is_valid()) {
// If the caller has supplied a default URLLoaderFactory override (for
@@ -3892,12 +3950,16 @@ void RenderFrameHostImpl::CommitNavigation(
} else {
std::string scheme = common_params.url.scheme();
const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
- if (std::find(schemes.begin(), schemes.end(), scheme) != schemes.end()) {
+ if (base::ContainsValue(schemes, scheme)) {
network::mojom::URLLoaderFactoryPtr factory_for_webui =
CreateWebUIURLLoaderBinding(this, scheme);
- if (enabled_bindings_ & BINDINGS_POLICY_WEB_UI) {
- // If the renderer has webui bindings, then don't give it access to
- // network loader for security reasons.
+ // If the renderer has webui bindings, then don't give it access to
+ // network loader for security reasons.
+ // http://crbug.com/829412: make an exception for a small whitelist
+ // of WebUIs that need to be fixed to not make network requests in JS.
+ if ((enabled_bindings_ & kWebUIBindingsPolicyMask) &&
+ !GetContentClient()->browser()->IsWebUIAllowedToMakeNetworkRequests(
+ url::Origin::Create(common_params.url.GetOrigin()))) {
default_factory_info = factory_for_webui.PassInterface();
} else {
// This is a webui scheme that doesn't have webui bindings. Give it
@@ -3918,12 +3980,6 @@ void RenderFrameHostImpl::CommitNavigation(
DCHECK(default_factory_info);
subresource_loader_factories->default_factory_info() =
std::move(default_factory_info);
- // Everyone gets a blob loader.
- network::mojom::URLLoaderFactoryPtrInfo blob_factory_info;
- storage_partition->GetBlobURLLoaderFactory()->HandleRequest(
- mojo::MakeRequest(&blob_factory_info));
- subresource_loader_factories->factories_info().emplace(
- url::kBlobScheme, std::move(blob_factory_info));
non_network_url_loader_factories_.clear();
@@ -3963,7 +4019,7 @@ void RenderFrameHostImpl::CommitNavigation(
network::mojom::URLLoaderFactoryPtrInfo factory_proxy_info;
auto factory_request = mojo::MakeRequest(&factory_proxy_info);
GetContentClient()->browser()->WillCreateURLLoaderFactory(
- this, false /* is_navigation */, &factory_request);
+ browser_context, this, false /* is_navigation */, &factory_request);
// Keep DevTools proxy lasy, i.e. closest to the network.
RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
this, false /* is_navigation */, false /* is_download */,
@@ -4004,22 +4060,61 @@ void RenderFrameHostImpl::CommitNavigation(
}
}
- GetNavigationControl()->CommitNavigation(
- head, common_params, request_params,
- std::move(url_loader_client_endpoints),
- std::move(subresource_loader_factories),
- std::move(subresource_overrides), std::move(controller),
- devtools_navigation_token);
+ network::mojom::URLLoaderFactoryPtr prefetch_loader_factory;
+ if (subresource_loader_factories) {
+ SaveSubresourceFactories(std::move(subresource_loader_factories));
+
+ // Also set-up URLLoaderFactory for prefetch using the same loader
+ // factories. TODO(kinuko): Consider setting this up only when prefetch
+ // is used. Currently we have this here to make sure we have non-racy
+ // situation (https://crbug.com/849929).
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+ auto* storage_partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetStoragePartition(
+ GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PrefetchURLLoaderService::GetFactory,
+ storage_partition->GetPrefetchURLLoaderService(),
+ mojo::MakeRequest(&prefetch_loader_factory),
+ frame_tree_node_->frame_tree_node_id(),
+ CloneSubresourceFactories()));
+ }
+
+ auto find_request = navigation_requests_.find(navigation_id);
+ NavigationRequest* request = find_request != navigation_requests_.end()
+ ? find_request->second.get()
+ : nullptr;
+
+ if (IsPerNavigationMojoInterfaceEnabled() && navigation_request_ &&
+ navigation_request_->GetCommitNavigationClient()) {
+ navigation_request_->GetCommitNavigationClient()->CommitNavigation(
+ head, common_params, request_params,
+ std::move(url_loader_client_endpoints), CloneSubresourceFactories(),
+ std::move(subresource_overrides), std::move(controller),
+ std::move(prefetch_loader_factory), devtools_navigation_token);
+ } else {
+ GetNavigationControl()->CommitNavigation(
+ head, common_params, request_params,
+ std::move(url_loader_client_endpoints), CloneSubresourceFactories(),
+ std::move(subresource_overrides), std::move(controller),
+ std::move(prefetch_loader_factory), devtools_navigation_token,
+ request ? base::BindOnce(
+ &RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
+ base::Unretained(this), navigation_id)
+ : content::mojom::FrameNavigationControl::
+ CommitNavigationCallback());
+ }
// |remote_object| is an associated interface ptr, so calls can't be made on
// it until its request endpoint is sent. Now that the request endpoint was
- // sent, it can be used, so add it to ServiceWorkerHandle.
+ // sent, it can be used, so add it to ServiceWorkerObjectHost.
if (remote_object.is_valid()) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
- &ServiceWorkerHandle::AddRemoteObjectPtrAndUpdateState,
- subresource_loader_params->controller_service_worker_handle,
+ &ServiceWorkerObjectHost::AddRemoteObjectPtrAndUpdateState,
+ subresource_loader_params->controller_service_worker_object_host,
std::move(remote_object), sent_state));
}
@@ -4032,6 +4127,7 @@ void RenderFrameHostImpl::CommitNavigation(
}
void RenderFrameHostImpl::FailedNavigation(
+ int64_t navigation_id,
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
bool has_stale_copy_in_cache,
@@ -4058,15 +4154,29 @@ void RenderFrameHostImpl::FailedNavigation(
std::move(default_factory_info),
std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>());
}
-
- GetNavigationControl()->CommitFailedNavigation(
- common_params, request_params, has_stale_copy_in_cache, error_code,
- error_page_content, std::move(subresource_loader_factories));
+ SaveSubresourceFactories(std::move(subresource_loader_factories));
+
+ auto find_request = navigation_requests_.find(navigation_id);
+ NavigationRequest* request = find_request != navigation_requests_.end()
+ ? find_request->second.get()
+ : nullptr;
+ if (IsPerNavigationMojoInterfaceEnabled() && request &&
+ request->GetCommitNavigationClient()) {
+ request->GetCommitNavigationClient()->CommitFailedNavigation(
+ common_params, request_params, has_stale_copy_in_cache, error_code,
+ error_page_content, CloneSubresourceFactories());
+ } else {
+ GetNavigationControl()->CommitFailedNavigation(
+ common_params, request_params, has_stale_copy_in_cache, error_code,
+ error_page_content, CloneSubresourceFactories(),
+ base::BindOnce(&RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
+ base::Unretained(this), navigation_id));
+ }
// An error page is expected to commit, hence why is_loading_ is set to true.
is_loading_ = true;
- DCHECK(GetNavigationHandle() &&
- GetNavigationHandle()->GetNetErrorCode() != net::OK);
+ DCHECK(request && request->navigation_handle() &&
+ request->navigation_handle()->GetNetErrorCode() != net::OK);
}
void RenderFrameHostImpl::HandleRendererDebugURL(const GURL& url) {
@@ -4155,6 +4265,12 @@ bool RenderFrameHostImpl::UpdatePendingWebUI(const GURL& dest_url,
// Reset the pending WebUI as from this point it will certainly not be reused.
ClearPendingWebUI();
+ // If error page isolation is enabled and this RenderFrameHost is going to
+ // commit an error page, there is no reason to create WebUI and give the
+ // process any bindings.
+ if (GetSiteInstance()->GetSiteURL() == GURL(kUnreachableWebDataURL))
+ return true;
+
// If this navigation is not to a WebUI, skip directly to bindings work.
if (new_web_ui_type != WebUI::kNoWebUI) {
if (new_web_ui_type == web_ui_type_) {
@@ -4238,7 +4354,8 @@ RenderFrameHostImpl::GetMojoImageDownloader() {
const blink::mojom::FindInPageAssociatedPtr&
RenderFrameHostImpl::GetFindInPage() {
- if (!find_in_page_)
+ if (!find_in_page_ || !find_in_page_.is_bound() ||
+ find_in_page_.encountered_error())
GetRemoteAssociatedInterfaces()->GetInterface(&find_in_page_);
return find_in_page_;
}
@@ -4338,8 +4455,7 @@ void RenderFrameHostImpl::RequestAXTreeSnapshot(AXTreeSnapshotCallback callback,
int callback_id = next_id++;
Send(new AccessibilityMsg_SnapshotTree(routing_id_, callback_id,
ax_mode.mode()));
- ax_tree_snapshot_callbacks_.insert(
- std::make_pair(callback_id, std::move(callback)));
+ ax_tree_snapshot_callbacks_.emplace(callback_id, std::move(callback));
}
void RenderFrameHostImpl::SetAccessibilityCallbackForTesting(
@@ -4354,18 +4470,16 @@ void RenderFrameHostImpl::UpdateAXTreeData() {
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);
+ detail.updates.resize(1);
+ detail.updates[0].has_tree_data = true;
+ AXContentTreeDataToAXTreeData(&detail.updates[0].tree_data);
if (browser_accessibility_manager_)
- browser_accessibility_manager_->OnAccessibilityEvents(details);
+ browser_accessibility_manager_->OnAccessibilityEvents(detail);
- delegate_->AccessibilityEventReceived(details);
+ delegate_->AccessibilityEventReceived(detail);
}
void RenderFrameHostImpl::SetTextTrackSettings(
@@ -4403,15 +4517,16 @@ void RenderFrameHostImpl::ActivateFindInPageResultForAccessibility(
}
void RenderFrameHostImpl::InsertVisualStateCallback(
- const VisualStateCallback& callback) {
+ VisualStateCallback callback) {
static uint64_t next_id = 1;
uint64_t key = next_id++;
Send(new FrameMsg_VisualStateRequest(routing_id_, key));
- visual_state_callbacks_.insert(std::make_pair(key, callback));
+ visual_state_callbacks_.emplace(key, std::move(callback));
}
bool RenderFrameHostImpl::IsRenderFrameLive() {
- bool is_live = GetProcess()->HasConnection() && render_frame_created_;
+ bool is_live =
+ GetProcess()->IsInitializedAndNotDead() && render_frame_created_;
// Sanity check: the RenderView should always be live if the RenderFrame is.
DCHECK(!is_live || render_view_host_->IsRenderViewLive());
@@ -4504,9 +4619,9 @@ void RenderFrameHostImpl::UpdatePermissionsForNavigation(
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params) {
// Browser plugin guests are not allowed to navigate outside web-safe schemes,
- // so do not grant them the ability to request additional URLs.
+ // so do not grant them the ability to commit additional URLs.
if (!GetProcess()->IsForGuestsOnly()) {
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantCommitURL(
GetProcess()->GetID(), common_params.url);
if (common_params.url.SchemeIs(url::kDataScheme) &&
!common_params.base_url_for_data_url.is_empty()) {
@@ -4514,7 +4629,7 @@ void RenderFrameHostImpl::UpdatePermissionsForNavigation(
// grant access to the base URL. This allows file: and other unexpected
// schemes to be accepted at commit time and during CORS checks (e.g., for
// font requests).
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantCommitURL(
GetProcess()->GetID(), common_params.base_url_for_data_url);
}
}
@@ -4553,47 +4668,37 @@ void RenderFrameHostImpl::UpdateSubresourceLoaderFactories() {
std::make_unique<URLLoaderFactoryBundleInfo>();
subresource_loader_factories->default_factory_info() =
std::move(default_factory_info);
+ SaveSubresourceFactories(std::move(subresource_loader_factories));
GetNavigationControl()->UpdateSubresourceLoaderFactories(
- std::move(subresource_loader_factories));
+ CloneSubresourceFactories());
+}
+
+std::set<int> RenderFrameHostImpl::GetNavigationEntryIdsPendingCommit() {
+ std::set<int> result;
+ if (navigation_request_)
+ result.insert(navigation_request_->nav_entry_id());
+ for (auto const& requests : navigation_requests_)
+ result.insert(requests.second->nav_entry_id());
+ return result;
}
void RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
network::mojom::URLLoaderFactoryRequest default_factory_request) {
- network::mojom::URLLoaderFactoryParamsPtr params =
- network::mojom::URLLoaderFactoryParams::New();
- params->process_id = GetProcess()->GetID();
- // TODO(lukasza): https://crbug.com/792546: Start using CORB.
- params->is_corb_enabled = false;
- network::mojom::URLLoaderFactoryParamsPtr params_for_error_monitoring =
- params->Clone();
-
- auto* context = GetSiteInstance()->GetBrowserContext();
- GetContentClient()->browser()->WillCreateURLLoaderFactory(
- this, false /* is_navigation */, &default_factory_request);
- // Keep DevTools proxy lasy, i.e. closest to the network.
- RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
- this, false /* is_navigation */, false /* is_download */,
- &default_factory_request);
- StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>(
- BrowserContext::GetStoragePartition(context, GetSiteInstance()));
- if (g_create_network_factory_callback_for_test.Get().is_null()) {
- storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
- std::move(default_factory_request), std::move(params));
- } else {
- network::mojom::URLLoaderFactoryPtr original_factory;
- storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
- mojo::MakeRequest(&original_factory), std::move(params));
- g_create_network_factory_callback_for_test.Get().Run(
- std::move(default_factory_request), GetProcess()->GetID(),
- original_factory.PassInterface());
- }
+ CreateNetworkServiceDefaultFactory(std::move(default_factory_request));
// Add connection error observer when Network Service is running
// out-of-process.
- if (IsOutOfProcessNetworkService()) {
+ if (IsOutOfProcessNetworkService() &&
+ (!network_service_connection_error_handler_holder_ ||
+ network_service_connection_error_handler_holder_.encountered_error())) {
+ StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
+ GetSiteInstance()->GetBrowserContext(), GetSiteInstance());
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = GetProcess()->GetID();
storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
mojo::MakeRequest(&network_service_connection_error_handler_holder_),
- std::move(params_for_error_monitoring));
+ std::move(params));
network_service_connection_error_handler_holder_
.set_connection_error_handler(base::BindOnce(
&RenderFrameHostImpl::UpdateSubresourceLoaderFactories,
@@ -4838,11 +4943,16 @@ void RenderFrameHostImpl::BindMediaInterfaceFactoryRequest(
void RenderFrameHostImpl::CreateWebSocket(
network::mojom::WebSocketRequest request) {
+ network::mojom::AuthenticationHandlerPtr auth_handler;
+ GetContentClient()->browser()->WillCreateWebSocket(this, &request,
+ &auth_handler);
+
// This is to support usage of WebSockets in cases in which there is an
// associated RenderFrame. This is important for showing the correct security
// state of the page and also honoring user override of bad certificates.
- WebSocketManager::CreateWebSocket(process_->GetID(), routing_id_,
- last_committed_origin_, std::move(request));
+ WebSocketManager::CreateWebSocket(
+ process_->GetID(), routing_id_, last_committed_origin_,
+ std::move(auth_handler), std::move(request));
}
void RenderFrameHostImpl::CreateDedicatedWorkerHostFactory(
@@ -4882,7 +4992,7 @@ void RenderFrameHostImpl::BindPresentationServiceRequest(
#if !defined(OS_ANDROID)
void RenderFrameHostImpl::BindAuthenticatorRequest(
- webauth::mojom::AuthenticatorRequest request) {
+ blink::mojom::AuthenticatorRequest request) {
if (!authenticator_impl_)
authenticator_impl_.reset(new AuthenticatorImpl(this));
@@ -4965,7 +5075,8 @@ RenderFrameHostImpl::TakeNavigationHandleForCommit(
if (navigation_handle && navigation_handle->GetURL() == params.url) {
std::unique_ptr<NavigationHandleImpl> result_navigation_handle =
navigation_request()->TakeNavigationHandle();
- navigation_request_.reset();
+ if (!IsPerNavigationMojoInterfaceEnabled())
+ navigation_request_.reset();
return result_navigation_handle;
}
@@ -5151,11 +5262,38 @@ bool RenderFrameHostImpl::ValidateDidCommitParams(
FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params) {
RenderProcessHost* process = GetProcess();
+ // Error pages may sometimes commit a URL in the wrong process, which requires
+ // an exception for the CanCommitURL checks. This is ok as long as the origin
+ // is unique.
+ // TODO(creis): Kill the renderer if it claims an error page has a non-unique
+ // origin.
+ bool is_permitted_error_page = false;
+ if (validated_params->origin.unique()) {
+ if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(
+ frame_tree_node_->IsMainFrame())) {
+ // With error page isolation, any URL can commit in an error page process.
+ if (GetSiteInstance()->GetSiteURL() ==
+ GURL(content::kUnreachableWebDataURL)) {
+ is_permitted_error_page = true;
+ }
+ } else {
+ // Without error page isolation, a blocked navigation is expected to
+ // commit in the old renderer process. This may be true for subframe
+ // navigations even when error page isolation is enabled for main frames.
+ if (GetNavigationHandle() && GetNavigationHandle()->GetNetErrorCode() ==
+ net::ERR_BLOCKED_BY_CLIENT) {
+ is_permitted_error_page = true;
+ }
+ }
+ }
+
// Attempts to commit certain off-limits URL should be caught more strictly
// than our FilterURL checks. If a renderer violates this policy, it
// should be killed.
- if (!CanCommitURL(validated_params->url)) {
+ if (!is_permitted_error_page && !CanCommitURL(validated_params->url)) {
VLOG(1) << "Blocked URL " << validated_params->url.spec();
+ LogRendererKillCrashKeys(GetSiteInstance()->GetSiteURL());
+
// Kills the process.
bad_message::ReceivedBadMessage(process,
bad_message::RFH_CAN_COMMIT_URL_BLOCKED);
@@ -5166,6 +5304,9 @@ bool RenderFrameHostImpl::ValidateDidCommitParams(
// be allowed to commit in this RenderFrameHost.
if (!CanCommitOrigin(validated_params->origin, validated_params->url)) {
DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, validated_params->origin);
+ LogRendererKillCrashKeys(GetSiteInstance()->GetSiteURL());
+
+ // Kills the process.
bad_message::ReceivedBadMessage(process,
bad_message::RFH_INVALID_ORIGIN_ON_COMMIT);
return false;
@@ -5203,22 +5344,6 @@ bool RenderFrameHostImpl::ValidateDidCommitParams(
return true;
}
-void RenderFrameHostImpl::UMACommitReport(
- FrameMsg_UILoadMetricsReportType::Value report_type,
- const base::TimeTicks& ui_timestamp) {
- if (report_type == FrameMsg_UILoadMetricsReportType::REPORT_LINK) {
- UMA_HISTOGRAM_CUSTOM_TIMES("Navigation.UI_OnCommitProvisionalLoad.Link",
- base::TimeTicks::Now() - ui_timestamp,
- base::TimeDelta::FromMilliseconds(10),
- base::TimeDelta::FromMinutes(10), 100);
- } else if (report_type == FrameMsg_UILoadMetricsReportType::REPORT_INTENT) {
- UMA_HISTOGRAM_CUSTOM_TIMES("Navigation.UI_OnCommitProvisionalLoad.Intent",
- base::TimeTicks::Now() - ui_timestamp,
- base::TimeDelta::FromMilliseconds(10),
- base::TimeDelta::FromMinutes(10), 100);
- }
-}
-
void RenderFrameHostImpl::UpdateSiteURL(const GURL& url,
bool url_is_unreachable) {
if (url_is_unreachable || delegate_->GetAsInterstitialPage()) {
@@ -5235,25 +5360,15 @@ bool RenderFrameHostImpl::DidCommitNavigationInternal(
DCHECK_EQ(ui::PageTransitionIsMainFrame(validated_params->transition),
!GetParent());
- UMACommitReport(validated_params->report_type,
- validated_params->ui_timestamp);
-
if (!ValidateDidCommitParams(validated_params))
return false;
- if (!navigation_request_) {
- // The browser has not been notified about the start of the
- // load in this renderer yet (e.g., for same-document navigations that start
- // in the renderer). Do it now.
- // TODO(ahemery): This should never be true for cross-document navigation
- // apart from race conditions. Move to same navigation specific code when
- // the full mojo interface is in place.
- // (https://bugs.chromium.org/p/chromium/issues/detail?id=784904)
- if (!is_loading()) {
- bool was_loading = frame_tree_node()->frame_tree()->IsLoading();
- is_loading_ = true;
- frame_tree_node()->DidStartLoading(true, was_loading);
- }
+ // A racy DidStopLoading IPC might have reset the loading state that was set
+ // to true in CommitNavigation. Set it to true now.
+ if (!is_loading()) {
+ bool was_loading = frame_tree_node()->frame_tree()->IsLoading();
+ is_loading_ = true;
+ frame_tree_node()->DidStartLoading(true, was_loading);
}
if (navigation_request_)
@@ -5275,6 +5390,8 @@ bool RenderFrameHostImpl::DidCommitNavigationInternal(
frame_tree_node()->navigator()->DidNavigate(this, *validated_params,
std::move(navigation_handle),
is_same_document_navigation);
+ if (IsPerNavigationMojoInterfaceEnabled() && !is_same_document_navigation)
+ navigation_request_.reset();
return true;
}
@@ -5298,10 +5415,49 @@ void RenderFrameHostImpl::OnSameDocumentCommitProcessed(
}
if (result == blink::mojom::CommitResult::Aborted) {
- // Note: if the commit was successful, navigation_handle_ is reset in
+ // Note: if the commit was successful, navigation_request_ is reset in
// DidCommitProvisionalLoad.
same_document_navigation_request_.reset();
}
}
+void RenderFrameHostImpl::OnCrossDocumentCommitProcessed(
+ int64_t navigation_id,
+ blink::mojom::CommitResult result) {
+ DCHECK_NE(blink::mojom::CommitResult::RestartCrossDocument, result);
+ if (result == blink::mojom::CommitResult::Ok) {
+ // The navigation will soon be committed. Move it out of the map to the
+ // NavigationRequest that is about to commit.
+ auto find_request = navigation_requests_.find(navigation_id);
+ if (find_request != navigation_requests_.end()) {
+ navigation_request_ = std::move(find_request->second);
+ } else {
+ NOTREACHED();
+ }
+ }
+ // Remove the requests from the list of NavigationRequests waiting to commit.
+ navigation_requests_.erase(navigation_id);
+}
+
+void RenderFrameHostImpl::SaveSubresourceFactories(
+ std::unique_ptr<URLLoaderFactoryBundleInfo> bundle_info) {
+ // CHECK for https://crbug.com/849929.
+ CHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService) ||
+ bundle_info);
+ subresource_loader_factories_bundle_ = nullptr;
+ if (bundle_info) {
+ subresource_loader_factories_bundle_ =
+ base::MakeRefCounted<URLLoaderFactoryBundle>(std::move(bundle_info));
+ }
+}
+
+std::unique_ptr<URLLoaderFactoryBundleInfo>
+RenderFrameHostImpl::CloneSubresourceFactories() {
+ if (subresource_loader_factories_bundle_) {
+ return base::WrapUnique(static_cast<URLLoaderFactoryBundleInfo*>(
+ subresource_loader_factories_bundle_->Clone().release()));
+ }
+ return nullptr;
+}
+
} // 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 e5c6b19d148..6c6f78fec35 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.h
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -63,6 +63,7 @@
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
#include "services/viz/public/interfaces/hit_test/input_target_client.mojom.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/common/frame/user_activation_update_type.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
#include "third_party/blink/public/platform/dedicated_worker_factory.mojom.h"
#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
@@ -86,7 +87,7 @@
#endif
class GURL;
-struct AccessibilityHostMsg_EventParams;
+struct AccessibilityHostMsg_EventBundleParams;
struct AccessibilityHostMsg_FindInPageResultParams;
struct AccessibilityHostMsg_LocationChangeParams;
struct FrameHostMsg_DidCommitProvisionalLoad_Params;
@@ -144,6 +145,7 @@ struct CommonNavigationParams;
struct ContextMenuParams;
struct FileChooserParams;
struct FrameOwnerProperties;
+struct PendingNavigation;
struct RequestNavigationParams;
struct ResourceTimingInfo;
struct SubresourceLoaderParams;
@@ -216,7 +218,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
void ExecuteJavaScriptWithUserGestureForTests(
const base::string16& javascript) override;
void ActivateFindInPageResultForAccessibility(int request_id) override;
- void InsertVisualStateCallback(const VisualStateCallback& callback) override;
+ void InsertVisualStateCallback(VisualStateCallback callback) override;
void CopyImageAt(int x, int y) override;
void SaveImageAt(int x, int y) override;
RenderViewHost* GetRenderViewHost() override;
@@ -240,6 +242,13 @@ class CONTENT_EXPORT RenderFrameHostImpl
blink::WebSuddenTerminationDisablerType disabler_type) override;
bool IsFeatureEnabled(blink::mojom::FeaturePolicyFeature feature) override;
void ViewSource() override;
+ blink::mojom::PauseSubresourceLoadingHandlePtr PauseSubresourceLoading()
+ override;
+ void ExecuteMediaPlayerActionAtLocation(
+ const gfx::Point&,
+ const blink::WebMediaPlayerAction& action) override;
+ void CreateNetworkServiceDefaultFactory(
+ network::mojom::URLLoaderFactoryRequest default_factory_request) override;
// IPC::Sender
bool Send(IPC::Message* msg) override;
@@ -573,7 +582,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
// |subresource_loader_params| is used in network service land to pass
// the parameters to create a custom subresource loader in the renderer
// process, e.g. by AppCache etc.
+ // TODO(clamy): Pass the NavigationRequest directly to this function when
+ // interstitials have been refactored to no longer call CommitNavigation
+ // without a NavigationRequest.
void CommitNavigation(
+ int64_t navigation_id,
network::ResourceResponse* response,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
const CommonNavigationParams& common_params,
@@ -586,7 +599,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Indicates that a navigation failed and that this RenderFrame should display
// an error page.
- void FailedNavigation(const CommonNavigationParams& common_params,
+ void FailedNavigation(int64_t navigation_id,
+ const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
bool has_stale_copy_in_cache,
int error_code,
@@ -745,6 +759,23 @@ class CONTENT_EXPORT RenderFrameHostImpl
// for unload handler processing.
void SetSubframeUnloadTimeoutForTesting(const base::TimeDelta& timeout);
+ bool received_post_message_from_non_descendant() const {
+ return received_post_message_from_non_descendant_;
+ }
+
+ void did_receive_post_message_from_non_descendant() {
+ received_post_message_from_non_descendant_ = true;
+ }
+
+ // Returns the list of NavigationEntry ids corresponding to NavigationRequests
+ // waiting to commit in this RenderFrameHost.
+ std::set<int> GetNavigationEntryIdsPendingCommit();
+
+ void DidCommitProvisionalLoadForTesting(
+ std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
+ service_manager::mojom::InterfaceProviderRequest
+ interface_provider_request);
+
protected:
friend class RenderFrameHostFactory;
@@ -768,6 +799,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
friend class TestRenderFrameHost;
friend class TestRenderViewHost;
+ FRIEND_TEST_ALL_PREFIXES(NavigatorTestWithBrowserSideNavigation,
+ TwoNavigationsRacingCommit);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBeforeUnloadBrowserTest,
SubframeShowsDialogWhenMainFrameNavigates);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBeforeUnloadBrowserTest,
@@ -800,6 +833,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
ActiveSandboxFlagsRetainedAfterSwapOut);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
LastCommittedURLRetainedAfterSwapOut);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ RenderFrameProxyNotRecreatedDuringProcessShutdown);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ SwapOutACKArrivesPriorToProcessShutdownRequest);
FRIEND_TEST_ALL_PREFIXES(SecurityExploitBrowserTest,
AttemptDuplicateRenderViewHost);
@@ -813,9 +850,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
void OnDetach();
void OnFrameFocused();
void OnOpenURL(const FrameHostMsg_OpenURL_Params& params);
- void OnDocumentOnLoadCompleted(
- FrameMsg_UILoadMetricsReportType::Value report_type,
- base::TimeTicks ui_timestamp);
+ void OnDocumentOnLoadCompleted();
void OnDidStartProvisionalLoad(
const GURL& url,
const std::vector<GURL>& redirect_chain,
@@ -858,12 +893,13 @@ class CONTENT_EXPORT RenderFrameHostImpl
void OnUpdateTitle(const base::string16& title,
blink::WebTextDirection title_direction);
void OnDidBlockFramebust(const GURL& url);
+ // Only used with PerNavigationMojoInterface disabled.
void OnAbortNavigation();
void OnForwardResourceTimingToParent(
const ResourceTimingInfo& resource_timing);
void OnDispatchLoad();
void OnAccessibilityEvents(
- const std::vector<AccessibilityHostMsg_EventParams>& params,
+ const AccessibilityHostMsg_EventBundleParams& params,
int reset_token,
int ack_token);
void OnAccessibilityLocationChanges(
@@ -897,7 +933,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
const gfx::Range& range);
void OnFocusedNodeChanged(bool is_editable_element,
const gfx::Rect& bounds_in_frame_widget);
- void OnSetHasReceivedUserGesture();
+ void OnUpdateUserActivationState(blink::UserActivationUpdateType update_type);
void OnSetHasReceivedUserGestureBeforeNavigation(bool value);
void OnScrollRectToVisibleInParentFrame(
const gfx::Rect& rect_to_scroll,
@@ -937,9 +973,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
void DidCommitSameDocumentNavigation(
std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
validated_params) override;
- void BeginNavigation(const CommonNavigationParams& common_params,
- mojom::BeginNavigationParamsPtr begin_params,
- blink::mojom::BlobURLTokenPtr blob_url_token) override;
+ void BeginNavigation(
+ const CommonNavigationParams& common_params,
+ mojom::BeginNavigationParamsPtr begin_params,
+ blink::mojom::BlobURLTokenPtr blob_url_token,
+ mojom::NavigationClientAssociatedPtrInfo navigation_client) override;
void SubresourceResponseStarted(const GURL& url,
net::CertStatus cert_status) override;
void ResourceLoadComplete(
@@ -955,6 +993,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
void CancelInitialHistoryLoad() override;
void UpdateEncoding(const std::string& encoding) override;
void FrameSizeChanged(const gfx::Size& frame_size) override;
+ void FullscreenStateChanged(bool is_fullscreen) override;
// Registers Mojo interfaces that this frame host makes available.
void RegisterMojoInterfaces();
@@ -1078,7 +1117,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
blink::mojom::PresentationServiceRequest request);
#if !defined(OS_ANDROID)
- void BindAuthenticatorRequest(webauth::mojom::AuthenticatorRequest request);
+ void BindAuthenticatorRequest(blink::mojom::AuthenticatorRequest request);
#endif
// service_manager::mojom::InterfaceProvider:
@@ -1171,11 +1210,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
// local roots which are under this frame and their first ancestor which is a
// local root is either this frame or this frame's local root. For instance,
// in a frame tree such as:
- // A0
- // / | \
- // B A1 E
- // / / \ \
- // D A2 C F
+ // A0 //
+ // / | \ //
+ // B A1 E //
+ // / / \ \ //
+ // D A2 C F //
// RFHs at nodes B, E, D, C, and F are all local roots in the given frame tree
// under the root at A0, but only B, C, and E are considered immediate local
// roots of A0. Note that this will exclude any speculative or pending RFHs.
@@ -1193,11 +1232,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
bool ValidateDidCommitParams(
FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params);
- // Utility function that does UMA reporting for link click or intent to
- // commit timings depending on |report_type|.
- void UMACommitReport(FrameMsg_UILoadMetricsReportType::Value report_type,
- const base::TimeTicks& ui_timestamp);
-
// Updates the site url if the navigation was successful and the page is not
// an interstitial.
void UpdateSiteURL(const GURL& url, bool url_is_unreachable);
@@ -1217,6 +1251,17 @@ class CONTENT_EXPORT RenderFrameHostImpl
bool should_replace_current_entry,
blink::mojom::CommitResult result);
+ // Called by the renderer process when it is done processing a cross-document
+ // commit request.
+ void OnCrossDocumentCommitProcessed(int64_t navigation_id,
+ blink::mojom::CommitResult result);
+
+ // Saves and clones URLLoaderFactoryBundleInfo for subresource loading.
+ // Must be called every time subresource_factories_bundle is updated.
+ void SaveSubresourceFactories(
+ std::unique_ptr<URLLoaderFactoryBundleInfo> bundle_info);
+ std::unique_ptr<URLLoaderFactoryBundleInfo> CloneSubresourceFactories();
+
// 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
@@ -1350,6 +1395,12 @@ class CONTENT_EXPORT RenderFrameHostImpl
// relevant NavigationEntry.
int nav_entry_id_;
+ // Tracks if a frame has been influenced by post message from
+ // non-descendant frames. Useful for determining if silently reloading a
+ // crashed frame is safe. Post messages from descendants to not matter for
+ // this decision since they will be reloaded as well.
+ bool received_post_message_from_non_descendant_ = false;
+
// Used to swap out or shut down this RFH when the unload event is taking too
// long to execute, depending on the number of active frames in the
// SiteInstance. May be null in tests.
@@ -1423,10 +1474,18 @@ class CONTENT_EXPORT RenderFrameHostImpl
std::unique_ptr<resource_coordinator::FrameResourceCoordinator>
frame_resource_coordinator_;
- // Holds a NavigationRequest while waiting for the navigation it is tracking
- // to commit. This NavigationRequest is for a cross-document navigation.
+ // Holds a NavigationRequest when it's about to commit, ie. after
+ // OnCrossDocumentCommitProcessed has returned a positive answer for this
+ // NavigationRequest but before receiving DidCommitProvisionalLoad. This
+ // NavigationRequest is for a cross-document navigation.
std::unique_ptr<NavigationRequest> navigation_request_;
+ // Holds the cross-document NavigationRequests that are waiting to commit,
+ // indexed by IDs. These are navigations that have passed ReadyToCommit stage
+ // and are waiting for the renderer to send back a matching
+ // OnCrossDocumentCommitProcessed.
+ std::map<int64_t, std::unique_ptr<NavigationRequest>> navigation_requests_;
+
// Holds a same-document NavigationRequest while waiting for the navigation it
// is tracking to commit.
std::unique_ptr<NavigationRequest> same_document_navigation_request_;
@@ -1477,16 +1536,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// If true then this frame's document has a focused element which is editable.
bool has_focused_editable_element_;
- struct PendingNavigation {
- PendingNavigation(
- const CommonNavigationParams& common_params,
- mojom::BeginNavigationParamsPtr begin_params,
- scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
- ~PendingNavigation();
- CommonNavigationParams common_params;
- mojom::BeginNavigationParamsPtr begin_params;
- scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
- };
std::unique_ptr<PendingNavigation> pending_navigate_;
// A collection of non-network URLLoaderFactory implementations which are used
@@ -1495,6 +1544,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
ContentBrowserClient::NonNetworkURLLoaderFactoryMap
non_network_url_loader_factories_;
+ // A bundle of subresource loader factories used by this frame.
+ // A clone of this bundle is sent to the renderer process.
+ scoped_refptr<URLLoaderFactoryBundle> subresource_loader_factories_bundle_;
+
// Bitfield for renderer-side state that blocks fast shutdown of the frame.
blink::WebSuddenTerminationDisablerType
sudden_termination_disabler_types_enabled_ = 0;
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc
index cd82082fbb7..87210e4c20e 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -10,7 +10,7 @@
#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
@@ -1036,7 +1036,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, POSTNavigation) {
EXPECT_TRUE(shell()
->web_contents()
->GetController()
- .GetActiveEntry()
+ .GetLastCommittedEntry()
->GetHasPostData());
// Reload and verify the form was submitted.
@@ -1349,7 +1349,7 @@ class ScopedFakeInterfaceProviderRequestInjector
}
protected:
- void WillDispatchDidCommitProvisionalLoad(
+ bool WillDispatchDidCommitProvisionalLoad(
RenderFrameHost* render_frame_host,
::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
service_manager::mojom::InterfaceProviderRequest*
@@ -1357,6 +1357,7 @@ class ScopedFakeInterfaceProviderRequestInjector
url_of_last_commit_ = params->url;
original_request_of_last_commit_ = std::move(*interface_provider_request);
*interface_provider_request = std::move(next_fake_request_);
+ return true;
}
private:
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 b682235b0f8..872e4609c94 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -58,6 +58,16 @@
namespace content {
+namespace {
+
+bool IsDataOrAbout(const GURL& url) {
+ GURL about_srcdoc(content::kAboutSrcDocURL);
+ return url == about_srcdoc || url.IsAboutBlank() ||
+ url.scheme() == url::kDataScheme;
+}
+
+} // namespace
+
RenderFrameHostManager::RenderFrameHostManager(
FrameTreeNode* frame_tree_node,
RenderFrameHostDelegate* render_frame_delegate,
@@ -92,11 +102,6 @@ void RenderFrameHostManager::Init(SiteInstance* site_instance,
int32_t widget_routing_id,
bool renderer_initiated_creation) {
DCHECK(site_instance);
- // TODO(avi): While RenderViewHostImpl is-a RenderWidgetHostImpl, this must
- // hold true to avoid having two RenderWidgetHosts for the top-level frame.
- // https://crbug.com/545684
- DCHECK(!frame_tree_node_->IsMainFrame() ||
- view_routing_id == widget_routing_id);
SetRenderFrameHost(CreateRenderFrameHost(site_instance, view_routing_id,
frame_routing_id, widget_routing_id,
delegate_->IsHidden(),
@@ -395,9 +400,6 @@ void RenderFrameHostManager::SwapOutOldFrame(
// Tell the old RenderFrameHost to swap out and be replaced by the proxy.
old_render_frame_host->SwapOut(proxy, true);
- // SwapOut creates a RenderFrameProxy, so set the proxy to be initialized.
- proxy->set_render_frame_proxy_created(true);
-
// |old_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).
@@ -521,11 +523,16 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// navigation was started from BeginNavigation. If the navigation was
// started through the NavigationController, the NavigationController has
// already updated its state properly, and doesn't need to be notified.
- if (speculative_render_frame_host_->GetNavigationHandle() &&
- request.from_begin_navigation()) {
- frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(
- speculative_render_frame_host_->GetNavigationHandle()
- ->pending_nav_entry_id());
+ // Note: We query all NavigationEntry IDs fom the RenderFrameHost, however
+ // at most one call to DiscardPendingEntryIfNeeded will succeed. Since we
+ // don't know which of the entries is the pending one, we have to try them
+ // all.
+ // TODO(clamy): Clean this up.
+ if (request.from_begin_navigation()) {
+ std::set<int> ids = speculative_render_frame_host_
+ ->GetNavigationEntryIdsPendingCommit();
+ for (int id : ids)
+ frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(id);
}
DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost());
}
@@ -559,12 +566,16 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// was started through the NavigationController, the NavigationController
// has already updated its state properly, and doesn't need to be
// notified.
- if (speculative_render_frame_host_ &&
- speculative_render_frame_host_->GetNavigationHandle() &&
- request.from_begin_navigation()) {
- frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(
- speculative_render_frame_host_->GetNavigationHandle()
- ->pending_nav_entry_id());
+ // Note: We query all NavigationEntry IDs fom the RenderFrameHost, however
+ // at most one call to DiscardPendingEntryIfNeeded will succeed. Since we
+ // don't know which of the entries is the pending one, we have to try them
+ // all.
+ // TODO(clamy): Clean this up.
+ if (request.from_begin_navigation() && speculative_render_frame_host_) {
+ std::set<int> ids = speculative_render_frame_host_
+ ->GetNavigationEntryIdsPendingCommit();
+ for (int id : ids)
+ frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(id);
}
// If a previous speculative RenderFrameHost didn't exist or if its
@@ -644,7 +655,7 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// removed once the process manager moves away from NotificationService.
// See https://crbug.com/462682.
delegate_->NotifyMainFrameSwappedFromRenderManager(
- nullptr, render_frame_host_->render_view_host());
+ nullptr, render_frame_host_.get());
}
}
@@ -817,10 +828,11 @@ void RenderFrameHostManager::CancelPendingIfNecessary(
}
}
-void RenderFrameHostManager::OnSetHasReceivedUserGesture() {
+void RenderFrameHostManager::UpdateUserActivationState(
+ blink::UserActivationUpdateType update_type) {
for (const auto& pair : proxy_hosts_) {
- pair.second->Send(
- new FrameMsg_SetHasReceivedUserGesture(pair.second->GetRoutingID()));
+ pair.second->Send(new FrameMsg_UpdateUserActivationState(
+ pair.second->GetRoutingID(), update_type));
}
}
@@ -873,13 +885,23 @@ bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation(
bool current_is_view_source_mode,
SiteInstance* new_site_instance,
const GURL& new_effective_url,
- bool new_is_view_source_mode) const {
+ bool new_is_view_source_mode,
+ bool is_failure) const {
// A subframe must stay in the same BrowsingInstance as its parent.
// TODO(nasko): Ensure that SiteInstance swap is still triggered for subframes
// in the cases covered by the rest of the checks in this method.
if (!frame_tree_node_->IsMainFrame())
return false;
+ // If the navigation has resulted in an error page, do not swap
+ // BrowsingInstance and keep the error page in a related SiteInstance. If
+ // later a reload of this navigation is successful, it will correctly
+ // create a new BrowsingInstance.
+ if (is_failure && SiteIsolationPolicy::IsErrorPageIsolationEnabled(
+ frame_tree_node_->IsMainFrame())) {
+ return false;
+ }
+
// If new_entry already has a SiteInstance, assume it is correct. We only
// need to force a swap if it is in a different BrowsingInstance.
if (new_site_instance) {
@@ -1018,11 +1040,9 @@ RenderFrameHostManager::GetSiteInstanceForNavigation(
current_entry->IsViewSourceMode() : dest_is_view_source_mode;
bool force_swap = ShouldSwapBrowsingInstancesForNavigation(
- current_effective_url,
- current_is_view_source_mode,
- dest_instance,
+ current_effective_url, current_is_view_source_mode, dest_instance,
SiteInstanceImpl::GetEffectiveURL(browser_context, dest_url),
- dest_is_view_source_mode);
+ dest_is_view_source_mode, is_failure);
SiteInstanceDescriptor new_instance_descriptor =
SiteInstanceDescriptor(current_instance);
if (ShouldTransitionCrossSite() || force_swap) {
@@ -1093,8 +1113,8 @@ void RenderFrameHostManager::InitializeRenderFrameIfNecessary(
// RenderFrameHostManager are completely initialized. This should be
// removed once the process manager moves away from NotificationService.
// See https://crbug.com/462682.
- delegate_->NotifyMainFrameSwappedFromRenderManager(
- nullptr, render_frame_host_->render_view_host());
+ delegate_->NotifyMainFrameSwappedFromRenderManager(nullptr,
+ render_frame_host_.get());
}
RenderFrameHostManager::SiteInstanceDescriptor
@@ -1115,14 +1135,39 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
delegate_->GetControllerForRenderManager();
BrowserContext* browser_context = controller.GetBrowserContext();
- // If the entry has an instance already we should use it.
+ // If the entry has an instance already we should use it, unless it is no
+ // longer suitable.
if (dest_instance) {
- // If we are forcing a swap, this should be in a different BrowsingInstance.
- if (force_browsing_instance_swap) {
- CHECK(!dest_instance->IsRelatedSiteInstance(
- render_frame_host_->GetSiteInstance()));
+ // When error page isolation is enabled, don't reuse |dest_instance| if it's
+ // an error page SiteInstance, but the navigation will no longer fail.
+ // Similarly, don't reuse |dest_instance| if it's not an error page
+ // SiteInstance but the navigation will fail and actually need an error page
+ // SiteInstance.
+ // Note: The later call to HasWrongProcessForURL does not have context about
+ // error page navigaions, so we cannot rely on it to return correct value
+ // when error pages are involved.
+ if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(
+ frame_tree_node_->IsMainFrame()) ||
+ ((dest_instance->GetSiteURL() == GURL(kUnreachableWebDataURL)) ==
+ is_failure)) {
+ // TODO(nasko,creis): The check whether data: or about: URLs are allowed
+ // to commit in the current process should be in HasWrongProcessForURL.
+ // However, making this change has further implications and needs more
+ // investigation of what behavior changes. For now, use a conservative
+ // approach and explicitly check before calling HasWrongProcessForURL.
+ SiteInstanceImpl* dest_instance_impl =
+ static_cast<SiteInstanceImpl*>(dest_instance);
+ if (IsDataOrAbout(dest_url) ||
+ !dest_instance_impl->HasWrongProcessForURL(dest_url)) {
+ // If we are forcing a swap, this should be in a different
+ // BrowsingInstance.
+ if (force_browsing_instance_swap) {
+ CHECK(!dest_instance->IsRelatedSiteInstance(
+ render_frame_host_->GetSiteInstance()));
+ }
+ return SiteInstanceDescriptor(dest_instance);
+ }
}
- return SiteInstanceDescriptor(dest_instance);
}
// If a swap is required, we need to force the SiteInstance AND
@@ -1263,11 +1308,7 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
// redirect arbitary requests to those URLs using webRequest or
// declarativeWebRequest API. For these cases, the content isn't controlled
// by the source SiteInstance, so it need not use it.
- GURL about_srcdoc(content::kAboutSrcDocURL);
- bool dest_is_data_or_about = dest_url == about_srcdoc ||
- dest_url.IsAboutBlank() ||
- dest_url.scheme() == url::kDataScheme;
- if (source_instance && dest_is_data_or_about && !was_server_redirect)
+ if (source_instance && IsDataOrAbout(dest_url) && !was_server_redirect)
return SiteInstanceDescriptor(source_instance);
// Use the current SiteInstance for same site navigations.
@@ -1641,7 +1682,8 @@ RenderFrameHostManager::CreateRenderFrameHost(
RenderViewHostImpl* render_view_host = nullptr;
if (frame_tree_node_->IsMainFrame()) {
render_view_host = frame_tree->CreateRenderViewHost(
- site_instance, view_routing_id, frame_routing_id, false, hidden);
+ site_instance, view_routing_id, frame_routing_id, widget_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
@@ -1652,8 +1694,9 @@ RenderFrameHostManager::CreateRenderFrameHost(
// if just ignored, should be an easy cleanup once RenderViewHostImpl has-a
// RenderWidgetHostImpl. https://crbug.com/545684
if (view_routing_id == MSG_ROUTING_NONE) {
- widget_routing_id = render_view_host->GetRoutingID();
+ widget_routing_id = render_view_host->GetWidget()->GetRoutingID();
} else {
+ DCHECK_NE(view_routing_id, widget_routing_id);
DCHECK_EQ(view_routing_id, render_view_host->GetRoutingID());
}
} else {
@@ -1718,6 +1761,10 @@ std::unique_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
// A RenderFrame in a different process from its parent RenderFrame
// requires a RenderWidget for input/layout/painting.
+ //
+ // TODO(ajwong): When RVH no longer owns a RWH, this logic should be
+ // simplified as the decision to create a RWH will be centralized here.
+ // https://crbug.com/545684
if (frame_tree_node_->parent() &&
frame_tree_node_->parent()->current_frame_host()->GetSiteInstance() !=
instance) {
@@ -1796,7 +1843,8 @@ int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
if (!render_view_host) {
CHECK(frame_tree_node_->IsMainFrame());
render_view_host = frame_tree_node_->frame_tree()->CreateRenderViewHost(
- instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, true, true);
+ instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, MSG_ROUTING_NONE, true,
+ true);
}
proxy = CreateRenderFrameProxyHost(instance, render_view_host);
@@ -1936,7 +1984,7 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
// allowed to swap processes.
no_renderer_swap_allowed |= !CanSubframeSwapProcess(
request.common_params().url, request.source_site_instance(),
- request.dest_site_instance(), was_server_redirect);
+ request.dest_site_instance());
}
if (no_renderer_swap_allowed)
@@ -2508,8 +2556,7 @@ void RenderFrameHostManager::SendPageMessage(IPC::Message* msg,
bool RenderFrameHostManager::CanSubframeSwapProcess(
const GURL& dest_url,
SiteInstance* source_instance,
- SiteInstance* dest_instance,
- bool was_server_redirect) {
+ SiteInstance* dest_instance) {
// On renderer-initiated navigations, when the frame initiating the navigation
// and the frame being navigated differ, |source_instance| is set to the
// SiteInstance of the initiating frame. |dest_instance| is present on session
@@ -2526,22 +2573,25 @@ bool RenderFrameHostManager::CanSubframeSwapProcess(
resolved_url = dest_instance->GetSiteURL();
} else {
// If there is no SiteInstance this unique origin can be associated with,
- // there are two cases:
- // (1) If there was a server redirect, allow a process swap. Normally,
- // redirects to data: or about: URLs are disallowed as
+ // then check whether it is safe to put into the parent frame's process.
+ // This is the case for about:blank URLs (with or without fragments),
+ // since they contain no active data. This is also the case for
+ // about:srcdoc, since such URLs only get active content from their parent
+ // frame. Using the parent frame's process avoids putting blank frames
+ // into OOPIFs and preserves scripting for about:srcdoc.
+ //
+ // Allow a process swap for other unique origin URLs, such as data: URLs.
+ // These have active content and may have come from an untrusted source,
+ // such as a restored frame from a different site or a redirect.
+ // (Normally, redirects to data: or about: URLs are disallowed as
// net::ERR_UNSAFE_REDIRECT. However, extensions can still redirect
// arbitary requests to those URLs using the chrome.webRequest or
// chrome.declarativeWebRequest API, which will end up here (for an
- // example, see ExtensionWebRequestApiTest.WebRequestDeclarative1). It's
- // safest to swap processes for those redirects if we are in an
- // appropriate OOPIF-enabled mode.
- //
- // (2) Otherwise, avoid a process swap. We can get here during session
- // restore, and this avoids putting all data: and about:blank subframes
- // in OOPIFs. We can also get here in tests with browser-initiated
- // subframe navigations (NavigateFrameToURL).
- if (!was_server_redirect)
+ // example, see ExtensionWebRequestApiTest.WebRequestDeclarative1).)
+ if (resolved_url.IsAboutBlank() ||
+ resolved_url == GURL(content::kAboutSrcDocURL)) {
return false;
+ }
}
}
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 e53920fc916..d8cf377f4e2 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.h
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.h
@@ -22,6 +22,7 @@
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/common/referrer.h"
+#include "third_party/blink/public/common/frame/user_activation_update_type.h"
#include "ui/base/page_transition_types.h"
#include "url/origin.h"
@@ -139,8 +140,8 @@ class CONTENT_EXPORT RenderFrameHostManager
// TODO(nasko): This should be removed once extensions no longer use
// NotificationService. See https://crbug.com/462682.
virtual void NotifyMainFrameSwappedFromRenderManager(
- RenderViewHost* old_host,
- RenderViewHost* new_host) = 0;
+ RenderFrameHost* old_host,
+ RenderFrameHost* new_host) = 0;
virtual NavigationControllerImpl&
GetControllerForRenderManager() = 0;
@@ -467,7 +468,10 @@ class CONTENT_EXPORT RenderFrameHostManager
// match the provided |render_frame_host|.
void CancelPendingIfNecessary(RenderFrameHostImpl* render_frame_host);
- void OnSetHasReceivedUserGesture();
+ // Updates the user activation state in all proxies of this frame. For
+ // more details, see the comment on FrameTreeNode::user_activation_state_.
+ void UpdateUserActivationState(blink::UserActivationUpdateType update_type);
+
void OnSetHasReceivedUserGestureBeforeNavigation(bool value);
// Sets up the necessary state for a new RenderViewHost. If |proxy| is not
@@ -561,7 +565,8 @@ class CONTENT_EXPORT RenderFrameHostManager
bool current_is_view_source_mode,
SiteInstance* new_site_instance,
const GURL& new_effective_url,
- bool new_is_view_source_mode) const;
+ bool new_is_view_source_mode,
+ bool is_failure) const;
// Returns the SiteInstance to use for the navigation.
scoped_refptr<SiteInstance> GetSiteInstanceForNavigation(
@@ -725,8 +730,7 @@ class CONTENT_EXPORT RenderFrameHostManager
// Returns true if a subframe can navigate cross-process.
bool CanSubframeSwapProcess(const GURL& dest_url,
SiteInstance* source_instance,
- SiteInstance* dest_instance,
- bool was_server_redirect);
+ SiteInstance* dest_instance);
// After a renderer process crash we'd have marked the host as invisible, so
// we need to set the visibility of the new View to the correct value here
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 0828c4263a3..c49de36a819 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
@@ -50,10 +50,12 @@
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/test_navigation_throttle_inserter.h"
#include "content/public/test/test_utils.h"
#include "content/public/test/url_loader_interceptor.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 "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -651,8 +653,9 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Test for crbug.com/116192. Targeted links should still work after the
// named target window has swapped processes.
+// Disabled Flaky test - crbug.com/859487
IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
- AllowTargetedNavigationsAfterSwap) {
+ DISABLED_AllowTargetedNavigationsAfterSwap) {
StartEmbeddedServer();
// Load a page with links that open in a new window.
@@ -1247,7 +1250,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// The original process should still be alive, since it is still used in the
// first window.
RenderProcessHost* orig_process = orig_site_instance->GetProcess();
- EXPECT_TRUE(orig_process->HasConnection());
+ EXPECT_TRUE(orig_process->IsInitializedAndNotDead());
// Navigate the first window to a different site as well. The original
// process should exit, since all of its views are now swapped out.
@@ -1745,7 +1748,7 @@ IN_PROC_BROWSER_TEST_F(
"</html>");
first_redirect_response.Done();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
- EXPECT_EQ(kFirstRedirectURL, shell()->web_contents()->GetVisibleURL());
+ EXPECT_EQ(kFirstRedirectURL, shell()->web_contents()->GetLastCommittedURL());
// Now reload the original request, but redirect to yet another site.
TestNavigationManager first_reload(shell()->web_contents(), kOriginalURL);
@@ -1771,19 +1774,24 @@ IN_PROC_BROWSER_TEST_F(
first_reload.ResumeNavigation();
// The navigation is ready to commit: it has been handed to the speculative
- // RenderFrameHost for commit.
+ // RenderFrameHost for commit if Site Isolation is enabled, otherwise it
+ // commits in the same RenderFrameHost.
RenderFrameHostImpl* speculative_rfh =
static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root()
->render_manager()
->speculative_frame_host();
- CHECK(speculative_rfh);
- EXPECT_TRUE(speculative_rfh->is_loading());
+ if (AreAllSitesIsolatedForTesting()) {
+ CHECK(speculative_rfh);
+ } else {
+ CHECK(!speculative_rfh);
+ }
// The user requests a new reload while the previous reload hasn't committed
// yet. The navigation start deletes the speculative RenderFrameHost that was
- // supposed to commit the browser-initiated navigation. This should not crash.
+ // supposed to commit the browser-initiated navigation, unless Site Isolation
+ // is enabled. This should not crash.
TestNavigationManager second_reload(shell()->web_contents(), kOriginalURL);
shell()->web_contents()->GetController().Reload(
ReloadType::ORIGINAL_REQUEST_URL, false);
@@ -1793,7 +1801,11 @@ IN_PROC_BROWSER_TEST_F(
->root()
->render_manager()
->speculative_frame_host();
- EXPECT_FALSE(speculative_rfh);
+ if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_TRUE(speculative_rfh);
+ } else {
+ EXPECT_FALSE(speculative_rfh);
+ }
// The second reload results in a 204.
second_reload.ResumeNavigation();
@@ -1815,7 +1827,7 @@ IN_PROC_BROWSER_TEST_F(
// navigation to the pending NavigationEntry will not crash if it happens
// because a new navigation to the same pending NavigationEntry started. This
// is a variant of the previous test, where we destroy the speculative
-// RenderFrameHost to create another speculative RenderFrameHost.This is a
+// RenderFrameHost to create another speculative RenderFrameHost. This is a
// regression test for crbug.com/796135.
IN_PROC_BROWSER_TEST_F(
RenderFrameHostManagerTest,
@@ -1837,6 +1849,11 @@ IN_PROC_BROWSER_TEST_F(
const GURL kCrossSiteURL =
embedded_test_server()->GetURL("c.com", "/title1.html");
+ const GURL kOriginalSiteURL = SiteInstance::GetSiteForURL(
+ shell()->web_contents()->GetBrowserContext(), kOriginalURL);
+ const GURL kRedirectSiteURL = SiteInstance::GetSiteForURL(
+ shell()->web_contents()->GetBrowserContext(), kRedirectURL);
+
// First navigate to the initial URL.
shell()->LoadURL(kOriginalURL);
original_response1.WaitForRequest();
@@ -1852,7 +1869,7 @@ IN_PROC_BROWSER_TEST_F(
"</html>");
original_response1.Done();
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
- EXPECT_EQ(kOriginalURL, shell()->web_contents()->GetVisibleURL());
+ EXPECT_EQ(kOriginalURL, shell()->web_contents()->GetLastCommittedURL());
// Navigate cross-site.
NavigateToURL(shell(), kCrossSiteURL);
@@ -1889,6 +1906,13 @@ IN_PROC_BROWSER_TEST_F(
->speculative_frame_host();
CHECK(speculative_rfh);
EXPECT_TRUE(speculative_rfh->is_loading());
+ if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_EQ(kRedirectSiteURL,
+ speculative_rfh->GetSiteInstance()->GetSiteURL());
+ } else {
+ EXPECT_EQ(kOriginalSiteURL,
+ speculative_rfh->GetSiteInstance()->GetSiteURL());
+ }
int site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
// The user starts a navigation towards the redirected URL, for which we have
@@ -1904,7 +1928,9 @@ IN_PROC_BROWSER_TEST_F(
->render_manager()
->speculative_frame_host();
CHECK(speculative_rfh);
- EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
+ EXPECT_EQ(kRedirectSiteURL, speculative_rfh->GetSiteInstance()->GetSiteURL());
+ if (AreAllSitesIsolatedForTesting())
+ EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
// The user requests to go back again while the previous back hasn't committed
// yet. This should delete the speculative RenderFrameHost trying to commit
@@ -1919,7 +1945,9 @@ IN_PROC_BROWSER_TEST_F(
->render_manager()
->speculative_frame_host();
CHECK(speculative_rfh);
- EXPECT_NE(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
+ EXPECT_EQ(kOriginalSiteURL, speculative_rfh->GetSiteInstance()->GetSiteURL());
+ if (AreAllSitesIsolatedForTesting())
+ EXPECT_NE(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
}
// Test for crbug.com/9682. We should not show the URL for a pending renderer-
@@ -4081,6 +4109,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
GURL error_url(embedded_test_server()->GetURL("/empty.html"));
std::unique_ptr<URLLoaderInterceptor> url_interceptor =
SetupRequestFailForURL(error_url);
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
// Start with a successful navigation to a document.
EXPECT_TRUE(NavigateToURL(shell(), url));
@@ -4105,7 +4134,6 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_EQ(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL());
// Verify that the error page process is locked to origin
- auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
EXPECT_EQ(
GURL(kUnreachableWebDataURL),
policy->GetOriginLock(error_site_instance->GetProcess()->GetID()));
@@ -4116,6 +4144,10 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_TRUE(NavigateToURL(shell(), url));
success_site_instance =
shell()->web_contents()->GetMainFrame()->GetSiteInstance();
+ EXPECT_NE(
+ GURL(kUnreachableWebDataURL),
+ policy->GetOriginLock(
+ shell()->web_contents()->GetSiteInstance()->GetProcess()->GetID()));
{
NavigationHandleObserver observer(shell()->web_contents(), error_url);
@@ -4134,6 +4166,11 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_NE(success_site_instance->GetProcess()->GetID(),
error_site_instance->GetProcess()->GetID());
EXPECT_EQ(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL());
+
+ // Verify that the error page process is locked to origin
+ EXPECT_EQ(
+ GURL(kUnreachableWebDataURL),
+ policy->GetOriginLock(error_site_instance->GetProcess()->GetID()));
}
}
@@ -4206,6 +4243,11 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
new_shell->web_contents()->GetMainFrame()->GetSiteInstance();
EXPECT_NE(main_site_instance, error_site_instance);
EXPECT_EQ(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL());
+
+ // Verify that the error page process is locked to origin
+ EXPECT_EQ(GURL(kUnreachableWebDataURL),
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
+ error_site_instance->GetProcess()->GetID()));
}
// Test to verify that windows that are not part of the same
@@ -4253,6 +4295,446 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
new_shell->web_contents()->GetSiteInstance()));
EXPECT_EQ(shell()->web_contents()->GetSiteInstance()->GetProcess(),
new_shell->web_contents()->GetSiteInstance()->GetProcess());
+
+ // Verify that the process is locked to origin
+ EXPECT_EQ(
+ GURL(kUnreachableWebDataURL),
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
+ shell()->web_contents()->GetSiteInstance()->GetProcess()->GetID()));
+}
+
+// Test to verify that reloading an error page once the error condition has
+// cleared up is successful and does not create a new navigation entry.
+// See https://crbug.com/840485.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ErrorPageNavigationReload) {
+ // This test is only valid if error page isolation is enabled.
+ if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(true))
+ return;
+
+ StartEmbeddedServer();
+ GURL start_url(embedded_test_server()->GetURL("/title1.html"));
+ GURL error_url(embedded_test_server()->GetURL("/empty.html"));
+ GURL end_url(embedded_test_server()->GetURL("/title2.html"));
+ NavigationControllerImpl& nav_controller =
+ static_cast<NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+
+ // Build session history with three entries, where the middle one will be
+ // tested for successful and failed reloads. This allows checking whether
+ // reload accidentally clears the forward session history if it is
+ // incorrectly classified.
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+ EXPECT_TRUE(NavigateToURL(shell(), error_url));
+ EXPECT_TRUE(NavigateToURL(shell(), end_url));
+ {
+ TestNavigationObserver back_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_observer.Wait();
+ EXPECT_TRUE(back_observer.last_navigation_succeeded());
+ }
+ EXPECT_EQ(3, nav_controller.GetEntryCount());
+ EXPECT_EQ(1, nav_controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(error_url, shell()->web_contents()->GetLastCommittedURL());
+
+ scoped_refptr<SiteInstance> success_site_instance =
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance();
+
+ // Install an interceptor which will cause network failure for |error_url|,
+ // reload the existing entry and verify.
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
+ SetupRequestFailForURL(error_url);
+ {
+ TestNavigationObserver reload_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false);
+ reload_observer.Wait();
+ EXPECT_FALSE(reload_observer.last_navigation_succeeded());
+ // TODO(nasko): Investigate making a failing reload of a successful
+ // navigation be classified as NEW_PAGE instead, since with error page
+ // isolation it involves a SiteInstance swap.
+ EXPECT_EQ(NavigationType::NAVIGATION_TYPE_EXISTING_PAGE,
+ reload_observer.last_navigation_type());
+ }
+ EXPECT_EQ(3, nav_controller.GetEntryCount());
+ EXPECT_EQ(1, nav_controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(
+ GURL(kUnreachableWebDataURL),
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ int process_id =
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
+ EXPECT_EQ(GURL(kUnreachableWebDataURL), policy->GetOriginLock(process_id));
+
+ // Reload while it will still fail to ensure it stays in the same process.
+ {
+ TestNavigationObserver reload_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false);
+ reload_observer.Wait();
+ EXPECT_FALSE(reload_observer.last_navigation_succeeded());
+ EXPECT_EQ(NavigationType::NAVIGATION_TYPE_EXISTING_PAGE,
+ reload_observer.last_navigation_type());
+ }
+ EXPECT_EQ(process_id,
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetID());
+
+ // Reload the error page after clearing the error condition, such that the
+ // navigation is successful and verify that no new entry was added to
+ // session history and forward history is not pruned.
+ url_interceptor.reset();
+ {
+ TestNavigationObserver reload_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false);
+ reload_observer.Wait();
+ EXPECT_TRUE(reload_observer.last_navigation_succeeded());
+ // The successful reload should be classified as a NEW_PAGE navigation
+ // with replacement, since it needs to stay at the same entry in session
+ // history, but needs a new entry because of the change in SiteInstance.
+ EXPECT_EQ(NavigationType::NAVIGATION_TYPE_NEW_PAGE,
+ reload_observer.last_navigation_type());
+ }
+ EXPECT_EQ(3, nav_controller.GetEntryCount());
+ EXPECT_EQ(1, nav_controller.GetLastCommittedEntryIndex());
+ EXPECT_NE(
+ GURL(kUnreachableWebDataURL),
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_NE(
+ GURL(kUnreachableWebDataURL),
+ policy->GetOriginLock(
+ shell()->web_contents()->GetSiteInstance()->GetProcess()->GetID()));
+
+ // Test the same scenario as above, but this time initiated by the
+ // renderer process.
+ url_interceptor = SetupRequestFailForURL(error_url);
+ {
+ TestNavigationObserver reload_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false);
+ reload_observer.Wait();
+ EXPECT_FALSE(reload_observer.last_navigation_succeeded());
+ // TODO(nasko): Investigate making a failing reload of a successful
+ // navigation be classified as NEW_PAGE instead, since with error page
+ // isolation it involves a SiteInstance swap.
+ EXPECT_EQ(NavigationType::NAVIGATION_TYPE_EXISTING_PAGE,
+ reload_observer.last_navigation_type());
+ }
+ EXPECT_EQ(3, nav_controller.GetEntryCount());
+ EXPECT_EQ(1, nav_controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(
+ GURL(kUnreachableWebDataURL),
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_EQ(
+ GURL(kUnreachableWebDataURL),
+ policy->GetOriginLock(
+ shell()->web_contents()->GetSiteInstance()->GetProcess()->GetID()));
+
+ url_interceptor.reset();
+ {
+ TestNavigationObserver reload_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell(), "location.reload();"));
+ reload_observer.Wait();
+ EXPECT_TRUE(reload_observer.last_navigation_succeeded());
+ // TODO(nasko): Investigate making renderer initiated reloads that change
+ // SiteInstance be classified as NEW_PAGE as well.
+ EXPECT_EQ(NavigationType::NAVIGATION_TYPE_EXISTING_PAGE,
+ reload_observer.last_navigation_type());
+ }
+ EXPECT_EQ(3, nav_controller.GetEntryCount());
+ EXPECT_EQ(1, nav_controller.GetLastCommittedEntryIndex());
+ EXPECT_NE(
+ GURL(kUnreachableWebDataURL),
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_NE(
+ GURL(kUnreachableWebDataURL),
+ policy->GetOriginLock(
+ shell()->web_contents()->GetSiteInstance()->GetProcess()->GetID()));
+}
+
+// Test to verify that navigating away from an error page results in correct
+// change in SiteInstance.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ ErrorPageNavigationAfterError) {
+ // This test is only valid if error page isolation is enabled.
+ if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(true))
+ return;
+
+ StartEmbeddedServer();
+ GURL url(embedded_test_server()->GetURL("/title1.html"));
+ GURL error_url(embedded_test_server()->GetURL("/empty.html"));
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
+ SetupRequestFailForURL(error_url);
+ NavigationControllerImpl& nav_controller =
+ static_cast<NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+
+ // Start with a successful navigation to a document.
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ scoped_refptr<SiteInstance> success_site_instance =
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance();
+ EXPECT_EQ(1, nav_controller.GetEntryCount());
+
+ // Navigate to an url resulting in an error page.
+ EXPECT_FALSE(NavigateToURL(shell(), error_url));
+ EXPECT_EQ(
+ GURL(kUnreachableWebDataURL),
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_EQ(
+ GURL(kUnreachableWebDataURL),
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
+ shell()->web_contents()->GetSiteInstance()->GetProcess()->GetID()));
+ EXPECT_EQ(2, nav_controller.GetEntryCount());
+
+ // Navigate again to the initial successful document, expecting a new
+ // navigation and new SiteInstance.
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ EXPECT_NE(
+ GURL(kUnreachableWebDataURL),
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_EQ(
+ success_site_instance->GetSiteURL(),
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_NE(success_site_instance,
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance());
+ EXPECT_EQ(3, nav_controller.GetEntryCount());
+
+ // Repeat again using a renderer-initiated navigation for the successful one.
+ EXPECT_FALSE(NavigateToURL(shell(), error_url));
+ EXPECT_EQ(
+ GURL(kUnreachableWebDataURL),
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_EQ(
+ GURL(kUnreachableWebDataURL),
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
+ shell()->web_contents()->GetSiteInstance()->GetProcess()->GetID()));
+ EXPECT_EQ(4, nav_controller.GetEntryCount());
+ {
+ TestNavigationObserver observer(shell()->web_contents());
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "location.href = '" + url.spec() + "';"));
+ observer.Wait();
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ }
+ EXPECT_EQ(5, nav_controller.GetEntryCount());
+ EXPECT_NE(
+ GURL(kUnreachableWebDataURL),
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+}
+
+// Test to verify that when an error page is hit and its process is terminated,
+// a successful reload correctly commits in a different process.
+// See https://crbug.com/866549.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ ErrorPageNavigationReloadWithTerminatedProcess) {
+ // This test is only valid if error page isolation is enabled.
+ if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(true))
+ return;
+
+ StartEmbeddedServer();
+ GURL url(embedded_test_server()->GetURL("/title1.html"));
+ GURL error_url(embedded_test_server()->GetURL("/empty.html"));
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
+ SetupRequestFailForURL(error_url);
+ WebContents* web_contents = shell()->web_contents();
+ NavigationControllerImpl& nav_controller =
+ static_cast<NavigationControllerImpl&>(web_contents->GetController());
+
+ // Start with a successful navigation to a document.
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ scoped_refptr<SiteInstance> success_site_instance =
+ web_contents->GetMainFrame()->GetSiteInstance();
+ EXPECT_EQ(1, nav_controller.GetEntryCount());
+
+ // Navigate to an url resulting in an error page.
+ EXPECT_FALSE(NavigateToURL(shell(), error_url));
+ EXPECT_EQ(GURL(kUnreachableWebDataURL),
+ web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL());
+ EXPECT_EQ(GURL(kUnreachableWebDataURL),
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
+ web_contents->GetSiteInstance()->GetProcess()->GetID()));
+ EXPECT_EQ(2, nav_controller.GetEntryCount());
+
+ // Terminate the renderer process.
+ {
+ RenderProcessHostWatcher termination_observer(
+ web_contents->GetMainFrame()->GetProcess(),
+ RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ web_contents->GetMainFrame()->GetProcess()->Shutdown(0);
+ termination_observer.Wait();
+ }
+
+ // Clear the interceptor so the navigation will succeed on reload.
+ url_interceptor.reset();
+
+ // Reload the URL and execute a Javascript statement to verify that the
+ // renderer process is still around and responsive.
+ TestNavigationObserver reload_observer(shell()->web_contents());
+ nav_controller.Reload(ReloadType::NORMAL, false);
+ reload_observer.Wait();
+ EXPECT_TRUE(reload_observer.last_navigation_succeeded());
+
+ std::string result;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ shell(), "window.domAutomationController.send(location.href);", &result));
+ EXPECT_EQ(error_url.spec(), result);
+}
+
+// A NavigationThrottle implementation that blocks all outgoing navigation
+// requests for a specific WebContents. It is used to block navigations to
+// WebUI URLs in the following test.
+class RequestBlockingNavigationThrottle : public NavigationThrottle {
+ public:
+ explicit RequestBlockingNavigationThrottle(NavigationHandle* handle)
+ : NavigationThrottle(handle) {}
+
+ static std::unique_ptr<NavigationThrottle> Create(NavigationHandle* handle) {
+ return std::make_unique<RequestBlockingNavigationThrottle>(handle);
+ }
+
+ private:
+ ThrottleCheckResult WillStartRequest() override {
+ return NavigationThrottle::BLOCK_REQUEST;
+ }
+
+ const char* GetNameForLogging() override {
+ return "RequestBlockingNavigationThrottle";
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(RequestBlockingNavigationThrottle);
+};
+
+// Test to verify that navigations to WebUI URL which results in an error
+// commits properly in the error page process and does not give it WebUI
+// bindings.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ ErrorPageNavigationToWebUIResourceWithError) {
+ // This test is only valid if error page isolation is enabled.
+ if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(true))
+ return;
+
+ StartEmbeddedServer();
+ GURL webui_url = GURL(std::string(kChromeUIScheme) + "://" +
+ std::string(kChromeUIGpuHost));
+ GURL error_url(webui_url.Resolve("/foo"));
+
+ // Navigate to the main WebUI URL and ensure it is successful.
+ EXPECT_TRUE(NavigateToURL(shell(), webui_url));
+
+ // Ensure that the subsequent navigation is blocked, resulting in an
+ // error.
+ TestNavigationThrottleInserter throttle_inserter(
+ shell()->web_contents(),
+ base::BindRepeating(&RequestBlockingNavigationThrottle::Create));
+
+ // Navigate to an error URL and verify the error page process does not get
+ // WebUI bindings.
+ NavigationHandleObserver observer(shell()->web_contents(), error_url);
+ EXPECT_FALSE(NavigateToURL(shell(), error_url));
+ scoped_refptr<SiteInstance> error_site_instance =
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance();
+ EXPECT_TRUE(observer.is_error());
+ EXPECT_EQ(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL());
+ EXPECT_EQ(GURL(kUnreachableWebDataURL),
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
+ error_site_instance->GetProcess()->GetID()));
+ EXPECT_FALSE(ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
+ error_site_instance->GetProcess()->GetID()));
+}
+
+// A test ContentBrowserClient implementation which enforces
+// BrowsingInstance swap on every navigation. It is used to verify that
+// reloading of an error page to an URL that requires BrowsingInstance swap
+// works correctly.
+class BrowsingInstanceSwapContentBrowserClient
+ : public TestContentBrowserClient {
+ public:
+ BrowsingInstanceSwapContentBrowserClient() = default;
+
+ bool ShouldIsolateErrorPage(bool in_main_frame) override {
+ return in_main_frame;
+ }
+
+ bool ShouldSwapBrowsingInstancesForNavigation(
+ content::SiteInstance* site_instance,
+ const GURL& current_url,
+ const GURL& new_url) override {
+ return true;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BrowsingInstanceSwapContentBrowserClient);
+};
+
+// Test to verify that reloading of an error page which resulted from a
+// navigation to an URL which requires a BrowsingInstance swap, correcly
+// reloads in the same SiteInstance for the error page.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ ErrorPageNavigationReloadBrowsingInstanceSwap) {
+ StartEmbeddedServer();
+ GURL url(embedded_test_server()->GetURL("/title1.html"));
+ GURL error_url(embedded_test_server()->GetURL("/empty.html"));
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
+ SetupRequestFailForURL(error_url);
+ NavigationControllerImpl& nav_controller =
+ static_cast<NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+
+ // Start with a successful navigation to a document and verify there is
+ // only one entry in session history.
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ scoped_refptr<SiteInstance> success_site_instance =
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance();
+ EXPECT_EQ(1, nav_controller.GetEntryCount());
+
+ BrowsingInstanceSwapContentBrowserClient content_browser_client;
+ ContentBrowserClient* old_client =
+ SetBrowserClientForTesting(&content_browser_client);
+
+ // Navigate to an url resulting in an error page and ensure a new entry
+ // was added to session history.
+ EXPECT_FALSE(NavigateToURL(shell(), error_url));
+ EXPECT_EQ(2, nav_controller.GetEntryCount());
+
+ scoped_refptr<SiteInstance> initial_instance =
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance();
+ EXPECT_EQ(GURL(kUnreachableWebDataURL), initial_instance->GetSiteURL());
+ EXPECT_TRUE(
+ success_site_instance->IsRelatedSiteInstance(initial_instance.get()));
+
+ // Reload of the error page that still results in an error should stay in
+ // the same SiteInstance. Ensure this works for both browser-initiated
+ // reloads and renderer-initiated ones.
+ {
+ TestNavigationObserver reload_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false);
+ reload_observer.Wait();
+ EXPECT_FALSE(reload_observer.last_navigation_succeeded());
+ EXPECT_EQ(2, nav_controller.GetEntryCount());
+ EXPECT_EQ(initial_instance,
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance());
+ }
+ {
+ TestNavigationObserver reload_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell(), "location.reload();"));
+ reload_observer.Wait();
+ EXPECT_FALSE(reload_observer.last_navigation_succeeded());
+ EXPECT_EQ(2, nav_controller.GetEntryCount());
+ EXPECT_EQ(initial_instance,
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance());
+ }
+
+ // Allow the navigation to succeed and ensure it swapped to a non-related
+ // SiteInstance.
+ url_interceptor.reset();
+ {
+ TestNavigationObserver reload_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell(), "location.reload();"));
+ reload_observer.Wait();
+ EXPECT_TRUE(reload_observer.last_navigation_succeeded());
+ EXPECT_EQ(2, nav_controller.GetEntryCount());
+ EXPECT_FALSE(initial_instance->IsRelatedSiteInstance(
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance()));
+ EXPECT_FALSE(success_site_instance->IsRelatedSiteInstance(
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance()));
+ }
+
+ SetBrowserClientForTesting(old_client);
}
// Helper class to simplify testing of unload handlers. It allows waiting for
@@ -4472,4 +4954,51 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerUnloadBrowserTest,
process_exit_observer.Wait();
}
+// Verify that when an OOPIF with an unload handler navigates cross-process,
+// its unload handler is able to send a postMessage to the parent frame.
+// See https://crbug.com/857274.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerUnloadBrowserTest,
+ PostMessageToParentWhenSubframeNavigates) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ FrameTreeNode* child = root->child_at(0);
+
+ // Add an onmessage listener in the main frame.
+ EXPECT_TRUE(ExecuteScript(root, R"(
+ window.addEventListener('message', function(e) {
+ domAutomationController.send(e.data);
+ });)"));
+
+ // Add an unload handler in the child frame to send a postMessage to the
+ // parent frame.
+ AddUnloadHandler(child->current_frame_host(),
+ "parent.postMessage('foo', '*')");
+
+ // Navigate the subframe cross-site to c.com and wait for the message.
+ GURL c_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ std::string message;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ root,
+ base::StringPrintf("document.querySelector('iframe').src = '%s';",
+ c_url.spec().c_str()),
+ &message));
+ EXPECT_EQ("foo", message);
+
+ // Now repeat the test with a remote-to-local navigation that brings the
+ // subframe back to a.com.
+ AddUnloadHandler(child->current_frame_host(),
+ "parent.postMessage('bar', '*')");
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title2.html"));
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ root,
+ base::StringPrintf("document.querySelector('iframe').src = '%s';",
+ a_url.spec().c_str()),
+ &message));
+ EXPECT_EQ("bar", message);
+}
+
} // 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 e1c1162d38b..b4fb251d110 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -17,7 +17,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -131,12 +131,13 @@ class RenderFrameHostManagerTestWebUIControllerFactory
}
// WebUIFactory implementation.
- WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
- const GURL& url) const override {
+ std::unique_ptr<WebUIController> CreateWebUIControllerForURL(
+ WebUI* web_ui,
+ const GURL& url) const override {
// If WebUI creation is enabled for the test and this is a WebUI URL,
// returns a new instance.
if (should_create_webui_ && HasWebUIScheme(url))
- return new WebUIController(web_ui);
+ return std::make_unique<WebUIController>(web_ui);
return nullptr;
}
@@ -391,11 +392,10 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
bool current_is_view_source_mode = current_entry ?
current_entry->IsViewSourceMode() : new_entry->IsViewSourceMode();
return manager->ShouldSwapBrowsingInstancesForNavigation(
- current_effective_url,
- current_is_view_source_mode,
+ current_effective_url, current_is_view_source_mode,
new_entry->site_instance(),
SiteInstanceImpl::GetEffectiveURL(browser_context, new_entry->GetURL()),
- new_entry->IsViewSourceMode());
+ new_entry->IsViewSourceMode(), false);
}
// Creates a test RenderViewHost that's swapped out.
@@ -837,11 +837,18 @@ TEST_F(RenderFrameHostManagerTest, AlwaysSendEnableViewSourceMode) {
kViewSourceUrl, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
+ NavigationRequest* request =
+ main_test_rfh()->frame_tree_node()->navigation_request();
+ CHECK(request);
+
// Simulate response from RenderFrame for DispatchBeforeUnload.
contents()->GetMainFrame()->PrepareForCommit();
ASSERT_TRUE(contents()->GetPendingMainFrame())
<< "Expected new pending RenderFrameHost to be created.";
RenderFrameHost* last_rfh = contents()->GetPendingMainFrame();
+ contents()->GetPendingMainFrame()->SimulateCommitProcessed(
+ request->navigation_handle()->GetNavigationId(),
+ true /* was_successful */);
contents()->GetPendingMainFrame()->SendNavigate(entry_id, true, kUrl);
EXPECT_EQ(1, controller().GetLastCommittedEntryIndex());
@@ -860,6 +867,8 @@ TEST_F(RenderFrameHostManagerTest, AlwaysSendEnableViewSourceMode) {
// Navigate, again.
controller().LoadURL(
kViewSourceUrl, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ request = main_test_rfh()->frame_tree_node()->navigation_request();
+ CHECK(request);
entry_id = controller().GetPendingEntry()->GetUniqueID();
contents()->GetMainFrame()->PrepareForCommit();
@@ -868,6 +877,9 @@ TEST_F(RenderFrameHostManagerTest, AlwaysSendEnableViewSourceMode) {
EXPECT_EQ(last_rfh, contents()->GetMainFrame());
// The renderer sends a commit.
+ contents()->GetMainFrame()->SimulateCommitProcessed(
+ request->navigation_handle()->GetNavigationId(),
+ true /* was_successful */);
contents()->GetMainFrame()->SendNavigateWithTransition(
entry_id, false, kUrl, ui::PAGE_TRANSITION_TYPED);
EXPECT_EQ(1, controller().GetLastCommittedEntryIndex());
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 91bf248a67a..2f32390f0b4 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.cc
@@ -35,6 +35,7 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_constants.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/cookies/canonical_cookie.h"
@@ -66,10 +67,6 @@ namespace content {
namespace {
-#if BUILDFLAG(ENABLE_PLUGINS)
-const int kPluginsRefreshThresholdInSeconds = 3;
-#endif
-
void CreateChildFrameOnUI(
int process_id,
int parent_routing_id,
@@ -129,6 +126,29 @@ void DownloadUrlOnUIThread(
std::move(blob_url_loader_factory));
}
+// With network service disabled the downloads code wouldn't know what to do
+// with a BlobURLToken, so this method is used to convert from a token to a
+// BlobDataHandle to be passed on to the rest of the downloads system.
+void DownloadBlobURLFromToken(
+ std::unique_ptr<download::DownloadUrlParameters> params,
+ blink::mojom::BlobURLTokenPtr,
+ const base::WeakPtr<storage::BlobStorageContext>& context,
+ const base::UnguessableToken& token) {
+ std::unique_ptr<storage::BlobDataHandle> blob_handle;
+ GURL blob_url;
+ if (context) {
+ std::string uuid;
+ if (context->registry().GetTokenMapping(token, &blob_url, &uuid) &&
+ blob_url == params->url()) {
+ blob_handle = context->GetBlobDataFromUUID(uuid);
+ }
+ }
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&DownloadUrlOnUIThread, std::move(params),
+ std::move(blob_handle), nullptr));
+}
+
// Common functionality for converting a sync renderer message to a callback
// function in the browser. Derive from this, create it on the heap when
// issuing your callback. When done, write your reply parameters into
@@ -288,7 +308,6 @@ bool RenderFrameMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER_GENERIC(FrameHostMsg_RenderProcessGone,
OnRenderProcessGone())
#if BUILDFLAG(ENABLE_PLUGINS)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_GetPlugins, OnGetPlugins)
IPC_MESSAGE_HANDLER(FrameHostMsg_GetPluginInfo, OnGetPluginInfo)
IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_OpenChannelToPepperPlugin,
OnOpenChannelToPepperPlugin)
@@ -319,6 +338,7 @@ void RenderFrameMessageFilter::DownloadUrl(
const url::Origin& initiator,
const base::string16& suggested_name,
const bool use_prompt,
+ const bool follow_cross_origin_redirects,
blink::mojom::BlobURLTokenPtrInfo blob_url_token) const {
if (!resource_context_)
return;
@@ -355,6 +375,7 @@ void RenderFrameMessageFilter::DownloadUrl(
parameters->set_content_initiated(true);
parameters->set_suggested_name(suggested_name);
parameters->set_prompt(use_prompt);
+ parameters->set_follow_cross_origin_redirects(follow_cross_origin_redirects);
parameters->set_referrer(referrer.url);
parameters->set_referrer_policy(
Referrer::ReferrerPolicyForUrlRequest(referrer.policy));
@@ -368,6 +389,24 @@ void RenderFrameMessageFilter::DownloadUrl(
if (url.SchemeIsBlob()) {
ChromeBlobStorageContext* blob_context =
GetChromeBlobStorageContextForResourceContext(resource_context_);
+
+ // With network service disabled the downloads code wouldn't know what to do
+ // with the BlobURLToken (or the resulting URLLoaderFactory). So for that
+ // case convert the token to a BlobDataHandle before passing it of to the
+ // rest of the downloads system.
+ if (blob_url_token &&
+ !base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ blink::mojom::BlobURLTokenPtr blob_url_token_ptr(
+ std::move(blob_url_token));
+ auto* raw_token = blob_url_token_ptr.get();
+ raw_token->GetToken(mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(&DownloadBlobURLFromToken, std::move(parameters),
+ std::move(blob_url_token_ptr),
+ blob_context->context()->AsWeakPtr()),
+ base::UnguessableToken()));
+ return;
+ }
+
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.
@@ -446,7 +485,8 @@ void RenderFrameMessageFilter::OnDownloadUrl(
DownloadUrl(params.render_view_id, params.render_frame_id, params.url,
params.referrer, params.initiator_origin, params.suggested_name,
- false, std::move(blob_url_token));
+ false, params.follow_cross_origin_redirects,
+ std::move(blob_url_token));
}
void RenderFrameMessageFilter::OnSaveImageFromDataURL(
@@ -462,7 +502,7 @@ void RenderFrameMessageFilter::OnSaveImageFromDataURL(
return;
DownloadUrl(render_view_id, render_frame_id, data_url, Referrer(),
- url::Origin(), base::string16(), true, nullptr);
+ url::Origin(), base::string16(), true, true, nullptr);
}
void RenderFrameMessageFilter::OnAre3DAPIsBlocked(int render_frame_id,
@@ -507,7 +547,7 @@ void RenderFrameMessageFilter::SetCookie(int32_t render_frame_id,
if (!GetContentClient()->browser()->AllowSetCookie(
url, site_for_cookies, *cookie, resource_context_, render_process_id_,
- render_frame_id, options))
+ render_frame_id))
return;
net::URLRequestContext* context = GetRequestContextForURL(url);
@@ -586,58 +626,6 @@ void RenderFrameMessageFilter::GetCookies(int render_frame_id,
#if BUILDFLAG(ENABLE_PLUGINS)
-void RenderFrameMessageFilter::OnGetPlugins(
- bool refresh,
- const url::Origin& main_frame_origin,
- IPC::Message* reply_msg) {
- // Don't refresh if the specified threshold has not been passed. Note that
- // this check is performed before off-loading to the file thread. The reason
- // we do this is that some pages tend to request that the list of plugins be
- // refreshed at an excessive rate. This instigates disk scanning, as the list
- // is accumulated by doing multiple reads from disk. This effect is
- // multiplied when we have several pages requesting this operation.
- if (refresh) {
- const base::TimeDelta threshold = base::TimeDelta::FromSeconds(
- kPluginsRefreshThresholdInSeconds);
- const base::TimeTicks now = base::TimeTicks::Now();
- if (now - last_plugin_refresh_time_ >= threshold) {
- // Only refresh if the threshold hasn't been exceeded yet.
- PluginServiceImpl::GetInstance()->RefreshPlugins();
- last_plugin_refresh_time_ = now;
- }
- }
-
- PluginServiceImpl::GetInstance()->GetPlugins(
- base::BindOnce(&RenderFrameMessageFilter::GetPluginsCallback, this,
- reply_msg, main_frame_origin));
-}
-
-void RenderFrameMessageFilter::GetPluginsCallback(
- IPC::Message* reply_msg,
- const url::Origin& main_frame_origin,
- const std::vector<WebPluginInfo>& all_plugins) {
- // Filter the plugin list.
- PluginServiceFilter* filter = PluginServiceImpl::GetInstance()->GetFilter();
- std::vector<WebPluginInfo> plugins;
-
- int child_process_id = -1;
- int routing_id = MSG_ROUTING_NONE;
- // In this loop, copy the WebPluginInfo (and do not use a reference) because
- // the filter might mutate it.
- for (WebPluginInfo plugin : all_plugins) {
- // TODO(crbug.com/621724): Pass an url::Origin instead of a GURL.
- if (!filter ||
- filter->IsPluginAvailable(child_process_id, routing_id,
- resource_context_, main_frame_origin.GetURL(),
- main_frame_origin, &plugin)) {
- plugins.push_back(plugin);
- }
- }
-
- FrameHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins);
- Send(reply_msg);
-}
-
void RenderFrameMessageFilter::OnGetPluginInfo(
int render_frame_id,
const GURL& url,
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 7f3ab224bd1..9716b200806 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.h
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.h
@@ -85,6 +85,7 @@ class CONTENT_EXPORT RenderFrameMessageFilter
const url::Origin& initiator,
const base::string16& suggested_name,
const bool use_prompt,
+ const bool follow_cross_origin_redirects,
blink::mojom::BlobURLTokenPtrInfo blob_url_token) const;
private:
@@ -141,12 +142,6 @@ class CONTENT_EXPORT RenderFrameMessageFilter
GetCookiesCallback callback) override;
#if BUILDFLAG(ENABLE_PLUGINS)
- void OnGetPlugins(bool refresh,
- const url::Origin& main_frame_origin,
- IPC::Message* reply_msg);
- void GetPluginsCallback(IPC::Message* reply_msg,
- const url::Origin& main_frame_origin,
- const std::vector<WebPluginInfo>& plugins);
void OnGetPluginInfo(int render_frame_id,
const GURL& url,
const url::Origin& main_frame_origin,
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 9c11ebe6935..6f1ed61980a 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
@@ -8,7 +8,7 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "content/browser/bad_message.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/render_frame_message_filter.h"
@@ -126,6 +126,32 @@ IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, Cookies) {
EXPECT_EQ("B=2; D=4", GetCookieFromJS(web_contents_http->GetMainFrame()));
}
+// Ensure "priority" cookie option is settable via document.cookie.
+IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, CookiePriority) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ struct {
+ std::string param;
+ net::CookiePriority priority;
+ } cases[] = {{"name=value", net::COOKIE_PRIORITY_DEFAULT},
+ {"name=value;priority=Low", net::COOKIE_PRIORITY_LOW},
+ {"name=value;priority=Medium", net::COOKIE_PRIORITY_MEDIUM},
+ {"name=value;priority=High", net::COOKIE_PRIORITY_HIGH}};
+
+ for (auto test_case : cases) {
+ GURL url = embedded_test_server()->GetURL("/set_document_cookie.html?" +
+ test_case.param);
+ NavigateToURL(shell(), url);
+ std::vector<net::CanonicalCookie> cookies =
+ GetCanonicalCookies(shell()->web_contents()->GetBrowserContext(), url);
+
+ EXPECT_EQ(1u, cookies.size());
+ EXPECT_EQ("name", cookies[0].Name());
+ EXPECT_EQ("value", cookies[0].Value());
+ EXPECT_EQ(test_case.priority, cookies[0].Priority());
+ }
+}
+
// SameSite cookies (that aren't marked as http-only) should be available to
// JavaScript.
IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, SameSiteCookies) {
@@ -278,7 +304,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, RenderProcessGone) {
// left the RPH and its connection alive, and the Wait below would hang.
EXPECT_EQ(bad_message::RFMF_RENDERER_FAKED_ITS_OWN_DEATH, kill_waiter.Wait());
- ASSERT_FALSE(web_rfh->GetProcess()->HasConnection());
+ ASSERT_FALSE(web_rfh->GetProcess()->IsInitializedAndNotDead());
ASSERT_FALSE(web_rfh->IsRenderFrameLive());
}
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 838bc1e20c3..b06a4b9242d 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
@@ -8,6 +8,8 @@
#include <vector>
#include "base/callback.h"
+#include "base/debug/alias.h"
+#include "base/debug/dump_without_crashing.h"
#include "base/lazy_instance.h"
#include "content/browser/bad_message.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
@@ -98,7 +100,7 @@ RenderFrameProxyHost::~RenderFrameProxyHost() {
if (!destruction_callback_.is_null())
std::move(destruction_callback_).Run();
- if (GetProcess()->HasConnection()) {
+ if (GetProcess()->IsInitializedAndNotDead()) {
// TODO(nasko): For now, don't send this IPC for top-level frames, as
// the top-level RenderFrame will delete the RenderFrameProxy.
// This can be removed once we don't have a swapped out state on
@@ -172,7 +174,7 @@ bool RenderFrameProxyHost::InitRenderFrameProxy() {
// RenderFrame. When that happens, the process will be reinitialized, and
// all necessary proxies, including any of the ones we skipped here, will be
// created by CreateProxiesForSiteInstance. See https://crbug.com/476846
- if (!GetProcess()->HasConnection())
+ if (!GetProcess()->IsInitializedAndNotDead())
return false;
int parent_routing_id = MSG_ROUTING_NONE;
@@ -202,6 +204,30 @@ bool RenderFrameProxyHost::InitRenderFrameProxy() {
site_instance_.get());
}
+ // Temporary debugging code for https://crbug.com/794625 to see if we're ever
+ // sending a message to create a RenderFrameProxy when one already exists.
+ // TODO(alexmos): Remove after the investigation.
+ if (render_frame_proxy_created_) {
+ SiteInstanceImpl* site_instance =
+ static_cast<SiteInstanceImpl*>(site_instance_.get());
+ GURL site_url(site_instance->GetSiteURL());
+ DEBUG_ALIAS_FOR_GURL(site_url_copy, site_url);
+ GURL current_rfh_site_url(frame_tree_node_->render_manager()
+ ->current_frame_host()
+ ->GetSiteInstance()
+ ->GetSiteURL());
+ DEBUG_ALIAS_FOR_GURL(current_rfh_site_url_copy, current_rfh_site_url);
+
+ int routing_id_copy = routing_id_;
+ base::debug::Alias(&routing_id_copy);
+ int parent_routing_id_copy = parent_routing_id;
+ base::debug::Alias(&parent_routing_id_copy);
+ int active_frame_count = site_instance->active_frame_count();
+ base::debug::Alias(&active_frame_count);
+
+ base::debug::DumpWithoutCrashing();
+ }
+
int view_routing_id = frame_tree_node_->frame_tree()
->GetRenderViewHost(site_instance_.get())->GetRoutingID();
GetProcess()->GetRendererInterface()->CreateFrameProxy(
@@ -381,6 +407,11 @@ void RenderFrameProxyHost::OnRouteMessageEvent(
->SynchronizeVisualPropertiesIgnoringPendingAck();
}
+ if (!source_rfh->frame_tree_node()->IsDescendantOf(
+ target_rfh->frame_tree_node())) {
+ target_rfh->did_receive_post_message_from_non_descendant();
+ }
+
// Ensure that we have a swapped-out RVH and proxy for the source frame
// in the target SiteInstance. If it doesn't exist, create it on demand
// and also create its opener chain, since that will also be accessible
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 a0bc38e7f05..7c08ae7a4ee 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
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "build/build_config.h"
+#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_hittest.h"
@@ -153,10 +154,9 @@ void RenderWidgetHostViewGuest::Show() {
// Since we were last shown, our renderer may have had a different surface
// set (e.g. showing an interstitial), so we resend our current surface to
// the renderer.
- if (last_received_local_surface_id_.is_valid())
- SendSurfaceInfoToEmbedder();
+ SendSurfaceInfoToEmbedder();
}
- host()->WasShown(ui::LatencyInfo());
+ host()->WasShown(false /* record_presentation_time */);
}
void RenderWidgetHostViewGuest::Hide() {
@@ -251,7 +251,7 @@ gfx::PointF RenderWidgetHostViewGuest::TransformPointToRootCoordSpaceF(
const gfx::PointF& point) {
// LocalSurfaceId is not needed in Viz hit-test.
if (!guest_ ||
- (!use_viz_hit_test_ && !last_received_local_surface_id_.is_valid())) {
+ (!use_viz_hit_test_ && !last_activated_surface_info_.is_valid())) {
return point;
}
@@ -264,9 +264,7 @@ gfx::PointF RenderWidgetHostViewGuest::TransformPointToRootCoordSpaceF(
// guarantee not to change transformed_point on failure, then we could skip
// checking the function return value and directly return transformed_point.
if (!root_rwhv->TransformPointToLocalCoordSpace(
- point,
- viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_),
- &transformed_point)) {
+ point, last_activated_surface_info_.id(), &transformed_point)) {
return point;
}
return transformed_point;
@@ -277,19 +275,18 @@ bool RenderWidgetHostViewGuest::TransformPointToLocalCoordSpaceLegacy(
const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point) {
*transformed_point = point;
- if (!guest_ || !last_received_local_surface_id_.is_valid())
+ if (!guest_ || !last_activated_surface_info_.is_valid())
return false;
- auto local_surface_id =
- viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_);
- if (original_surface == local_surface_id)
+ if (original_surface == last_activated_surface_info_.id())
return true;
*transformed_point =
gfx::ConvertPointToPixel(current_surface_scale_factor(), point);
viz::SurfaceHittest hittest(nullptr,
GetFrameSinkManager()->surface_manager());
- if (!hittest.TransformPointToTargetSurface(original_surface, local_surface_id,
+ if (!hittest.TransformPointToTargetSurface(original_surface,
+ last_activated_surface_info_.id(),
transformed_point)) {
return false;
}
@@ -349,6 +346,14 @@ base::string16 RenderWidgetHostViewGuest::GetSelectedText() {
return platform_view_->GetSelectedText();
}
+base::string16 RenderWidgetHostViewGuest::GetSurroundingText() {
+ return platform_view_->GetSurroundingText();
+}
+
+gfx::Range RenderWidgetHostViewGuest::GetSelectedRange() {
+ return platform_view_->GetSelectedRange();
+}
+
void RenderWidgetHostViewGuest::SetNeedsBeginFrames(bool needs_begin_frames) {
if (platform_view_)
platform_view_->SetNeedsBeginFrames(needs_begin_frames);
@@ -371,10 +376,10 @@ void RenderWidgetHostViewGuest::SetTooltipText(
root_view->GetCursorManager()->SetTooltipTextForView(this, tooltip_text);
}
-void RenderWidgetHostViewGuest::SendSurfaceInfoToEmbedderImpl(
+void RenderWidgetHostViewGuest::FirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
if (guest_ && !guest_->is_in_destruction())
- guest_->SetChildFrameSurface(surface_info);
+ guest_->FirstSurfaceActivation(surface_info);
}
void RenderWidgetHostViewGuest::OnDidUpdateVisualPropertiesComplete(
@@ -387,13 +392,14 @@ void RenderWidgetHostViewGuest::OnDidUpdateVisualPropertiesComplete(
void RenderWidgetHostViewGuest::OnAttached() {
RegisterFrameSinkId();
#if defined(USE_AURA)
- if (base::FeatureList::IsEnabled(::features::kMash)) {
+ if (!features::IsAshInBrowserProcess()) {
aura::Env::GetInstance()->ScheduleEmbed(
GetWindowTreeClientFromRenderer(),
base::BindOnce(&RenderWidgetHostViewGuest::OnGotEmbedToken,
weak_ptr_factory_.GetWeakPtr()));
}
#endif
+ SendSurfaceInfoToEmbedder();
}
bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) {
@@ -568,10 +574,11 @@ viz::FrameSinkId RenderWidgetHostViewGuest::GetRootFrameSinkId() {
return viz::FrameSinkId();
}
-viz::LocalSurfaceId RenderWidgetHostViewGuest::GetLocalSurfaceId() const {
+const viz::LocalSurfaceId& RenderWidgetHostViewGuest::GetLocalSurfaceId()
+ const {
if (guest_)
return guest_->local_surface_id();
- return viz::LocalSurfaceId();
+ return viz::ParentLocalSurfaceIdAllocator::InvalidLocalSurfaceId();
}
void RenderWidgetHostViewGuest::DidCreateNewRendererCompositorFrameSink(
@@ -664,6 +671,25 @@ void RenderWidgetHostViewGuest::GestureEventAck(
event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
GetOwnerRenderWidgetHostView()->GestureEventAck(event, ack_result);
}
+
+ if (blink::WebInputEvent::IsPinchGestureEventType(event.GetType()))
+ ProcessTouchpadPinchAckInRoot(event, ack_result);
+}
+
+void RenderWidgetHostViewGuest::ProcessTouchpadPinchAckInRoot(
+ const blink::WebGestureEvent& event,
+ InputEventAckState ack_result) {
+ DCHECK(blink::WebInputEvent::IsPinchGestureEventType(event.GetType()));
+
+ RenderWidgetHostViewBase* root_rwhv = GetRootView(this);
+ if (!root_rwhv)
+ return;
+
+ blink::WebGestureEvent pinch_event(event);
+ const gfx::PointF root_point =
+ TransformPointToRootCoordSpaceF(event.PositionInWidget());
+ pinch_event.SetPositionInWidget(root_point);
+ root_rwhv->GestureEventAck(pinch_event, ack_result);
}
InputEventAckState RenderWidgetHostViewGuest::FilterInputEvent(
@@ -798,10 +824,6 @@ void RenderWidgetHostViewGuest::OnHandleInputEvent(
}
}
-bool RenderWidgetHostViewGuest::HasEmbedderChanged() {
- return guest_ && guest_->has_attached_since_surface_set();
-}
-
#if defined(USE_AURA)
void RenderWidgetHostViewGuest::OnGotEmbedToken(
const base::UnguessableToken& token) {
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 1e2687b945e..864dd4bed93 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
@@ -80,6 +80,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
gfx::Rect GetBoundsInRootWindow() override;
gfx::Size GetCompositorViewportPixelSize() const override;
base::string16 GetSelectedText() override;
+ base::string16 GetSurroundingText() override;
+ gfx::Range GetSelectedRange() override;
void SetNeedsBeginFrames(bool needs_begin_frames) override;
TouchSelectionControllerClientManager*
GetTouchSelectionControllerClientManager() override;
@@ -126,7 +128,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
bool LockMouse() override;
void UnlockMouse() override;
viz::FrameSinkId GetRootFrameSinkId() override;
- viz::LocalSurfaceId GetLocalSurfaceId() const override;
+ const viz::LocalSurfaceId& GetLocalSurfaceId() const override;
void DidCreateNewRendererCompositorFrameSink(
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
override;
@@ -162,8 +164,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
private:
friend class RenderWidgetHostView;
- void SendSurfaceInfoToEmbedderImpl(
- const viz::SurfaceInfo& surface_info) override;
+ void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
void OnDidUpdateVisualPropertiesComplete(
const cc::RenderFrameMetadata& metadata);
@@ -187,7 +188,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
int browser_plugin_instance_id,
const blink::WebInputEvent* event);
- bool HasEmbedderChanged() override;
+ void ProcessTouchpadPinchAckInRoot(const blink::WebGestureEvent& event,
+ InputEventAckState ack_result);
#if defined(USE_AURA)
void OnGotEmbedToken(const base::UnguessableToken& token);
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 8c69857ab3f..fa97ccfa39b 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
@@ -28,7 +28,6 @@
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
-#include "content/test/fake_renderer_compositor_frame_sink.h"
#include "content/test/mock_render_widget_host_delegate.h"
#include "content/test/mock_widget_impl.h"
#include "content/test/test_render_view_host.h"
@@ -114,16 +113,11 @@ class TestBrowserPluginGuest : public BrowserPluginGuest {
void ResetTestData() { last_surface_info_ = viz::SurfaceInfo(); }
- void set_has_attached_since_surface_set(bool has_attached_since_surface_set) {
- BrowserPluginGuest::set_has_attached_since_surface_set_for_test(
- has_attached_since_surface_set);
- }
-
void set_attached(bool attached) {
BrowserPluginGuest::set_attached_for_test(attached);
}
- void SetChildFrameSurface(const viz::SurfaceInfo& surface_info) override {
+ void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override {
last_surface_info_ = surface_info;
}
@@ -131,9 +125,7 @@ class TestBrowserPluginGuest : public BrowserPluginGuest {
};
// TODO(wjmaclean): we should restructure RenderWidgetHostViewChildFrameTest to
-// look more like this one, and then this one could be derived from it. Also,
-// include CreateDelegatedFrame as part of the test class so we don't have to
-// repeat it here.
+// look more like this one, and then this one could be derived from it.
class RenderWidgetHostViewGuestSurfaceTest
: public testing::Test {
public:
@@ -162,16 +154,6 @@ class RenderWidgetHostViewGuestSurfaceTest
view_ = RenderWidgetHostViewGuest::Create(
widget_host_, browser_plugin_guest_,
(new TestRenderWidgetHostView(widget_host_))->GetWeakPtr());
- viz::mojom::CompositorFrameSinkPtr sink;
- viz::mojom::CompositorFrameSinkRequest sink_request =
- mojo::MakeRequest(&sink);
- viz::mojom::CompositorFrameSinkClientRequest client_request =
- mojo::MakeRequest(&renderer_compositor_frame_sink_ptr_);
- renderer_compositor_frame_sink_ =
- std::make_unique<FakeRendererCompositorFrameSink>(
- std::move(sink), std::move(client_request));
- view_->DidCreateNewRendererCompositorFrameSink(
- renderer_compositor_frame_sink_ptr_.get());
}
void TearDown() override {
@@ -192,10 +174,7 @@ class RenderWidgetHostViewGuestSurfaceTest
DCHECK(view_);
RenderWidgetHostViewChildFrame* rwhvcf =
static_cast<RenderWidgetHostViewChildFrame*>(view_);
- if (!rwhvcf->last_received_local_surface_id_.is_valid())
- return viz::SurfaceId();
- return viz::SurfaceId(rwhvcf->frame_sink_id_,
- rwhvcf->last_received_local_surface_id_);
+ return rwhvcf->last_activated_surface_info_.id();
}
protected:
@@ -211,8 +190,6 @@ class RenderWidgetHostViewGuestSurfaceTest
std::unique_ptr<MockWidgetImpl> widget_impl_;
RenderWidgetHostImpl* widget_host_;
RenderWidgetHostViewGuest* view_;
- std::unique_ptr<FakeRendererCompositorFrameSink>
- renderer_compositor_frame_sink_;
private:
viz::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_;
@@ -220,33 +197,13 @@ class RenderWidgetHostViewGuestSurfaceTest
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestSurfaceTest);
};
-namespace {
-viz::CompositorFrame CreateDelegatedFrame(float scale_factor,
- gfx::Size size,
- const gfx::Rect& damage) {
- viz::CompositorFrame frame;
- frame.metadata.device_scale_factor = scale_factor;
- frame.metadata.begin_frame_ack = viz::BeginFrameAck(0, 1, true);
-
- std::unique_ptr<viz::RenderPass> pass = viz::RenderPass::Create();
- pass->SetNew(1, gfx::Rect(size), damage, gfx::Transform());
- frame.render_pass_list.push_back(std::move(pass));
- return frame;
-}
-} // anonymous namespace
-
TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
- // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
- // https://crbug.com/844469
- if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- base::FeatureList::IsEnabled(features::kMash)) {
- return;
- }
-
gfx::Size view_size(100, 100);
gfx::Rect view_rect(view_size);
float scale_factor = 1.f;
viz::LocalSurfaceId local_surface_id(1, base::UnguessableToken::Create());
+ viz::SurfaceId surface_id(view_->GetFrameSinkId(), local_surface_id);
+ viz::SurfaceInfo surface_info(surface_id, scale_factor, view_size);
ASSERT_TRUE(browser_plugin_guest_);
@@ -254,46 +211,24 @@ TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
view_->Show();
browser_plugin_guest_->set_attached(true);
- view_->SubmitCompositorFrame(
- local_surface_id,
- CreateDelegatedFrame(scale_factor, view_size, view_rect), base::nullopt);
- viz::SurfaceId id = GetSurfaceId();
+ view_->OnFirstSurfaceActivation(surface_info);
- EXPECT_TRUE(id.is_valid());
+ EXPECT_EQ(surface_id, GetSurfaceId());
-#if !defined(OS_ANDROID)
- viz::SurfaceManager* manager = ImageTransportFactory::GetInstance()
- ->GetContextFactoryPrivate()
- ->GetFrameSinkManager()
- ->surface_manager();
- viz::Surface* surface = manager->GetSurfaceForId(id);
- EXPECT_TRUE(surface);
-#endif
// Surface ID should have been passed to BrowserPluginGuest to
// be sent to the embedding renderer.
- EXPECT_EQ(viz::SurfaceInfo(id, scale_factor, view_size),
- browser_plugin_guest_->last_surface_info_);
+ EXPECT_EQ(surface_info, browser_plugin_guest_->last_surface_info_);
browser_plugin_guest_->ResetTestData();
- browser_plugin_guest_->set_has_attached_since_surface_set(true);
- view_->SubmitCompositorFrame(
- local_surface_id,
- CreateDelegatedFrame(scale_factor, view_size, view_rect), base::nullopt);
+ // The last received SurfaceInfo must be sent to BrowserPluginGuest on
+ // attachment.
+ view_->OnAttached();
- // Since we have not changed the frame size and scale factor, the same surface
- // id must be used.
- DCHECK_EQ(id, GetSurfaceId());
-
-#if !defined(OS_ANDROID)
- surface = manager->GetSurfaceForId(id);
- EXPECT_TRUE(surface);
-#endif
// Surface ID should have been passed to BrowserPluginGuest to
// be sent to the embedding renderer.
- EXPECT_EQ(viz::SurfaceInfo(id, scale_factor, view_size),
- browser_plugin_guest_->last_surface_info_);
+ EXPECT_EQ(surface_info, browser_plugin_guest_->last_surface_info_);
browser_plugin_guest_->set_attached(false);
browser_plugin_guest_->ResetTestData();
diff --git a/chromium/content/browser/frame_host/webui_navigation_browsertest.cc b/chromium/content/browser/frame_host/webui_navigation_browsertest.cc
index 23f8a793303..7add77190dd 100644
--- a/chromium/content/browser/frame_host/webui_navigation_browsertest.cc
+++ b/chromium/content/browser/frame_host/webui_navigation_browsertest.cc
@@ -6,6 +6,7 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents.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"
@@ -28,6 +29,107 @@ class WebUINavigationBrowserTest : public ContentBrowserTest {
ASSERT_TRUE(embedded_test_server()->Start());
}
+ // Verify that no web content can be loaded in a process that has WebUI
+ // bindings, regardless of what scheme the content was loaded from.
+ void TestWebFrameInWebUIProcessDisallowed(int bindings) {
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ GURL data_url("data:text/html,a data url document");
+ EXPECT_TRUE(NavigateToURL(shell(), data_url));
+ EXPECT_EQ(data_url, root->current_frame_host()->GetLastCommittedURL());
+ EXPECT_FALSE(
+ ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ root->current_frame_host()->GetProcess()->GetID()));
+
+ // Grant WebUI bindings to the process. This will ensure that if there is
+ // a mistake in the navigation logic and a process gets somehow WebUI
+ // bindings, it cannot include web content regardless of the scheme of the
+ // document.
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
+ root->current_frame_host()->GetProcess()->GetID(), bindings);
+ EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ root->current_frame_host()->GetProcess()->GetID()));
+ {
+ GURL web_url(embedded_test_server()->GetURL("/title2.html"));
+ std::string script = base::StringPrintf(
+ "var frame = document.createElement('iframe');\n"
+ "frame.src = '%s';\n"
+ "document.body.appendChild(frame);\n",
+ web_url.spec().c_str());
+
+ TestNavigationObserver navigation_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell(), script));
+ navigation_observer.Wait();
+
+ EXPECT_EQ(1U, root->child_count());
+ EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
+ }
+ }
+
+ // Verify that a WebUI document in a subframe is allowed to target a new
+ // window and navigate it to web content.
+ void TestWebUISubframeNewWindowToWebAllowed(int bindings) {
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // TODO(nasko): Replace this URL with one with a custom WebUI object that
+ // doesn't have restrictive CSP, so the test can successfully add an
+ // iframe which gets WebUI bindings in the renderer process.
+ GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" +
+ std::string(kChromeUIBlobInternalsHost));
+ EXPECT_TRUE(NavigateToURL(shell(), chrome_url));
+ RenderFrameHost* webui_rfh = root->current_frame_host();
+ scoped_refptr<SiteInstance> webui_site_instance =
+ webui_rfh->GetSiteInstance();
+
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
+ webui_rfh->GetProcess()->GetID(), bindings);
+
+ EXPECT_EQ(chrome_url, webui_rfh->GetLastCommittedURL());
+ EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ webui_rfh->GetProcess()->GetID()));
+
+ // Create a subframe with a WebUI document in it.
+ {
+ std::string script = base::StringPrintf(
+ "var frame = document.createElement('iframe');\n"
+ "frame.src = '%s';\n"
+ "document.body.appendChild(frame);\n",
+ chrome_url.spec().c_str());
+
+ TestNavigationObserver navigation_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell(), script));
+ navigation_observer.Wait();
+
+ EXPECT_EQ(1U, root->child_count());
+ EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
+ }
+
+ // Add a link that targets a new window and click it.
+ GURL web_url(embedded_test_server()->GetURL("/title2.html"));
+ std::string script = base::StringPrintf(
+ "var a = document.createElement('a');"
+ "a.href = '%s'; a.target = '_blank'; a.click()",
+ web_url.spec().c_str());
+
+ ShellAddedObserver new_shell_observer;
+ EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ Shell* new_shell = new_shell_observer.GetShell();
+ WaitForLoadStop(new_shell->web_contents());
+
+ EXPECT_EQ(web_url, new_shell->web_contents()->GetLastCommittedURL());
+
+ // TODO(nasko): Verify the SiteInstance is different once
+ // https://crbug.com/776900 is fixed.
+ // Without a WebUI object which requires WebUI bindings, the RenderFrame is
+ // not notified that it has WebUI bindings. This in turn causes link clicks
+ // to use the BeginNavigation path, where otherwise the WebUI bindings will
+ // cause the OpenURL path to be taken. When using BeginNavigation, the
+ // navigation is committed same process, since it is renderer initiated.
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(WebUINavigationBrowserTest);
};
@@ -101,44 +203,6 @@ IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
}
}
-// Verify that no web content can be loaded in a process that has WebUI
-// bindings, regardless of what scheme the content was loaded from.
-IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
- WebFrameInWebUIProcessDisallowed) {
- FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root();
- GURL data_url("data:text/html,a data url document");
- EXPECT_TRUE(NavigateToURL(shell(), data_url));
- EXPECT_EQ(data_url, root->current_frame_host()->GetLastCommittedURL());
- EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
- root->current_frame_host()->GetProcess()->GetID()));
-
- // Grant WebUI bindings to the process. This will ensure that if there is
- // a mistake in the navigation logic and a process gets somehow WebUI
- // bindings, it cannot include web content regardless of the scheme of the
- // document.
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
- root->current_frame_host()->GetProcess()->GetID());
- EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
- root->current_frame_host()->GetProcess()->GetID()));
- {
- GURL web_url(embedded_test_server()->GetURL("/title2.html"));
- std::string script = base::StringPrintf(
- "var frame = document.createElement('iframe');\n"
- "frame.src = '%s';\n"
- "document.body.appendChild(frame);\n",
- web_url.spec().c_str());
-
- TestNavigationObserver navigation_observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(shell(), script));
- navigation_observer.Wait();
-
- EXPECT_EQ(1U, root->child_count());
- EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
- }
-}
-
// Verify that a WebUI document in the main frame is allowed to navigate to
// web content and it properly does cross-process navigation.
IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest, WebUIMainFrameToWebAllowed) {
@@ -171,68 +235,36 @@ IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest, WebUIMainFrameToWebAllowed) {
root->current_frame_host()->GetSiteInstance()));
}
-// Verify that a WebUI document in a subframe is allowed to target a new
-// window and navigate it to web content.
IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
- WebUISubframeNewWindowToWebAllowed) {
- FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root();
-
- // TODO(nasko): Replace this URL with one with a custom WebUI object that
- // doesn't have restrictive CSP, so the test can successfully add an
- // iframe which gets WebUI bindings in the renderer process.
- GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" +
- std::string(kChromeUIBlobInternalsHost));
- EXPECT_TRUE(NavigateToURL(shell(), chrome_url));
- RenderFrameHost* webui_rfh = root->current_frame_host();
- scoped_refptr<SiteInstance> webui_site_instance =
- webui_rfh->GetSiteInstance();
-
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
- webui_rfh->GetProcess()->GetID());
+ WebFrameInWebUIProcessDisallowed) {
+ TestWebFrameInWebUIProcessDisallowed(BINDINGS_POLICY_WEB_UI);
+}
- EXPECT_EQ(chrome_url, webui_rfh->GetLastCommittedURL());
- EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
- webui_rfh->GetProcess()->GetID()));
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+ WebFrameInMojoWebUIProcessDisallowed) {
+ TestWebFrameInWebUIProcessDisallowed(BINDINGS_POLICY_MOJO_WEB_UI);
+}
- // Create a subframe with a WebUI document in it.
- {
- std::string script = base::StringPrintf(
- "var frame = document.createElement('iframe');\n"
- "frame.src = '%s';\n"
- "document.body.appendChild(frame);\n",
- chrome_url.spec().c_str());
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+ WebFrameInHybridWebUIProcessDisallowed) {
+ TestWebFrameInWebUIProcessDisallowed(BINDINGS_POLICY_MOJO_WEB_UI |
+ BINDINGS_POLICY_WEB_UI);
+}
- TestNavigationObserver navigation_observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(shell(), script));
- navigation_observer.Wait();
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+ WebUISubframeNewWindowToWebAllowed) {
+ TestWebUISubframeNewWindowToWebAllowed(BINDINGS_POLICY_WEB_UI);
+}
- EXPECT_EQ(1U, root->child_count());
- EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
- }
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+ MojoWebUISubframeNewWindowToWebAllowed) {
+ TestWebUISubframeNewWindowToWebAllowed(BINDINGS_POLICY_MOJO_WEB_UI);
+}
- // Add a link that targets a new window and click it.
- GURL web_url(embedded_test_server()->GetURL("/title2.html"));
- std::string script = base::StringPrintf(
- "var a = document.createElement('a');"
- "a.href = '%s'; a.target = '_blank'; a.click()",
- web_url.spec().c_str());
-
- ShellAddedObserver new_shell_observer;
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
- Shell* new_shell = new_shell_observer.GetShell();
- WaitForLoadStop(new_shell->web_contents());
-
- EXPECT_EQ(web_url, new_shell->web_contents()->GetLastCommittedURL());
-
- // TODO(nasko): Verify the SiteInstance is different once
- // https://crbug.com/776900 is fixed.
- // Without a WebUI object which requires WebUI bindings, the RenderFrame is
- // not notified that it has WebUI bindings. This in turn causes link clicks
- // to use the BeginNavigation path, where otherwise the WebUI bindings will
- // cause the OpenURL path to be taken. When using BeginNavigation, the
- // navigation is committed same process, since it is renderer initiated.
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+ HybridWebUISubframeNewWindowToWebAllowed) {
+ TestWebUISubframeNewWindowToWebAllowed(BINDINGS_POLICY_MOJO_WEB_UI |
+ BINDINGS_POLICY_WEB_UI);
}
} // namespace content
diff --git a/chromium/content/browser/generic_sensor/generic_sensor_browsertest.cc b/chromium/content/browser/generic_sensor/generic_sensor_browsertest.cc
index ec3dff1a554..216f03d8869 100644
--- a/chromium/content/browser/generic_sensor/generic_sensor_browsertest.cc
+++ b/chromium/content/browser/generic_sensor/generic_sensor_browsertest.cc
@@ -4,7 +4,6 @@
#include "base/bind.h"
#include "base/macros.h"
-#include "base/synchronization/waitable_event.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
@@ -42,15 +41,24 @@ using device::FakeSensorProvider;
class GenericSensorBrowserTest : public ContentBrowserTest {
public:
- GenericSensorBrowserTest()
- : io_loop_finished_event_(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED) {
+ GenericSensorBrowserTest() {
scoped_feature_list_.InitWithFeatures(
{features::kGenericSensor, features::kGenericSensorExtraClasses}, {});
+
+ // Because Device Service also runs in this process (browser process), here
+ // we can directly set our binder to intercept interface requests against
+ // it.
+ service_manager::ServiceContext::SetGlobalBinderForTesting(
+ device::mojom::kServiceName, device::mojom::SensorProvider::Name_,
+ base::BindRepeating(
+ &GenericSensorBrowserTest::BindSensorProviderRequest,
+ base::Unretained(this)));
}
- ~GenericSensorBrowserTest() override {}
+ ~GenericSensorBrowserTest() override {
+ service_manager::ServiceContext::ClearGlobalBindersForTesting(
+ device::mojom::kServiceName);
+ }
void SetUpOnMainThread() override {
https_embedded_test_server_.reset(
@@ -62,13 +70,6 @@ class GenericSensorBrowserTest : public ContentBrowserTest {
https_embedded_test_server_->ServeFilesFromSourceDirectory(
"content/test/data/generic_sensor");
https_embedded_test_server_->StartAcceptingConnections();
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&GenericSensorBrowserTest::SetBinderOnIOThread,
- base::Unretained(this)));
-
- io_loop_finished_event_.Wait();
}
void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -77,19 +78,6 @@ class GenericSensorBrowserTest : public ContentBrowserTest {
command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
}
- void SetBinderOnIOThread() {
- // Because Device Service also runs in this process(browser process), here
- // we can directly set our binder to intercept interface requests against
- // it.
- service_manager::ServiceContext::SetGlobalBinderForTesting(
- device::mojom::kServiceName, device::mojom::SensorProvider::Name_,
- base::BindRepeating(
- &GenericSensorBrowserTest::BindSensorProviderRequest,
- base::Unretained(this)));
-
- io_loop_finished_event_.Signal();
- }
-
void BindSensorProviderRequest(
const std::string& interface_name,
mojo::ScopedMessagePipeHandle handle,
@@ -115,21 +103,13 @@ class GenericSensorBrowserTest : public ContentBrowserTest {
private:
base::test::ScopedFeatureList scoped_feature_list_;
- base::WaitableEvent io_loop_finished_event_;
bool sensor_provider_available_ = true;
std::unique_ptr<FakeSensorProvider> fake_sensor_provider_;
DISALLOW_COPY_AND_ASSIGN(GenericSensorBrowserTest);
};
-// Flakily crashes on Linux ASAN/TSAN bots. https://crbug.com/789515
-// Flakily times out on Windows bots. https://crbug.com/809537
-#if defined(OS_LINUX) || defined(OS_WIN)
-#define MAYBE_AmbientLightSensorTest DISABLED_AmbientLightSensorTest
-#else
-#define MAYBE_AmbientLightSensorTest AmbientLightSensorTest
-#endif
-IN_PROC_BROWSER_TEST_F(GenericSensorBrowserTest, MAYBE_AmbientLightSensorTest) {
+IN_PROC_BROWSER_TEST_F(GenericSensorBrowserTest, AmbientLightSensorTest) {
// The test page will create an AmbientLightSensor object in Javascript,
// expects to get events with fake values then navigates to #pass.
GURL test_url =
diff --git a/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.cc b/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.cc
index 552320b0d36..174388b58fb 100644
--- a/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.cc
+++ b/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.cc
@@ -8,8 +8,8 @@
#include <utility>
#include <vector>
+#include "content/browser/permissions/permission_controller_impl.h"
#include "content/public/browser/browser_context.h"
-#include "content/public/browser/permission_manager.h"
#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -26,11 +26,12 @@ using device::mojom::SensorCreationResult;
namespace content {
SensorProviderProxyImpl::SensorProviderProxyImpl(
- PermissionManager* permission_manager,
+ PermissionControllerImpl* permission_controller,
RenderFrameHost* render_frame_host)
- : permission_manager_(permission_manager),
- render_frame_host_(render_frame_host) {
- DCHECK(permission_manager);
+ : permission_controller_(permission_controller),
+ render_frame_host_(render_frame_host),
+ weak_factory_(this) {
+ DCHECK(permission_controller);
DCHECK(render_frame_host);
}
@@ -43,36 +44,46 @@ void SensorProviderProxyImpl::Bind(
void SensorProviderProxyImpl::GetSensor(SensorType type,
GetSensorCallback callback) {
- ServiceManagerConnection* connection =
- ServiceManagerConnection::GetForProcess();
-
- if (!connection) {
- std::move(callback).Run(SensorCreationResult::ERROR_NOT_AVAILABLE, nullptr);
- return;
- }
-
- if (!CheckFeaturePolicies(type) || !CheckPermission()) {
+ if (!CheckFeaturePolicies(type)) {
std::move(callback).Run(SensorCreationResult::ERROR_NOT_ALLOWED, nullptr);
return;
}
if (!sensor_provider_) {
+ auto* connection = ServiceManagerConnection::GetForProcess();
+
+ if (!connection) {
+ std::move(callback).Run(SensorCreationResult::ERROR_NOT_AVAILABLE,
+ nullptr);
+ return;
+ }
+
connection->GetConnector()->BindInterface(
device::mojom::kServiceName, mojo::MakeRequest(&sensor_provider_));
sensor_provider_.set_connection_error_handler(base::BindOnce(
&SensorProviderProxyImpl::OnConnectionError, base::Unretained(this)));
}
- sensor_provider_->GetSensor(type, std::move(callback));
-}
-bool SensorProviderProxyImpl::CheckPermission() const {
- const GURL& requesting_origin =
- render_frame_host_->GetLastCommittedURL().GetOrigin();
+ // TODO(shalamov): base::BindOnce should be used (https://crbug.com/714018),
+ // however, PermissionController::RequestPermission enforces use of repeating
+ // callback.
+ permission_controller_->RequestPermission(
+ PermissionType::SENSORS, render_frame_host_,
+ render_frame_host_->GetLastCommittedURL().GetOrigin(), false,
+ base::BindRepeating(
+ &SensorProviderProxyImpl::OnPermissionRequestCompleted,
+ weak_factory_.GetWeakPtr(), type, base::Passed(std::move(callback))));
+}
- blink::mojom::PermissionStatus permission_status =
- permission_manager_->GetPermissionStatusForFrame(
- PermissionType::SENSORS, render_frame_host_, requesting_origin);
- return permission_status == blink::mojom::PermissionStatus::GRANTED;
+void SensorProviderProxyImpl::OnPermissionRequestCompleted(
+ device::mojom::SensorType type,
+ GetSensorCallback callback,
+ blink::mojom::PermissionStatus status) {
+ if (status != blink::mojom::PermissionStatus::GRANTED || !sensor_provider_) {
+ std::move(callback).Run(SensorCreationResult::ERROR_NOT_ALLOWED, nullptr);
+ return;
+ }
+ sensor_provider_->GetSensor(type, std::move(callback));
}
namespace {
diff --git a/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.h b/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.h
index 5947fab761e..41e673bddf4 100644
--- a/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.h
+++ b/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.h
@@ -5,21 +5,23 @@
#ifndef CONTENT_BROWSER_GENERIC_SENSOR_SENSOR_PROVIDER_PROXY_IMPL_H_
#define CONTENT_BROWSER_GENERIC_SENSOR_SENSOR_PROVIDER_PROXY_IMPL_H_
+#include "base/memory/weak_ptr.h"
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/device/public/mojom/sensor_provider.mojom.h"
+#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
namespace content {
-class PermissionManager;
+class PermissionControllerImpl;
class RenderFrameHost;
// This proxy acts as a gatekeeper to the real sensor provider so that this
// proxy can intercept sensor requests and allow or deny them based on
-// the permission statuses retrieved from a permission manager.
+// the permission statuses retrieved from a permission controller.
class SensorProviderProxyImpl final : public device::mojom::SensorProvider {
public:
- SensorProviderProxyImpl(PermissionManager* permission_manager,
+ SensorProviderProxyImpl(PermissionControllerImpl* permission_controller,
RenderFrameHost* render_frame_host);
~SensorProviderProxyImpl() override;
@@ -30,16 +32,19 @@ class SensorProviderProxyImpl final : public device::mojom::SensorProvider {
void GetSensor(device::mojom::SensorType type,
GetSensorCallback callback) override;
- bool CheckPermission() const;
bool CheckFeaturePolicies(device::mojom::SensorType type) const;
-
+ void OnPermissionRequestCompleted(device::mojom::SensorType type,
+ GetSensorCallback callback,
+ blink::mojom::PermissionStatus);
void OnConnectionError();
mojo::BindingSet<device::mojom::SensorProvider> binding_set_;
- PermissionManager* permission_manager_;
+ PermissionControllerImpl* permission_controller_;
RenderFrameHost* render_frame_host_;
device::mojom::SensorProviderPtr sensor_provider_;
+ base::WeakPtrFactory<SensorProviderProxyImpl> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(SensorProviderProxyImpl);
};
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl.cc b/chromium/content/browser/geolocation/geolocation_service_impl.cc
index 80bdba2932e..342e68a8317 100644
--- a/chromium/content/browser/geolocation/geolocation_service_impl.cc
+++ b/chromium/content/browser/geolocation/geolocation_service_impl.cc
@@ -4,7 +4,7 @@
#include "content/browser/geolocation/geolocation_service_impl.h"
-#include "content/public/browser/permission_manager.h"
+#include "content/browser/permissions/permission_controller_impl.h"
#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/content_features.h"
@@ -13,9 +13,9 @@
namespace content {
GeolocationServiceImplContext::GeolocationServiceImplContext(
- PermissionManager* permission_manager)
- : permission_manager_(permission_manager),
- request_id_(PermissionManager::kNoPendingOperation),
+ PermissionControllerImpl* permission_controller)
+ : permission_controller_(permission_controller),
+ request_id_(PermissionController::kNoPendingOperation),
weak_factory_(this) {}
GeolocationServiceImplContext::~GeolocationServiceImplContext() {
@@ -25,14 +25,14 @@ void GeolocationServiceImplContext::RequestPermission(
RenderFrameHost* render_frame_host,
bool user_gesture,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback) {
- if (request_id_ != PermissionManager::kNoPendingOperation) {
+ if (request_id_ != PermissionController::kNoPendingOperation) {
mojo::ReportBadMessage(
"GeolocationService client may only create one Geolocation at a "
"time.");
return;
}
- request_id_ = permission_manager_->RequestPermission(
+ request_id_ = permission_controller_->RequestPermission(
PermissionType::GEOLOCATION, render_frame_host,
render_frame_host->GetLastCommittedOrigin().GetURL(), user_gesture,
// NOTE: The permission request is canceled in the destructor, so it is
@@ -44,19 +44,19 @@ void GeolocationServiceImplContext::RequestPermission(
void GeolocationServiceImplContext::HandlePermissionStatus(
const base::Callback<void(blink::mojom::PermissionStatus)>& callback,
blink::mojom::PermissionStatus permission_status) {
- request_id_ = PermissionManager::kNoPendingOperation;
+ request_id_ = PermissionController::kNoPendingOperation;
callback.Run(permission_status);
}
GeolocationServiceImpl::GeolocationServiceImpl(
device::mojom::GeolocationContext* geolocation_context,
- PermissionManager* permission_manager,
+ PermissionControllerImpl* permission_controller,
RenderFrameHost* render_frame_host)
: geolocation_context_(geolocation_context),
- permission_manager_(permission_manager),
+ permission_controller_(permission_controller),
render_frame_host_(render_frame_host) {
DCHECK(geolocation_context);
- DCHECK(permission_manager);
+ DCHECK(permission_controller);
DCHECK(render_frame_host);
}
@@ -66,7 +66,7 @@ void GeolocationServiceImpl::Bind(
blink::mojom::GeolocationServiceRequest request) {
binding_set_.AddBinding(
this, std::move(request),
- std::make_unique<GeolocationServiceImplContext>(permission_manager_));
+ std::make_unique<GeolocationServiceImplContext>(permission_controller_));
}
void GeolocationServiceImpl::CreateGeolocation(
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl.h b/chromium/content/browser/geolocation/geolocation_service_impl.h
index 68f6a2000bd..42548d97ad4 100644
--- a/chromium/content/browser/geolocation/geolocation_service_impl.h
+++ b/chromium/content/browser/geolocation/geolocation_service_impl.h
@@ -20,11 +20,12 @@ enum class PermissionStatus;
namespace content {
class RenderFrameHost;
-class PermissionManager;
+class PermissionControllerImpl;
class GeolocationServiceImplContext {
public:
- GeolocationServiceImplContext(PermissionManager* permission_manager_);
+ explicit GeolocationServiceImplContext(
+ PermissionControllerImpl* permission_controller);
~GeolocationServiceImplContext();
void RequestPermission(
RenderFrameHost* render_frame_host,
@@ -32,7 +33,7 @@ class GeolocationServiceImplContext {
const base::Callback<void(blink::mojom::PermissionStatus)>& callback);
private:
- PermissionManager* permission_manager_;
+ PermissionControllerImpl* permission_controller_;
int request_id_;
void HandlePermissionStatus(
@@ -48,7 +49,7 @@ class CONTENT_EXPORT GeolocationServiceImpl
: public blink::mojom::GeolocationService {
public:
GeolocationServiceImpl(device::mojom::GeolocationContext* geolocation_context,
- PermissionManager* permission_manager,
+ PermissionControllerImpl* permission_controller,
RenderFrameHost* render_frame_host);
~GeolocationServiceImpl() override;
@@ -68,7 +69,7 @@ class CONTENT_EXPORT GeolocationServiceImpl
blink::mojom::PermissionStatus permission_status);
device::mojom::GeolocationContext* geolocation_context_;
- PermissionManager* permission_manager_;
+ PermissionControllerImpl* permission_controller_;
RenderFrameHost* render_frame_host_;
// Along with each GeolocationService, we store a
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc b/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc
index 895cd610fe8..bb1ec33adf4 100644
--- a/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc
+++ b/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc
@@ -7,15 +7,17 @@
#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
-#include "content/public/browser/permission_manager.h"
+#include "content/browser/permissions/permission_controller_impl.h"
+#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_type.h"
#include "content/public/common/content_features.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/test/mock_permission_manager.h"
#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_service_manager_context.h"
#include "content/test/test_render_frame_host.h"
-#include "device/geolocation/public/cpp/scoped_geolocation_overrider.h"
+#include "services/device/public/cpp/test/scoped_geolocation_overrider.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/geolocation.mojom.h"
#include "services/device/public/mojom/geolocation_context.mojom.h"
@@ -45,7 +47,7 @@ GURL kEmbeddedUrl = GURL("https://embeddables.com/someframe");
class TestPermissionManager : public MockPermissionManager {
public:
TestPermissionManager()
- : request_id_(PermissionManager::kNoPendingOperation) {}
+ : request_id_(PermissionController::kNoPendingOperation) {}
~TestPermissionManager() override = default;
int RequestPermission(PermissionType permissions,
@@ -81,7 +83,11 @@ class GeolocationServiceTest : public RenderViewHostImplTestHarness {
void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
NavigateAndCommit(kMainUrl);
- permission_manager_.reset(new TestPermissionManager);
+ browser_context_.reset(new content::TestBrowserContext());
+ browser_context_->SetPermissionControllerDelegate(
+ std::make_unique<TestPermissionManager>());
+ permission_controller_.reset(
+ new PermissionControllerImpl(browser_context_.get()));
service_manager_context_ = std::make_unique<TestServiceManagerContext>();
geolocation_overrider_ =
@@ -97,6 +103,7 @@ class GeolocationServiceTest : public RenderViewHostImplTestHarness {
context_ptr_.reset();
geolocation_overrider_.reset();
service_manager_context_.reset();
+ browser_context_.reset();
RenderViewHostImplTestHarness::TearDown();
}
@@ -116,7 +123,7 @@ class GeolocationServiceTest : public RenderViewHostImplTestHarness {
embedded_rfh = navigation_simulator->GetFinalRenderFrameHost();
service_.reset(new GeolocationServiceImpl(
- context_ptr_.get(), permission_manager_.get(), embedded_rfh));
+ context_ptr_.get(), permission_controller_.get(), embedded_rfh));
service_->Bind(mojo::MakeRequest(&service_ptr_));
}
@@ -125,7 +132,8 @@ class GeolocationServiceTest : public RenderViewHostImplTestHarness {
GeolocationService* service() { return &*service_ptr_; }
TestPermissionManager* permission_manager() {
- return permission_manager_.get();
+ return static_cast<TestPermissionManager*>(
+ browser_context_->GetPermissionControllerDelegate());
}
private:
@@ -134,7 +142,8 @@ class GeolocationServiceTest : public RenderViewHostImplTestHarness {
// The |permission_manager_| needs to come before the |service_| since
// GeolocationService calls PermissionManager in its destructor.
- std::unique_ptr<TestPermissionManager> permission_manager_;
+ std::unique_ptr<TestBrowserContext> browser_context_;
+ std::unique_ptr<PermissionControllerImpl> permission_controller_;
std::unique_ptr<GeolocationServiceImpl> service_;
GeolocationServicePtr service_ptr_;
device::mojom::GeolocationContextPtr context_ptr_;
diff --git a/chromium/content/browser/gpu/OWNERS b/chromium/content/browser/gpu/OWNERS
index c45f8fa6e23..55d9b9bde3d 100644
--- a/chromium/content/browser/gpu/OWNERS
+++ b/chromium/content/browser/gpu/OWNERS
@@ -1,5 +1,6 @@
kbr@chromium.org
piman@chromium.org
zmo@chromium.org
+backer@chromium.org
# COMPONENT: Internals>GPU>Internals
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 cdc4d3d678a..ca32413b3f3 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -4,6 +4,7 @@
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include "base/android/orderfile/orderfile_buildflags.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
@@ -15,6 +16,7 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "components/viz/common/features.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"
@@ -26,10 +28,15 @@
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/ipc/in_process_command_buffer.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h"
#include "services/service_manager/runner/common/client_util.h"
#include "ui/base/ui_base_features.h"
+#if defined(OS_MACOSX)
+#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
+#endif
+
namespace content {
#if defined(OS_ANDROID)
@@ -105,7 +112,13 @@ BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest(
gpu_client_id_(gpu_client_id),
gpu_client_tracing_id_(gpu_client_tracing_id),
finished_(false),
- main_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
+#if defined(OS_MACOSX)
+ main_task_runner_(ui::WindowResizeHelperMac::Get()->task_runner())
+#else
+ main_task_runner_(base::ThreadTaskRunnerHandle::Get())
+#endif
+{
+}
void BrowserGpuChannelHostFactory::EstablishRequest::RestartTimeout() {
BrowserGpuChannelHostFactory* factory =
@@ -273,7 +286,7 @@ BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() {
void BrowserGpuChannelHostFactory::EstablishGpuChannel(
gpu::GpuChannelEstablishedCallback callback) {
#if defined(USE_AURA)
- DCHECK(!base::FeatureList::IsEnabled(::features::kMash));
+ DCHECK(features::IsAshInBrowserProcess());
#endif
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (gpu_channel_.get() && gpu_channel_->IsLost()) {
@@ -352,7 +365,7 @@ void BrowserGpuChannelHostFactory::RestartTimeout() {
return;
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
- defined(CYGPROFILE_INSTRUMENTATION)
+ BUILDFLAG(ORDERFILE_INSTRUMENTATION)
constexpr int64_t kGpuChannelTimeoutInSeconds = 40;
#else
// The GPU watchdog timeout is 15 seconds (1.5x the kGpuTimeout value due to
@@ -371,6 +384,10 @@ void BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO(
int gpu_client_id,
const base::FilePath& cache_dir) {
GetShaderCacheFactorySingleton()->SetCacheInfo(gpu_client_id, cache_dir);
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) {
+ GetShaderCacheFactorySingleton()->SetCacheInfo(
+ gpu::InProcessCommandBuffer::kGpuClientId, cache_dir);
+ }
}
} // namespace content
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 22d03d380b4..8568d3f5885 100644
--- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
+++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
@@ -141,7 +141,7 @@ void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess(
auto handle = gpu::GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer(
id, size, format, usage);
buffers.find(id)->second.shared_memory_guid = handle.handle.GetGUID();
- std::move(callback).Run(handle);
+ std::move(callback).Run(std::move(handle));
}
void BrowserGpuMemoryBufferManager::SetDestructionSyncToken(
@@ -310,7 +310,7 @@ void BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferOnIO(
void BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO(
CreateGpuMemoryBufferRequest* request,
- const gfx::GpuMemoryBufferHandle& handle) {
+ gfx::GpuMemoryBufferHandle handle) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Early out if factory failed to create the buffer.
@@ -321,15 +321,16 @@ void BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO(
// Note: Unretained is safe as IO thread is stopped before manager is
// destroyed.
+ auto handle_id = handle.id;
request->result =
gpu_memory_buffer_support_->CreateGpuMemoryBufferImplFromHandle(
- handle, request->size, request->format, request->usage,
+ std::move(handle), request->size, request->format, request->usage,
base::Bind(
&GpuMemoryBufferDeleted,
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
base::Bind(
&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO,
- base::Unretained(this), handle.id, request->client_id)));
+ base::Unretained(this), handle_id, request->client_id)));
request->event.Signal();
}
@@ -377,7 +378,7 @@ void BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO(
int client_id,
int gpu_host_id,
CreateCallback callback,
- const gfx::GpuMemoryBufferHandle& handle,
+ gfx::GpuMemoryBufferHandle handle,
GpuProcessHost::BufferCreationStatus status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -432,7 +433,7 @@ void BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO(
buffer_it->second.gpu_host_id = gpu_host_id;
buffer_it->second.shared_memory_guid = handle.handle.GetGUID();
- std::move(callback).Run(handle);
+ std::move(callback).Run(std::move(handle));
}
void BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO(
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 41843a9309c..4cf2b632fb0 100644
--- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
+++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
@@ -33,7 +33,7 @@ class CONTENT_EXPORT BrowserGpuMemoryBufferManager
public base::trace_event::MemoryDumpProvider {
public:
using CreateCallback =
- base::OnceCallback<void(const gfx::GpuMemoryBufferHandle& handle)>;
+ base::OnceCallback<void(gfx::GpuMemoryBufferHandle handle)>;
using AllocationCallback = CreateCallback;
BrowserGpuMemoryBufferManager(int gpu_client_id,
@@ -98,9 +98,8 @@ class CONTENT_EXPORT BrowserGpuMemoryBufferManager
// Functions that handle synchronous buffer creation requests.
void HandleCreateGpuMemoryBufferOnIO(CreateGpuMemoryBufferRequest* request);
- void HandleGpuMemoryBufferCreatedOnIO(
- CreateGpuMemoryBufferRequest* request,
- const gfx::GpuMemoryBufferHandle& handle);
+ void HandleGpuMemoryBufferCreatedOnIO(CreateGpuMemoryBufferRequest* request,
+ gfx::GpuMemoryBufferHandle handle);
// Functions that implement asynchronous buffer creation.
void CreateGpuMemoryBufferOnIO(gfx::GpuMemoryBufferId id,
@@ -115,7 +114,7 @@ class CONTENT_EXPORT BrowserGpuMemoryBufferManager
int client_id,
int gpu_host_id,
CreateCallback callback,
- const gfx::GpuMemoryBufferHandle& handle,
+ gfx::GpuMemoryBufferHandle handle,
GpuProcessHost::BufferCreationStatus status);
void DestroyGpuMemoryBufferOnIO(gfx::GpuMemoryBufferId id,
int client_id,
diff --git a/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc b/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc
new file mode 100644
index 00000000000..8f3efa6a705
--- /dev/null
+++ b/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc
@@ -0,0 +1,115 @@
+// Copyright 2018 The Chromium Authors. All rights 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/ca_transaction_gpu_coordinator.h"
+
+#include "base/cancelable_callback.h"
+#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
+#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
+#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
+
+namespace content {
+
+// static
+scoped_refptr<CATransactionGPUCoordinator> CATransactionGPUCoordinator::Create(
+ GpuProcessHost* host) {
+ scoped_refptr<CATransactionGPUCoordinator> result(
+ new CATransactionGPUCoordinator(host));
+ // Avoid modifying result's refcount in the constructor by performing this
+ // PostTask afterward.
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ui::WindowResizeHelperMac::Get()->task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &CATransactionGPUCoordinator::AddPostCommitObserverOnUIThread,
+ result));
+ return result;
+}
+
+CATransactionGPUCoordinator::CATransactionGPUCoordinator(GpuProcessHost* host)
+ : host_(host) {}
+
+CATransactionGPUCoordinator::~CATransactionGPUCoordinator() {
+ DCHECK(!host_);
+ DCHECK(!registered_as_observer_);
+}
+
+void CATransactionGPUCoordinator::HostWillBeDestroyed() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ui::WindowResizeHelperMac::Get()->task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &CATransactionGPUCoordinator::RemovePostCommitObserverOnUIThread,
+ this));
+ host_ = nullptr;
+}
+
+void CATransactionGPUCoordinator::AddPostCommitObserverOnUIThread() {
+ DCHECK(!registered_as_observer_);
+ ui::CATransactionCoordinator::Get().AddPostCommitObserver(this);
+ registered_as_observer_ = true;
+}
+
+void CATransactionGPUCoordinator::RemovePostCommitObserverOnUIThread() {
+ DCHECK(registered_as_observer_);
+ ui::CATransactionCoordinator::Get().RemovePostCommitObserver(this);
+ registered_as_observer_ = false;
+}
+
+void CATransactionGPUCoordinator::OnActivateForTransaction() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&CATransactionGPUCoordinator::OnActivateForTransactionOnIO,
+ this));
+}
+
+void CATransactionGPUCoordinator::OnEnterPostCommit() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // If HostWillBeDestroyed() is called during a commit, pending_commit_count_
+ // may be left non-zero. That's fine as long as this instance is destroyed
+ // (and removed from the list of post-commit observers) soon after.
+ pending_commit_count_++;
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&CATransactionGPUCoordinator::OnEnterPostCommitOnIO,
+ this));
+}
+
+bool CATransactionGPUCoordinator::ShouldWaitInPostCommit() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return pending_commit_count_ > 0;
+}
+
+void CATransactionGPUCoordinator::OnActivateForTransactionOnIO() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (host_)
+ host_->gpu_service()->BeginCATransaction();
+}
+
+void CATransactionGPUCoordinator::OnEnterPostCommitOnIO() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (host_)
+ host_->gpu_service()->CommitCATransaction(base::BindOnce(
+ &CATransactionGPUCoordinator::OnCommitCompletedOnIO, this));
+}
+
+void CATransactionGPUCoordinator::OnCommitCompletedOnIO() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ui::WindowResizeHelperMac::Get()->task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&CATransactionGPUCoordinator::OnCommitCompletedOnUI,
+ this));
+}
+
+void CATransactionGPUCoordinator::OnCommitCompletedOnUI() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ pending_commit_count_--;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.h b/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.h
new file mode 100644
index 00000000000..53b52a25d3f
--- /dev/null
+++ b/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.h
@@ -0,0 +1,60 @@
+// Copyright 2018 The Chromium Authors. All 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_CA_TRANSACTION_GPU_COORDINATOR_H_
+#define CONTENT_BROWSER_GPU_CA_TRANSACTION_GPU_COORDINATOR_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
+
+#include <memory>
+
+namespace content {
+
+class GpuProcessHost;
+
+// Synchronizes CATransaction commits between the browser and GPU processes.
+class CATransactionGPUCoordinator
+ : public ui::CATransactionCoordinator::PostCommitObserver {
+ public:
+ static scoped_refptr<CATransactionGPUCoordinator> Create(
+ GpuProcessHost* host);
+ void HostWillBeDestroyed();
+
+ private:
+ friend class base::RefCountedThreadSafe<CATransactionGPUCoordinator>;
+ CATransactionGPUCoordinator(GpuProcessHost* host);
+ ~CATransactionGPUCoordinator() override;
+
+ // ui::CATransactionObserver implementation
+ void OnActivateForTransaction() override;
+ void OnEnterPostCommit() override;
+ bool ShouldWaitInPostCommit() override;
+
+ void AddPostCommitObserverOnUIThread();
+ void RemovePostCommitObserverOnUIThread();
+
+ void OnActivateForTransactionOnIO();
+ void OnEnterPostCommitOnIO();
+ void OnCommitCompletedOnIO();
+ void OnCommitCompletedOnUI();
+
+ // The GpuProcessHost to use to initiate GPU-side CATransactions. This is only
+ // to be accessed on the IO thread.
+ GpuProcessHost* host_ = nullptr;
+
+ // The number CATransactions that have not yet completed. This is only to be
+ // accessed on the UI thread.
+ int pending_commit_count_ = 0;
+
+ // Egregious state tracking to debug https://crbug.com/871430
+ bool registered_as_observer_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(CATransactionGPUCoordinator);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GPU_CA_TRANSACTION_GPU_COORDINATOR_H_
diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc
index db3b6606770..9773ec885ea 100644
--- a/chromium/content/browser/gpu/compositor_util.cc
+++ b/chromium/content/browser/gpu/compositor_util.cc
@@ -161,6 +161,13 @@ const GpuFeatureData GetGpuFeatureData(
"Accelerated rasterization has been disabled, either via blacklist, "
"about:flags or the command line.",
true, true},
+ {"oop_rasterization",
+ SafeGetFeatureStatus(gpu_feature_info,
+ gpu::GPU_FEATURE_TYPE_OOP_RASTERIZATION),
+ command_line.HasSwitch(switches::kDisableOopRasterization),
+ "Out-of-process accelerated rasterization has been disabled, either "
+ "via blacklist, about:flags or the command line.",
+ false, true},
{"multiple_raster_threads", gpu::kGpuFeatureStatusEnabled,
NumberOfRendererRasterThreads() == 1, "Raster is using a single thread.",
false, true},
@@ -215,8 +222,12 @@ std::unique_ptr<base::DictionaryValue> GetFeatureStatusImpl(
const GpuFeatureData gpu_feature_data =
GetGpuFeatureData(gpu_feature_info, type, i, &eof);
std::string status;
- if (gpu_feature_data.disabled || gpu_access_blocked ||
- gpu_feature_data.status == gpu::kGpuFeatureStatusDisabled) {
+ if (gpu_feature_data.name == "surface_synchronization") {
+ status = (!gpu_feature_data.disabled ? "enabled_on" : "disabled_off");
+ } else if (gpu_feature_data.name == "viz_display_compositor") {
+ status = (!gpu_feature_data.disabled ? "enabled_on" : "disabled_off");
+ } else if (gpu_feature_data.disabled || gpu_access_blocked ||
+ gpu_feature_data.status == gpu::kGpuFeatureStatusDisabled) {
status = "disabled";
if (gpu_feature_data.fallback_to_software)
status += "_software";
@@ -244,14 +255,6 @@ std::unique_ptr<base::DictionaryValue> GetFeatureStatusImpl(
status += "_force";
status += "_on";
}
- if (gpu_feature_data.name == "surface_synchronization") {
- if (features::IsSurfaceSynchronizationEnabled())
- status += "_on";
- }
- if (gpu_feature_data.name == "viz_display_compositor") {
- if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor))
- status += "_on";
- }
if (gpu_feature_data.name == "skia_renderer") {
if (features::IsUsingSkiaRenderer())
status += "_on";
diff --git a/chromium/content/browser/gpu/gpu_client_impl.cc b/chromium/content/browser/gpu/gpu_client_impl.cc
index a591794d329..c2ef9591cd3 100644
--- a/chromium/content/browser/gpu/gpu_client_impl.cc
+++ b/chromium/content/browser/gpu/gpu_client_impl.cc
@@ -7,7 +7,6 @@
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/common/child_process_host_impl.h"
-#include "content/public/browser/browser_thread.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/gpu_memory_buffer_impl.h"
#include "gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h"
@@ -15,51 +14,67 @@
namespace content {
// static
-std::unique_ptr<GpuClient, BrowserThread::DeleteOnIOThread> GpuClient::Create(
+std::unique_ptr<GpuClient, base::OnTaskRunnerDeleter> GpuClient::Create(
ui::mojom::GpuRequest request,
- ConnectionErrorHandlerClosure connection_error_handler) {
- std::unique_ptr<GpuClientImpl, BrowserThread::DeleteOnIOThread> gpu_client(
- new GpuClientImpl(ChildProcessHostImpl::GenerateChildProcessUniqueId()));
+ ConnectionErrorHandlerClosure connection_error_handler,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ const int client_id = ChildProcessHostImpl::GenerateChildProcessUniqueId();
+ const uint64_t client_tracing_id =
+ ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(client_id);
+ std::unique_ptr<GpuClientImpl, base::OnTaskRunnerDeleter> gpu_client(
+ new GpuClientImpl(client_id, client_tracing_id, task_runner),
+ base::OnTaskRunnerDeleter(task_runner));
gpu_client->SetConnectionErrorHandler(std::move(connection_error_handler));
gpu_client->Add(std::move(request));
return gpu_client;
}
-GpuClientImpl::GpuClientImpl(int render_process_id)
- : render_process_id_(render_process_id), weak_factory_(this) {
- bindings_.set_connection_error_handler(
- base::Bind(&GpuClientImpl::OnError, base::Unretained(this),
- ErrorReason::kConnectionLost));
+GpuClientImpl::GpuClientImpl(
+ int client_id,
+ uint64_t client_tracing_id,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : client_id_(client_id),
+ client_tracing_id_(client_tracing_id),
+ task_runner_(std::move(task_runner)),
+ weak_factory_(this) {
+ gpu_bindings_.set_connection_error_handler(
+ base::BindRepeating(&GpuClientImpl::OnError, base::Unretained(this),
+ ErrorReason::kConnectionLost));
}
GpuClientImpl::~GpuClientImpl() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- bindings_.CloseAllBindings();
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ gpu_bindings_.CloseAllBindings();
OnError(ErrorReason::kInDestructor);
}
void GpuClientImpl::Add(ui::mojom::GpuRequest request) {
- bindings_.AddBinding(this, std::move(request));
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ gpu_bindings_.AddBinding(this, std::move(request));
}
void GpuClientImpl::OnError(ErrorReason reason) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
ClearCallback();
- if (bindings_.empty()) {
+ if (gpu_bindings_.empty()) {
BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager =
BrowserGpuMemoryBufferManager::current();
if (gpu_memory_buffer_manager)
- gpu_memory_buffer_manager->ProcessRemoved(render_process_id_);
+ gpu_memory_buffer_manager->ProcessRemoved(client_id_);
}
if (reason == ErrorReason::kConnectionLost && connection_error_handler_)
std::move(connection_error_handler_).Run(this);
}
void GpuClientImpl::PreEstablishGpuChannel() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&GpuClientImpl::EstablishGpuChannel,
- base::Unretained(this), EstablishGpuChannelCallback()));
+ if (task_runner_->RunsTasksInCurrentSequence()) {
+ EstablishGpuChannel(EstablishGpuChannelCallback());
+ } else {
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&GpuClientImpl::EstablishGpuChannel,
+ base::Unretained(this), EstablishGpuChannelCallback()));
+ }
}
void GpuClientImpl::SetConnectionErrorHandler(
@@ -85,8 +100,8 @@ void GpuClientImpl::OnEstablishGpuChannel(
}
if (callback) {
// A request is waiting.
- std::move(callback).Run(render_process_id_, std::move(channel_handle),
- gpu_info, gpu_feature_info);
+ std::move(callback).Run(client_id_, std::move(channel_handle), gpu_info,
+ gpu_feature_info);
return;
}
if (status == GpuProcessHost::EstablishChannelStatus::SUCCESS) {
@@ -100,21 +115,21 @@ void GpuClientImpl::OnEstablishGpuChannel(
void GpuClientImpl::OnCreateGpuMemoryBuffer(
CreateGpuMemoryBufferCallback callback,
- const gfx::GpuMemoryBufferHandle& handle) {
- std::move(callback).Run(handle);
+ gfx::GpuMemoryBufferHandle handle) {
+ std::move(callback).Run(std::move(handle));
}
void GpuClientImpl::ClearCallback() {
if (!callback_)
return;
EstablishGpuChannelCallback callback = std::move(callback_);
- std::move(callback).Run(render_process_id_, mojo::ScopedMessagePipeHandle(),
+ std::move(callback).Run(client_id_, mojo::ScopedMessagePipeHandle(),
gpu::GPUInfo(), gpu::GpuFeatureInfo());
DCHECK(!callback_);
}
void GpuClientImpl::EstablishGpuChannel(EstablishGpuChannelCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
// At most one channel should be requested. So clear previous request first.
ClearCallback();
if (channel_handle_.is_valid()) {
@@ -123,8 +138,8 @@ void GpuClientImpl::EstablishGpuChannel(EstablishGpuChannelCallback callback) {
// 2) if callback is empty, it's PreEstablishGpyChannel() being called
// more than once, no need to do anything.
if (callback) {
- std::move(callback).Run(render_process_id_, std::move(channel_handle_),
- gpu_info_, gpu_feature_info_);
+ std::move(callback).Run(client_id_, std::move(channel_handle_), gpu_info_,
+ gpu_feature_info_);
DCHECK(!channel_handle_.is_valid());
}
return;
@@ -132,9 +147,8 @@ void GpuClientImpl::EstablishGpuChannel(EstablishGpuChannelCallback callback) {
GpuProcessHost* host = GpuProcessHost::Get();
if (!host) {
if (callback) {
- std::move(callback).Run(render_process_id_,
- mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
- gpu::GpuFeatureInfo());
+ std::move(callback).Run(client_id_, mojo::ScopedMessagePipeHandle(),
+ gpu::GPUInfo(), gpu::GpuFeatureInfo());
}
return;
}
@@ -146,12 +160,10 @@ void GpuClientImpl::EstablishGpuChannel(EstablishGpuChannelCallback callback) {
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(&GpuClientImpl::OnEstablishGpuChannel,
- weak_factory_.GetWeakPtr()));
+ client_id_, client_tracing_id_, preempts, allow_view_command_buffers,
+ allow_real_time_streams,
+ base::BindRepeating(&GpuClientImpl::OnEstablishGpuChannel,
+ weak_factory_.GetWeakPtr()));
}
void GpuClientImpl::CreateJpegDecodeAccelerator(
@@ -175,7 +187,7 @@ void GpuClientImpl::CreateGpuMemoryBuffer(
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- ui::mojom::Gpu::CreateGpuMemoryBufferCallback callback) {
+ ui::mojom::GpuMemoryBufferFactory::CreateGpuMemoryBufferCallback callback) {
DCHECK(BrowserGpuMemoryBufferManager::current());
base::CheckedNumeric<int> bytes = size.width();
@@ -187,7 +199,7 @@ void GpuClientImpl::CreateGpuMemoryBuffer(
BrowserGpuMemoryBufferManager::current()
->AllocateGpuMemoryBufferForChildProcess(
- id, size, format, usage, render_process_id_,
+ id, size, format, usage, client_id_,
base::BindOnce(&GpuClientImpl::OnCreateGpuMemoryBuffer,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
@@ -197,7 +209,12 @@ void GpuClientImpl::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
DCHECK(BrowserGpuMemoryBufferManager::current());
BrowserGpuMemoryBufferManager::current()->ChildProcessDeletedGpuMemoryBuffer(
- id, render_process_id_, sync_token);
+ id, client_id_, sync_token);
+}
+
+void GpuClientImpl::CreateGpuMemoryBufferFactory(
+ ui::mojom::GpuMemoryBufferFactoryRequest request) {
+ gpu_memory_buffer_factory_bindings_.AddBinding(this, std::move(request));
}
} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_client_impl.h b/chromium/content/browser/gpu/gpu_client_impl.h
index 03e29bf4b5f..70e684a68be 100644
--- a/chromium/content/browser/gpu/gpu_client_impl.h
+++ b/chromium/content/browser/gpu/gpu_client_impl.h
@@ -13,11 +13,19 @@
namespace content {
-class GpuClientImpl : public ui::mojom::Gpu, public GpuClient {
+class GpuClientImpl : public ui::mojom::GpuMemoryBufferFactory,
+ public ui::mojom::Gpu,
+ public GpuClient {
public:
- explicit GpuClientImpl(int render_process_id);
+ // GpuClientImpl must be destroyed on the thread associated with
+ // |task_runner|.
+ GpuClientImpl(int client_id,
+ uint64_t client_tracing_id,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+
~GpuClientImpl() override;
+ // This needs to be run on the thread associated with |task_runner_|.
void Add(ui::mojom::GpuRequest request);
void PreEstablishGpuChannel();
@@ -25,6 +33,27 @@ class GpuClientImpl : public ui::mojom::Gpu, public GpuClient {
void SetConnectionErrorHandler(
ConnectionErrorHandlerClosure connection_error_handler);
+ // ui::mojom::GpuMemoryBufferFactory overrides:
+ void CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::BufferFormat format,
+ gfx::BufferUsage usage,
+ ui::mojom::GpuMemoryBufferFactory::CreateGpuMemoryBufferCallback callback)
+ override;
+ void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
+ const gpu::SyncToken& sync_token) override;
+
+ // ui::mojom::Gpu overrides:
+ void CreateGpuMemoryBufferFactory(
+ ui::mojom::GpuMemoryBufferFactoryRequest request) override;
+ void EstablishGpuChannel(EstablishGpuChannelCallback callback) override;
+ void CreateJpegDecodeAccelerator(
+ media::mojom::JpegDecodeAcceleratorRequest jda_request) override;
+ void CreateVideoEncodeAcceleratorProvider(
+ media::mojom::VideoEncodeAcceleratorProviderRequest vea_provider_request)
+ override;
+
private:
enum class ErrorReason {
// OnError() is being called from the destructor.
@@ -38,33 +67,24 @@ class GpuClientImpl : public ui::mojom::Gpu, public GpuClient {
const gpu::GpuFeatureInfo& gpu_feature_info,
GpuProcessHost::EstablishChannelStatus status);
void OnCreateGpuMemoryBuffer(CreateGpuMemoryBufferCallback callback,
- const gfx::GpuMemoryBufferHandle& handle);
+ gfx::GpuMemoryBufferHandle handle);
void ClearCallback();
- // ui::mojom::Gpu overrides:
- void EstablishGpuChannel(EstablishGpuChannelCallback callback) override;
- void CreateJpegDecodeAccelerator(
- media::mojom::JpegDecodeAcceleratorRequest jda_request) override;
- void CreateVideoEncodeAcceleratorProvider(
- media::mojom::VideoEncodeAcceleratorProviderRequest vea_provider_request)
- override;
- void CreateGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- ui::mojom::Gpu::CreateGpuMemoryBufferCallback callback) override;
- void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- const gpu::SyncToken& sync_token) override;
-
- const int render_process_id_;
- mojo::BindingSet<ui::mojom::Gpu> bindings_;
+ const int client_id_;
+ const uint64_t client_tracing_id_;
+ mojo::BindingSet<ui::mojom::GpuMemoryBufferFactory>
+ gpu_memory_buffer_factory_bindings_;
+ mojo::BindingSet<ui::mojom::Gpu> gpu_bindings_;
bool gpu_channel_requested_ = false;
EstablishGpuChannelCallback callback_;
mojo::ScopedMessagePipeHandle channel_handle_;
gpu::GPUInfo gpu_info_;
gpu::GpuFeatureInfo gpu_feature_info_;
ConnectionErrorHandlerClosure connection_error_handler_;
+ // |task_runner_| is associated with the thread |gpu_bindings_| is bound on.
+ // GpuClientImpl instance is bound to this thread, and must be destroyed on
+ // this thread.
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::WeakPtrFactory<GpuClientImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(GpuClientImpl);
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.cc b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
index 3c8b665a48a..f6d3d4c18f1 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
@@ -16,7 +16,8 @@ GpuDataManager* GpuDataManager::GetInstance() {
// static
GpuDataManagerImpl* GpuDataManagerImpl::GetInstance() {
- return base::Singleton<GpuDataManagerImpl>::get();
+ static base::NoDestructor<GpuDataManagerImpl> instance;
+ return instance.get();
}
void GpuDataManagerImpl::BlacklistWebGLForTesting() {
@@ -79,16 +80,6 @@ void GpuDataManagerImpl::DisableHardwareAcceleration() {
private_->DisableHardwareAcceleration();
}
-void GpuDataManagerImpl::BlockSwiftShader() {
- base::AutoLock auto_lock(lock_);
- private_->BlockSwiftShader();
-}
-
-bool GpuDataManagerImpl::SwiftShaderAllowed() const {
- base::AutoLock auto_lock(lock_);
- return private_->SwiftShaderAllowed();
-}
-
bool GpuDataManagerImpl::HardwareAccelerationEnabled() const {
base::AutoLock auto_lock(lock_);
return private_->HardwareAccelerationEnabled();
@@ -207,9 +198,14 @@ void GpuDataManagerImpl::NotifyGpuInfoUpdate() {
private_->NotifyGpuInfoUpdate();
}
-void GpuDataManagerImpl::OnGpuProcessInitFailure() {
+gpu::GpuMode GpuDataManagerImpl::GetGpuMode() const {
+ base::AutoLock auto_lock(lock_);
+ return private_->GetGpuMode();
+}
+
+void GpuDataManagerImpl::FallBackToNextGpuMode() {
base::AutoLock auto_lock(lock_);
- private_->OnGpuProcessInitFailure();
+ private_->FallBackToNextGpuMode();
}
bool GpuDataManagerImpl::IsGpuProcessUsingHardwareGpu() const {
@@ -217,11 +213,14 @@ bool GpuDataManagerImpl::IsGpuProcessUsingHardwareGpu() const {
return private_->IsGpuProcessUsingHardwareGpu();
}
-GpuDataManagerImpl::GpuDataManagerImpl()
- : private_(GpuDataManagerImplPrivate::Create(this)) {
+void GpuDataManagerImpl::SetApplicationVisible(bool is_visible) {
+ base::AutoLock auto_lock(lock_);
+ private_->SetApplicationVisible(is_visible);
}
-GpuDataManagerImpl::~GpuDataManagerImpl() {
-}
+GpuDataManagerImpl::GpuDataManagerImpl()
+ : private_(std::make_unique<GpuDataManagerImplPrivate>(this)) {}
+
+GpuDataManagerImpl::~GpuDataManagerImpl() = default;
} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.h b/chromium/content/browser/gpu/gpu_data_manager_impl.h
index 06210a34e80..d91d77659f3 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.h
@@ -14,7 +14,7 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/singleton.h"
+#include "base/no_destructor.h"
#include "base/process/kill.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
@@ -24,6 +24,7 @@
#include "gpu/config/gpu_control_list.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_info.h"
+#include "gpu/config/gpu_mode.h"
class GURL;
@@ -149,44 +150,27 @@ class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
// status update.
void NotifyGpuInfoUpdate();
- // Called when GPU process initialization failed.
- void OnGpuProcessInitFailure();
+ // Return mode describing what the GPU process will be launched to run.
+ gpu::GpuMode GetGpuMode() const;
- void BlockSwiftShader();
- bool SwiftShaderAllowed() const;
+ // Called when GPU process initialization failed or the GPU process has
+ // crashed repeatedly. This will try to disable hardware acceleration and then
+ // SwiftShader WebGL. It will also crash the browser process as a last resort
+ // on Android and Chrome OS.
+ void FallBackToNextGpuMode();
// Returns false if the latest GPUInfo gl_renderer is from SwiftShader or
// Disabled (in the viz case).
bool IsGpuProcessUsingHardwareGpu() const;
+ // State tracking allows us to customize GPU process launch depending on
+ // whether we are in the foreground or background.
+ void SetApplicationVisible(bool is_visible);
+
private:
friend class GpuDataManagerImplPrivate;
friend class GpuDataManagerImplPrivateTest;
- friend struct base::DefaultSingletonTraits<GpuDataManagerImpl>;
-
- // It's similar to AutoUnlock, but we want to make it a no-op
- // if the owner GpuDataManagerImpl is null.
- // This should only be used by GpuDataManagerImplPrivate where
- // callbacks are called, during which re-entering
- // GpuDataManagerImpl is possible.
- class UnlockedSession {
- public:
- explicit UnlockedSession(GpuDataManagerImpl* owner)
- : owner_(owner) {
- DCHECK(owner_);
- owner_->lock_.AssertAcquired();
- owner_->lock_.Release();
- }
-
- ~UnlockedSession() {
- DCHECK(owner_);
- owner_->lock_.Acquire();
- }
-
- private:
- GpuDataManagerImpl* owner_;
- DISALLOW_COPY_AND_ASSIGN(UnlockedSession);
- };
+ friend class base::NoDestructor<GpuDataManagerImpl>;
GpuDataManagerImpl();
~GpuDataManagerImpl() override;
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 e3b41337158..63797576500 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -32,17 +32,16 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
-#include "gpu/command_buffer/service/gpu_preferences.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/gpu_blacklist.h"
#include "gpu/config/gpu_driver_bug_list.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_info_collector.h"
+#include "gpu/config/gpu_preferences.h"
#include "gpu/config/gpu_switches.h"
#include "gpu/config/gpu_util.h"
#include "gpu/config/software_rendering_list_autogen.h"
-#include "gpu/ipc/common/gpu_preferences_util.h"
#include "gpu/ipc/common/memory_stats.h"
#include "gpu/ipc/host/gpu_memory_buffer_support.h"
#include "gpu/ipc/host/shader_disk_cache.h"
@@ -118,18 +117,21 @@ void UpdateFeatureStats(const gpu::GpuFeatureInfo& gpu_feature_info) {
gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS,
gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING,
gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION,
+ gpu::GPU_FEATURE_TYPE_OOP_RASTERIZATION,
gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL,
gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL2};
const std::string kGpuBlacklistFeatureHistogramNames[] = {
"GPU.BlacklistFeatureTestResults.Accelerated2dCanvas",
"GPU.BlacklistFeatureTestResults.GpuCompositing",
"GPU.BlacklistFeatureTestResults.GpuRasterization",
+ "GPU.BlacklistFeatureTestResults.OopRasterization",
"GPU.BlacklistFeatureTestResults.Webgl",
"GPU.BlacklistFeatureTestResults.Webgl2"};
const bool kGpuFeatureUserFlags[] = {
command_line.HasSwitch(switches::kDisableAccelerated2dCanvas),
command_line.HasSwitch(switches::kDisableGpu),
command_line.HasSwitch(switches::kDisableGpuRasterization),
+ command_line.HasSwitch(switches::kDisableOopRasterization),
command_line.HasSwitch(switches::kDisableWebGL),
(command_line.HasSwitch(switches::kDisableWebGL) ||
command_line.HasSwitch(switches::kDisableWebGL2))};
@@ -138,6 +140,7 @@ void UpdateFeatureStats(const gpu::GpuFeatureInfo& gpu_feature_info) {
"GPU.BlacklistFeatureTestResultsWindows2.Accelerated2dCanvas",
"GPU.BlacklistFeatureTestResultsWindows2.GpuCompositing",
"GPU.BlacklistFeatureTestResultsWindows2.GpuRasterization",
+ "GPU.BlacklistFeatureTestResultsWindows2.OopRasterization",
"GPU.BlacklistFeatureTestResultsWindows2.Webgl",
"GPU.BlacklistFeatureTestResultsWindows2.Webgl2"};
#endif
@@ -263,6 +266,35 @@ void UpdateGpuInfoOnIO(const gpu::GPUInfo& gpu_info) {
} // anonymous namespace
+GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(GpuDataManagerImpl* owner)
+ : owner_(owner),
+ observer_list_(base::MakeRefCounted<GpuDataManagerObserverList>()) {
+ DCHECK(owner_);
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kDisableGpu))
+ DisableHardwareAcceleration();
+
+ if (command_line->HasSwitch(switches::kSingleProcess) ||
+ command_line->HasSwitch(switches::kInProcessGPU)) {
+ in_process_gpu_ = true;
+ AppendGpuCommandLine(command_line);
+ }
+
+#if defined(OS_MACOSX)
+ CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_);
+#endif // OS_MACOSX
+
+ // For testing only.
+ if (command_line->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs))
+ domain_blocking_enabled_ = false;
+}
+
+GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
+#if defined(OS_MACOSX)
+ CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_);
+#endif
+}
+
void GpuDataManagerImplPrivate::BlacklistWebGLForTesting() {
// This function is for testing only, so disable histograms.
update_histograms_ = false;
@@ -286,8 +318,7 @@ gpu::GPUInfo GpuDataManagerImplPrivate::GetGPUInfoForHardwareGpu() const {
return gpu_info_for_hardware_gpu_;
}
-bool GpuDataManagerImplPrivate::GpuAccessAllowed(
- std::string* reason) const {
+bool GpuDataManagerImplPrivate::GpuAccessAllowed(std::string* reason) const {
bool swiftshader_available = false;
#if BUILDFLAG(ENABLE_SWIFTSHADER)
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -322,8 +353,19 @@ bool GpuDataManagerImplPrivate::GpuAccessAllowed(
}
bool GpuDataManagerImplPrivate::GpuProcessStartAllowed() const {
- return base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- GpuAccessAllowed(nullptr);
+ if (GpuAccessAllowed(nullptr))
+ return true;
+
+#if defined(USE_X11) || defined(OS_MACOSX)
+ // If GPU access is disabled with OOP-D we run the display compositor in:
+ // Browser process: Windows
+ // GPU process: Linux and Mac
+ // N/A: Android and Chrome OS (GPU access can't be disabled)
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor))
+ return true;
+#endif
+
+ return false;
}
void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
@@ -395,13 +437,11 @@ void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate(
}
void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver* observer) {
- GpuDataManagerImpl::UnlockedSession session(owner_);
observer_list_->AddObserver(observer);
}
void GpuDataManagerImplPrivate::RemoveObserver(
GpuDataManagerObserver* observer) {
- GpuDataManagerImpl::UnlockedSession session(owner_);
observer_list_->RemoveObserver(observer);
}
@@ -514,7 +554,7 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
gpu::GpuPreferences gpu_prefs = GetGpuPreferencesFromCommandLine();
UpdateGpuPreferences(&gpu_prefs);
command_line->AppendSwitchASCII(switches::kGpuPreferences,
- gpu::GpuPreferencesToSwitchValue(gpu_prefs));
+ gpu_prefs.ToSwitchValue());
std::string use_gl;
if (card_disabled_ && SwiftShaderAllowed()) {
@@ -560,6 +600,8 @@ void GpuDataManagerImplPrivate::UpdateGpuPreferences(
gpu_preferences->texture_target_exception_list =
gpu::CreateBufferUsageAndFormatExceptionList();
+
+ gpu_preferences->watchdog_starts_backgrounded = !application_is_visible_;
}
void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
@@ -572,11 +614,6 @@ bool GpuDataManagerImplPrivate::HardwareAccelerationEnabled() const {
return !card_disabled_;
}
-void GpuDataManagerImplPrivate::BlockSwiftShader() {
- swiftshader_blocked_ = true;
- OnGpuBlocked();
-}
-
bool GpuDataManagerImplPrivate::SwiftShaderAllowed() const {
#if !BUILDFLAG(ENABLE_SWIFTSHADER)
return false;
@@ -613,27 +650,15 @@ void GpuDataManagerImplPrivate::AddLogMessage(
void GpuDataManagerImplPrivate::ProcessCrashed(
base::TerminationStatus exit_code) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- // Unretained is ok, because it's posted to UI thread, the thread
- // where the singleton GpuDataManagerImpl lives until the end.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&GpuDataManagerImpl::ProcessCrashed,
- base::Unretained(owner_), exit_code));
- return;
- }
- {
- GpuDataManagerImpl::UnlockedSession session(owner_);
- observer_list_->Notify(
- FROM_HERE, &GpuDataManagerObserver::OnGpuProcessCrashed, exit_code);
- }
+ observer_list_->Notify(
+ FROM_HERE, &GpuDataManagerObserver::OnGpuProcessCrashed, exit_code);
}
std::unique_ptr<base::ListValue> GpuDataManagerImplPrivate::GetLogMessages()
const {
auto value = std::make_unique<base::ListValue>();
for (size_t ii = 0; ii < log_messages_.size(); ++ii) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ auto dict = std::make_unique<base::DictionaryValue>();
dict->SetInteger("level", log_messages_[ii].level);
dict->SetString("header", log_messages_[ii].header);
dict->SetString("message", log_messages_[ii].message);
@@ -643,7 +668,7 @@ std::unique_ptr<base::ListValue> GpuDataManagerImplPrivate::GetLogMessages()
}
void GpuDataManagerImplPrivate::HandleGpuSwitch() {
- GpuDataManagerImpl::UnlockedSession session(owner_);
+ base::AutoUnlock unlock(owner_->lock_);
// Notify observers in the browser process.
ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
// Pass the notification to the GPU process to notify observers there.
@@ -701,48 +726,6 @@ void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() {
domain_blocking_enabled_ = false;
}
-// static
-GpuDataManagerImplPrivate* GpuDataManagerImplPrivate::Create(
- GpuDataManagerImpl* owner) {
- return new GpuDataManagerImplPrivate(owner);
-}
-
-GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(GpuDataManagerImpl* owner)
- : complete_gpu_info_already_requested_(false),
- observer_list_(new GpuDataManagerObserverList),
- card_disabled_(false),
- swiftshader_blocked_(false),
- update_histograms_(true),
- domain_blocking_enabled_(true),
- owner_(owner),
- in_process_gpu_(false) {
- DCHECK(owner_);
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kDisableGpu))
- DisableHardwareAcceleration();
-
- if (command_line->HasSwitch(switches::kSingleProcess) ||
- command_line->HasSwitch(switches::kInProcessGPU)) {
- in_process_gpu_ = true;
- AppendGpuCommandLine(command_line);
- }
-
-#if defined(OS_MACOSX)
- CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_);
-#endif // OS_MACOSX
-
- // For testing only.
- if (command_line->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs)) {
- domain_blocking_enabled_ = false;
- }
-}
-
-GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
-#if defined(OS_MACOSX)
- CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_);
-#endif
-}
-
void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() {
observer_list_->Notify(FROM_HERE, &GpuDataManagerObserver::OnGpuInfoUpdate);
}
@@ -756,8 +739,11 @@ bool GpuDataManagerImplPrivate::IsGpuProcessUsingHardwareGpu() const {
return true;
}
-std::string GpuDataManagerImplPrivate::GetDomainFromURL(
- const GURL& url) const {
+void GpuDataManagerImplPrivate::SetApplicationVisible(bool is_visible) {
+ application_is_visible_ = is_visible;
+}
+
+std::string GpuDataManagerImplPrivate::GetDomainFromURL(const GURL& url) const {
// For the moment, we just use the host, or its IP address, as the
// entry in the set, rather than trying to figure out the top-level
// domain. This does mean that a.foo.com and b.foo.com will be
@@ -860,21 +846,44 @@ bool GpuDataManagerImplPrivate::NeedsCompleteGpuInfoCollection() const {
#endif
}
-void GpuDataManagerImplPrivate::OnGpuProcessInitFailure() {
+gpu::GpuMode GpuDataManagerImplPrivate::GetGpuMode() const {
+ if (HardwareAccelerationEnabled()) {
+ return gpu::GpuMode::HARDWARE_ACCELERATED;
+ } else if (SwiftShaderAllowed()) {
+ return gpu::GpuMode::SWIFTSHADER;
+ } else if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) {
+ return gpu::GpuMode::DISPLAY_COMPOSITOR;
+ } else {
+ return gpu::GpuMode::DISABLED;
+ }
+}
+
+void GpuDataManagerImplPrivate::FallBackToNextGpuMode() {
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+ // Android and Chrome OS can't switch to software compositing. If the GPU
+ // process initialization fails or GPU process is too unstable then crash the
+ // browser process to reset everything.
+ LOG(FATAL) << "GPU process isn't usable. Goodbye.";
+#else
+ // TODO(kylechar): Use GpuMode to store the current mode instead of
+ // multiple bools.
+
if (!card_disabled_) {
DisableHardwareAcceleration();
- return;
- }
- if (SwiftShaderAllowed()) {
- BlockSwiftShader();
- return;
- }
- if (!base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) {
- // When Viz display compositor is not enabled, if GPU process fails to
- // launch with hardware GPU, and then fails to launch with SwiftShader if
- // available, then GPU process should not launch again.
+ } else if (SwiftShaderAllowed()) {
+ swiftshader_blocked_ = true;
+ OnGpuBlocked();
+ } else if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) {
+ // The GPU process is frequently crashing with only the display compositor
+ // running. This should never happen so something is wrong. Crash the
+ // browser process to reset everything.
+ LOG(FATAL) << "The display compositor is frequently crashing. Goodbye.";
+ } else {
+ // We are already at GpuMode::DISABLED. We shouldn't be launching the GPU
+ // process for it to fail.
NOTREACHED();
}
+#endif
}
} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
index a84efd1a461..68fc14b5286 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -37,7 +37,8 @@ namespace content {
class CONTENT_EXPORT GpuDataManagerImplPrivate {
public:
- static GpuDataManagerImplPrivate* Create(GpuDataManagerImpl* owner);
+ explicit GpuDataManagerImplPrivate(GpuDataManagerImpl* owner);
+ virtual ~GpuDataManagerImplPrivate();
void BlacklistWebGLForTesting();
gpu::GPUInfo GetGPUInfo() const;
@@ -57,7 +58,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
void UnblockDomainFrom3DAPIs(const GURL& url);
void DisableHardwareAcceleration();
bool HardwareAccelerationEnabled() const;
- void BlockSwiftShader();
bool SwiftShaderAllowed() const;
void UpdateGpuInfo(
@@ -99,14 +99,15 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
bool UpdateActiveGpu(uint32_t vendor_id, uint32_t device_id);
- void OnGpuProcessInitFailure();
+ gpu::GpuMode GetGpuMode() const;
+ void FallBackToNextGpuMode();
// Notify all observers whenever there is a GPU info update.
void NotifyGpuInfoUpdate();
bool IsGpuProcessUsingHardwareGpu() const;
- virtual ~GpuDataManagerImplPrivate();
+ void SetApplicationVisible(bool is_visible);
private:
friend class GpuDataManagerImplPrivateTest;
@@ -128,10 +129,10 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
GpuDataManagerImpl::DomainGuilt last_guilt;
};
- typedef std::map<std::string, DomainBlockEntry> DomainBlockMap;
+ using DomainBlockMap = std::map<std::string, DomainBlockEntry>;
- typedef base::ObserverListThreadSafe<GpuDataManagerObserver>
- GpuDataManagerObserverList;
+ using GpuDataManagerObserverList =
+ base::ObserverListThreadSafe<GpuDataManagerObserver>;
struct LogMessage {
int level;
@@ -146,8 +147,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
message(_message) { }
};
- explicit GpuDataManagerImplPrivate(GpuDataManagerImpl* owner);
-
// Called when GPU access (hardware acceleration and swiftshader) becomes
// blocked.
void OnGpuBlocked();
@@ -170,7 +169,9 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
// 3) all other platforms, this returns false.
bool NeedsCompleteGpuInfoCollection() const;
- bool complete_gpu_info_already_requested_;
+ GpuDataManagerImpl* const owner_;
+
+ bool complete_gpu_info_already_requested_ = false;
gpu::GpuFeatureInfo gpu_feature_info_;
gpu::GPUInfo gpu_info_;
@@ -187,23 +188,23 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
// Current card force-disabled due to GPU crashes, or disabled through
// the --disable-gpu commandline switch.
- bool card_disabled_;
+ bool card_disabled_ = false;
// SwiftShader force-blocked due to GPU crashes using SwiftShader.
- bool swiftshader_blocked_;
+ bool swiftshader_blocked_ = false;
// We disable histogram stuff in testing, especially in unit tests because
// they cause random failures.
- bool update_histograms_;
+ bool update_histograms_ = true;
DomainBlockMap blocked_domains_;
mutable std::list<base::Time> timestamps_of_gpu_resets_;
- bool domain_blocking_enabled_;
+ bool domain_blocking_enabled_ = true;
- GpuDataManagerImpl* owner_;
+ bool application_is_visible_ = true;
// True if --single-process or --in-process-gpu is passed in.
- bool in_process_gpu_;
+ bool in_process_gpu_ = false;
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 a105555d01f..bb1ddc7b334 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
@@ -21,12 +21,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
-
-#define LONG_STRING_CONST(...) #__VA_ARGS__
-
namespace content {
namespace {
@@ -72,18 +66,14 @@ class GpuDataManagerImplPrivateTest : public testing::Test {
// so we can make a little helper class here.
class ScopedGpuDataManagerImpl {
public:
- ScopedGpuDataManagerImpl() : impl_(new GpuDataManagerImpl()) {
- EXPECT_TRUE(impl_);
- EXPECT_TRUE(impl_->private_.get());
- }
- ~ScopedGpuDataManagerImpl() { delete impl_; }
-
- GpuDataManagerImpl* get() const { return impl_; }
+ ScopedGpuDataManagerImpl() { EXPECT_TRUE(impl_.private_.get()); }
+ ~ScopedGpuDataManagerImpl() = default;
- GpuDataManagerImpl* operator->() const { return impl_; }
+ GpuDataManagerImpl* get() { return &impl_; }
+ GpuDataManagerImpl* operator->() { return &impl_; }
private:
- GpuDataManagerImpl* impl_;
+ GpuDataManagerImpl impl_;
DISALLOW_COPY_AND_ASSIGN(ScopedGpuDataManagerImpl);
};
@@ -91,29 +81,17 @@ class GpuDataManagerImplPrivateTest : public testing::Test {
// in the GpuDataManagerImpl constructor.
class ScopedGpuDataManagerImplPrivate {
public:
- ScopedGpuDataManagerImplPrivate() : impl_(new GpuDataManagerImpl()) {
- EXPECT_TRUE(impl_);
- EXPECT_TRUE(impl_->private_.get());
- }
- ~ScopedGpuDataManagerImplPrivate() { delete impl_; }
+ ScopedGpuDataManagerImplPrivate() { EXPECT_TRUE(impl_.private_.get()); }
+ ~ScopedGpuDataManagerImplPrivate() = default;
- GpuDataManagerImplPrivate* get() const {
- return impl_->private_.get();
- }
-
- GpuDataManagerImplPrivate* operator->() const {
- return impl_->private_.get();
- }
+ GpuDataManagerImplPrivate* get() { return impl_.private_.get(); }
+ GpuDataManagerImplPrivate* operator->() { return impl_.private_.get(); }
private:
- GpuDataManagerImpl* impl_;
+ GpuDataManagerImpl impl_;
DISALLOW_COPY_AND_ASSIGN(ScopedGpuDataManagerImplPrivate);
};
- void SetUp() override {}
-
- void TearDown() override {}
-
base::Time JustBeforeExpiration(const GpuDataManagerImplPrivate* manager);
base::Time JustAfterExpiration(const GpuDataManagerImplPrivate* manager);
void TestBlockingDomainFrom3DAPIs(
diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc
index 54537e236ac..a64a4419064 100644
--- a/chromium/content/browser/gpu/gpu_internals_ui.cc
+++ b/chromium/content/browser/gpu/gpu_internals_ui.cc
@@ -64,6 +64,8 @@ namespace {
WebUIDataSource* CreateGpuHTMLSource() {
WebUIDataSource* source = WebUIDataSource::Create(kChromeUIGpuHost);
+ source->OverrideContentSecurityPolicyScriptSrc(
+ "script-src chrome://resources 'self' 'unsafe-eval';");
source->SetJsonPath("strings.js");
source->AddResourcePath("gpu_internals.js", IDR_GPU_INTERNALS_JS);
@@ -147,6 +149,7 @@ std::string GPUDeviceToString(const gpu::GPUInfo::GPUDevice& gpu) {
std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue(
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info) {
+ const gpu::GPUInfo::GPUDevice& active_gpu = gpu_info.active_gpu();
auto basic_info = std::make_unique<base::ListValue>();
basic_info->Append(NewDescriptionValuePair(
"Initialization time",
@@ -158,15 +161,9 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue(
"Passthrough Command Decoder",
std::make_unique<base::Value>(gpu_info.passthrough_cmd_decoder)));
basic_info->Append(NewDescriptionValuePair(
- "Direct Composition",
- std::make_unique<base::Value>(gpu_info.direct_composition)));
- basic_info->Append(NewDescriptionValuePair(
- "Supports overlays",
- std::make_unique<base::Value>(gpu_info.supports_overlays)));
- basic_info->Append(NewDescriptionValuePair(
"Sandboxed", std::make_unique<base::Value>(gpu_info.sandboxed)));
- basic_info->Append(NewDescriptionValuePair(
- "GPU0", GPUDeviceToString(gpu_info.gpu)));
+ basic_info->Append(
+ NewDescriptionValuePair("GPU0", GPUDeviceToString(gpu_info.gpu)));
for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) {
basic_info->Append(NewDescriptionValuePair(
base::StringPrintf("GPU%d", static_cast<int>(i + 1)),
@@ -183,6 +180,22 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue(
basic_info->Append(
NewDescriptionValuePair("Desktop compositing", compositor));
+ basic_info->Append(NewDescriptionValuePair(
+ "Direct Composition",
+ std::make_unique<base::Value>(gpu_info.direct_composition)));
+ basic_info->Append(NewDescriptionValuePair(
+ "Supports overlays",
+ std::make_unique<base::Value>(gpu_info.supports_overlays)));
+
+ auto overlay_capabilities = std::make_unique<base::ListValue>();
+ for (const auto& cap : gpu_info.overlay_capabilities) {
+ overlay_capabilities->Append(NewDescriptionValuePair(
+ gpu::OverlayFormatToString(cap.format),
+ cap.is_scaling_supported ? "SCALING" : "DIRECT"));
+ }
+ basic_info->Append(NewDescriptionValuePair("Overlay capabilities",
+ std::move(overlay_capabilities)));
+
std::vector<gfx::PhysicalDisplaySize> display_sizes =
gfx::GetPhysicalSizeForDisplays();
for (const auto& display_size : display_sizes) {
@@ -208,29 +221,28 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue(
#endif
basic_info->Append(
- NewDescriptionValuePair("Driver vendor", gpu_info.driver_vendor));
- basic_info->Append(NewDescriptionValuePair("Driver version",
- gpu_info.driver_version));
- basic_info->Append(NewDescriptionValuePair("Driver date",
- gpu_info.driver_date));
+ NewDescriptionValuePair("Driver vendor", active_gpu.driver_vendor));
+ basic_info->Append(
+ NewDescriptionValuePair("Driver version", active_gpu.driver_version));
+ basic_info->Append(
+ NewDescriptionValuePair("Driver date", active_gpu.driver_date));
basic_info->Append(NewDescriptionValuePair("Pixel shader version",
gpu_info.pixel_shader_version));
basic_info->Append(NewDescriptionValuePair("Vertex shader version",
gpu_info.vertex_shader_version));
- basic_info->Append(NewDescriptionValuePair("Max. MSAA samples",
- gpu_info.max_msaa_samples));
+ basic_info->Append(
+ NewDescriptionValuePair("Max. MSAA samples", gpu_info.max_msaa_samples));
basic_info->Append(NewDescriptionValuePair("Machine model name",
gpu_info.machine_model_name));
basic_info->Append(NewDescriptionValuePair("Machine model version",
gpu_info.machine_model_version));
- basic_info->Append(NewDescriptionValuePair("GL_VENDOR",
- gpu_info.gl_vendor));
- basic_info->Append(NewDescriptionValuePair("GL_RENDERER",
- gpu_info.gl_renderer));
- basic_info->Append(NewDescriptionValuePair("GL_VERSION",
- gpu_info.gl_version));
- basic_info->Append(NewDescriptionValuePair("GL_EXTENSIONS",
- gpu_info.gl_extensions));
+ basic_info->Append(NewDescriptionValuePair("GL_VENDOR", gpu_info.gl_vendor));
+ basic_info->Append(
+ NewDescriptionValuePair("GL_RENDERER", gpu_info.gl_renderer));
+ basic_info->Append(
+ NewDescriptionValuePair("GL_VERSION", gpu_info.gl_version));
+ basic_info->Append(
+ NewDescriptionValuePair("GL_EXTENSIONS", gpu_info.gl_extensions));
basic_info->Append(NewDescriptionValuePair(
"Disabled Extensions", gpu_feature_info.disabled_extensions));
basic_info->Append(NewDescriptionValuePair(
@@ -242,8 +254,8 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue(
basic_info->Append(NewDescriptionValuePair("Window system binding extensions",
gpu_info.gl_ws_extensions));
#if defined(USE_X11)
- basic_info->Append(NewDescriptionValuePair("Window manager",
- ui::GuessWindowManagerName()));
+ basic_info->Append(
+ NewDescriptionValuePair("Window manager", ui::GuessWindowManagerName()));
{
std::unique_ptr<base::Environment> env(base::Environment::Create());
std::string value;
@@ -264,8 +276,8 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue(
std::string reset_strategy =
base::StringPrintf("0x%04x", gpu_info.gl_reset_notification_strategy);
- basic_info->Append(NewDescriptionValuePair(
- "Reset notification strategy", reset_strategy));
+ basic_info->Append(
+ NewDescriptionValuePair("Reset notification strategy", reset_strategy));
basic_info->Append(NewDescriptionValuePair(
"GPU process crash count",
@@ -436,8 +448,12 @@ std::string GetProfileName(gpu::VideoCodecProfile profile) {
return "dolby vision profile 7";
case gpu::THEORAPROFILE_ANY:
return "theora";
- case gpu::AV1PROFILE_PROFILE0:
- return "av1 profile0";
+ case gpu::AV1PROFILE_PROFILE_MAIN:
+ return "av1 profile main";
+ case gpu::AV1PROFILE_PROFILE_HIGH:
+ return "av1 profile high";
+ case gpu::AV1PROFILE_PROFILE_PRO:
+ return "av1 profile pro";
}
NOTREACHED();
return "";
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index 72708d0f0c7..bdecceea7e6 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -15,6 +15,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
+#include "base/debug/alias.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -23,6 +24,7 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -34,14 +36,17 @@
#include "components/viz/common/switches.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/field_trial_recorder.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_main_thread_factory.h"
#include "content/browser/gpu/shader_cache_factory.h"
+#include "content/browser/memory/memory_coordinator_impl.h"
#include "content/browser/service_manager/service_manager_context.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/in_process_child_thread_params.h"
+#include "content/common/memory_coordinator.mojom.h"
#include "content/common/service_manager/child_connection.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
@@ -55,14 +60,14 @@
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
-#include "gpu/command_buffer/service/gpu_preferences.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/gpu_driver_bug_list.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
+#include "gpu/config/gpu_preferences.h"
#include "gpu/ipc/host/shader_disk_cache.h"
+#include "gpu/ipc/in_process_command_buffer.h"
#include "media/base/media_switches.h"
#include "media/media_buildflags.h"
-#include "mojo/edk/embedder/embedder.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
@@ -73,6 +78,7 @@
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/display/display_switches.h"
+#include "ui/gfx/font_render_params.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "ui/latency/latency_info.h"
@@ -104,18 +110,35 @@
#include "gpu/ipc/common/gpu_surface_tracker.h"
#endif
+#if defined(OS_MACOSX)
+#include "content/browser/gpu/ca_transaction_gpu_coordinator.h"
+#endif
+
namespace content {
base::subtle::Atomic32 GpuProcessHost::gpu_crash_count_ = 0;
-int GpuProcessHost::gpu_recent_crash_count_ = 0;
bool GpuProcessHost::crashed_before_ = false;
-int GpuProcessHost::swiftshader_crash_count_ = 0;
+int GpuProcessHost::hardware_accelerated_recent_crash_count_ = 0;
int GpuProcessHost::swiftshader_recent_crash_count_ = 0;
-int GpuProcessHost::display_compositor_crash_count_ = 0;
int GpuProcessHost::display_compositor_recent_crash_count_ = 0;
namespace {
+// UMA histogram names.
+constexpr char kProcessLifetimeEventsHardwareAccelerated[] =
+ "GPU.ProcessLifetimeEvents.HardwareAccelerated";
+constexpr char kProcessLifetimeEventsSwiftShader[] =
+ "GPU.ProcessLifetimeEvents.SwiftShader";
+constexpr char kProcessLifetimeEventsDisplayCompositor[] =
+ "GPU.ProcessLifetimeEvents.DisplayCompositor";
+
+// Forgive one GPU process crash after this many minutes.
+constexpr int kForgiveGpuCrashMinutes = 60;
+
+// Forgive one GPU process crash, when the GPU process is launched to run only
+// the display compositor, after this many minutes.
+constexpr int kForgiveDisplayCompositorCrashMinutes = 10;
+
// This matches base::TerminationStatus.
// These values are persisted to logs. Entries (except MAX_ENUM) should not be
// renumbered and numeric values should never be reused. Should also avoid
@@ -185,19 +208,21 @@ static const char* const kSwitchNames[] = {
switches::kDisableGLExtensions,
switches::kDisableLogging,
switches::kDisableShaderNameHashing,
+ switches::kDisableSkiaRuntimeOpts,
switches::kDisableWebRtcHWEncoding,
#if defined(OS_WIN)
switches::kEnableAcceleratedVpxDecode,
#endif
switches::kEnableGpuRasterization,
switches::kEnableLogging,
- switches::kEnableOOPRasterization,
switches::kEnableVizDevTools,
switches::kHeadless,
switches::kLoggingLevel,
switches::kEnableLowEndDeviceMode,
switches::kDisableLowEndDeviceMode,
switches::kRunAllCompositorStagesBeforeDraw,
+ switches::kSkiaFontCacheLimitMb,
+ switches::kSkiaResourceCacheLimitMb,
switches::kTestGLLib,
switches::kTraceToConsole,
switches::kUseFakeJpegDecodeAccelerator,
@@ -226,15 +251,19 @@ static const char* const kSwitchNames[] = {
#if defined(OS_ANDROID)
switches::kOrderfileMemoryOptimization,
#endif
+ switches::kWebglAntialiasingMode,
+ switches::kWebglMSAASampleCount,
};
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
enum GPUProcessLifetimeEvent {
- LAUNCHED,
- DIED_FIRST_TIME,
- DIED_SECOND_TIME,
- DIED_THIRD_TIME,
- DIED_FOURTH_TIME,
- GPU_PROCESS_LIFETIME_EVENT_MAX = 100
+ LAUNCHED = 0,
+ // When the GPU process crashes the (DIED_FIRST_TIME + recent_crash_count - 1)
+ // bucket in the appropriate UMA histogram will be incremented. The first
+ // crash will be DIED_FIRST_TIME, the second DIED_FIRST_TIME+1, etc.
+ DIED_FIRST_TIME = 1,
+ GPU_PROCESS_LIFETIME_EVENT_MAX = 100,
};
// Indexed by GpuProcessKind. There is one of each kind maximum. This array may
@@ -442,7 +471,7 @@ void BindDiscardableMemoryRequestOnUI(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if defined(USE_AURA)
- if (features::IsMashEnabled()) {
+ if (!features::IsAshInBrowserProcess()) {
ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
ui::mojom::kServiceName, std::move(request));
return;
@@ -455,11 +484,28 @@ void BindDiscardableMemoryRequestOnUI(
BrowserMainLoop::GetInstance()->discardable_shared_memory_manager()));
}
+struct FontRenderParamsOnIO {
+ bool initialized = false;
+ gfx::FontRenderParams params;
+};
+
+FontRenderParamsOnIO& GetFontRenderParamsOnIO() {
+ static base::NoDestructor<FontRenderParamsOnIO> instance;
+ return *instance;
+}
+
+void CreateMemoryCoordinatorHandleForGpuProcess(
+ int gpu_process_id,
+ mojom::MemoryCoordinatorHandleRequest request) {
+ MemoryCoordinatorImpl::GetInstance()->CreateHandle(gpu_process_id,
+ std::move(request));
+}
+
} // anonymous namespace
class GpuProcessHost::ConnectionFilterImpl : public ConnectionFilter {
public:
- ConnectionFilterImpl() {
+ explicit ConnectionFilterImpl(int gpu_process_id) {
auto task_runner = BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
registry_.AddInterface(base::Bind(&FieldTrialRecorder::Create),
task_runner);
@@ -468,6 +514,11 @@ class GpuProcessHost::ConnectionFilterImpl : public ConnectionFilter {
base::Bind(&BindJavaInterface<media::mojom::AndroidOverlayProvider>),
task_runner);
#endif
+
+ registry_.AddInterface(
+ base::BindRepeating(&CreateMemoryCoordinatorHandleForGpuProcess,
+ gpu_process_id),
+ task_runner);
}
private:
@@ -488,6 +539,16 @@ class GpuProcessHost::ConnectionFilterImpl : public ConnectionFilter {
};
// static
+void GpuProcessHost::InitFontRenderParamsOnIO(
+ const gfx::FontRenderParams& params) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!GetFontRenderParamsOnIO().initialized);
+
+ GetFontRenderParamsOnIO().initialized = true;
+ GetFontRenderParamsOnIO().params = params;
+}
+
+// static
bool GpuProcessHost::ValidateHost(GpuProcessHost* host) {
// The Gpu process is invalid if it's not using SwiftShader, the card is
// blacklisted, and we can kill it and start over.
@@ -612,17 +673,20 @@ int GpuProcessHost::GetGpuCrashCount() {
}
// static
-void GpuProcessHost::IncrementCrashCount(int* crash_count) {
+void GpuProcessHost::IncrementCrashCount(int forgive_minutes,
+ int* crash_count) {
+ DCHECK_GT(forgive_minutes, 0);
+
// Last time the process crashed.
- static base::Time last_crash_time;
+ static base::TimeTicks last_crash_time;
- // Allow about 1 crash per hour to be removed from the crash count, so very
- // occasional crashes won't eventually add up and prevent the process from
- // launching.
- base::Time current_time = base::Time::Now();
+ // Remove one crash per |forgive_minutes| from the crash count, so occasional
+ // crashes won't add up and eventually prevent using the GPU process.
+ base::TimeTicks current_time = base::TimeTicks::Now();
if (crashed_before_) {
- int hours_different = (current_time - last_crash_time).InHours();
- *crash_count = std::max(0, *crash_count - hours_different);
+ int minutes_delta = (current_time - last_crash_time).InMinutes();
+ int crashes_to_forgive = minutes_delta / forgive_minutes;
+ *crash_count = std::max(0, *crash_count - crashes_to_forgive);
}
++(*crash_count);
@@ -663,6 +727,13 @@ GpuProcessHost::~GpuProcessHost() {
SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID);
+#if defined(OS_MACOSX)
+ if (ca_transaction_gpu_coordinator_) {
+ ca_transaction_gpu_coordinator_->HostWillBeDestroyed();
+ ca_transaction_gpu_coordinator_ = nullptr;
+ }
+#endif
+
if (status_ == UNKNOWN) {
RunRequestGPUInfoCallbacks(gpu::GPUInfo());
} else {
@@ -806,11 +877,14 @@ bool GpuProcessHost::Init() {
// May be null during test execution.
if (ServiceManagerConnection::GetForProcess()) {
ServiceManagerConnection::GetForProcess()->AddConnectionFilter(
- std::make_unique<ConnectionFilterImpl>());
+ std::make_unique<ConnectionFilterImpl>(process_->GetData().id));
}
process_->GetHost()->CreateChannelMojo();
+ mode_ = GpuDataManagerImpl::GetInstance()->GetGpuMode();
+ DCHECK_NE(mode_, gpu::GpuMode::DISABLED);
+
if (in_process_) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(GetGpuMainThreadFactory());
@@ -819,7 +893,7 @@ bool GpuProcessHost::Init() {
in_process_gpu_thread_.reset(GetGpuMainThreadFactory()(
InProcessChildThreadParams(
base::ThreadTaskRunnerHandle::Get(),
- process_->GetInProcessBrokerClientInvitation(),
+ process_->GetInProcessMojoInvitation(),
process_->child_connection()->service_token()),
gpu_preferences));
base::Thread::Options options;
@@ -850,14 +924,20 @@ bool GpuProcessHost::Init() {
base::BindOnce(&BindDiscardableMemoryRequestOnUI,
std::move(discardable_request)));
+ DCHECK(GetFontRenderParamsOnIO().initialized);
gpu_main_ptr_->CreateGpuService(
mojo::MakeRequest(&gpu_service_ptr_), std::move(host_proxy),
- std::move(discardable_manager_ptr), activity_flags_.CloneHandle());
+ std::move(discardable_manager_ptr), activity_flags_.CloneHandle(),
+ GetFontRenderParamsOnIO().params.subpixel_rendering);
#if defined(USE_OZONE)
InitOzone();
#endif // defined(USE_OZONE)
+#if defined(OS_MACOSX)
+ ca_transaction_gpu_coordinator_ = CATransactionGPUCoordinator::Create(this);
+#endif
+
return true;
}
@@ -916,6 +996,16 @@ void GpuProcessHost::EstablishGpuChannel(
return;
}
+ bool oopd_enabled =
+ base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
+ if (oopd_enabled && client_id == gpu::InProcessCommandBuffer::kGpuClientId) {
+ // The display-compositor in the gpu process uses this special client id.
+ callback.Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
+ gpu::GpuFeatureInfo(),
+ EstablishChannelStatus::GPU_ACCESS_DENIED);
+ return;
+ }
+
DCHECK_EQ(preempts, allow_view_command_buffers);
DCHECK_EQ(preempts, allow_real_time_streams);
bool is_gpu_host = preempts;
@@ -929,6 +1019,8 @@ void GpuProcessHost::EstablishGpuChannel(
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuShaderDiskCache)) {
CreateChannelCache(client_id);
+ if (oopd_enabled)
+ CreateChannelCache(gpu::InProcessCommandBuffer::kGpuClientId);
}
}
@@ -987,19 +1079,6 @@ void GpuProcessHost::RequestHDRStatus(RequestHDRStatusCallback request_cb) {
gpu_service_ptr_->RequestHDRStatus(std::move(request_cb));
}
-#if defined(OS_ANDROID)
-void GpuProcessHost::SendDestroyingVideoSurface(int surface_id,
- const base::Closure& done_cb) {
- TRACE_EVENT0("gpu", "GpuProcessHost::SendDestroyingVideoSurface");
- DCHECK(send_destroying_video_surface_done_cb_.is_null());
- DCHECK(!done_cb.is_null());
- send_destroying_video_surface_done_cb_ = done_cb;
- gpu_service_ptr_->DestroyingVideoSurface(
- surface_id, base::Bind(&GpuProcessHost::OnDestroyingVideoSurfaceAck,
- weak_ptr_factory_.GetWeakPtr()));
-}
-#endif
-
void GpuProcessHost::OnChannelEstablished(
int client_id,
const EstablishChannelCallback& callback,
@@ -1029,13 +1108,13 @@ void GpuProcessHost::OnChannelEstablished(
}
void GpuProcessHost::OnGpuMemoryBufferCreated(
- const gfx::GpuMemoryBufferHandle& handle) {
+ gfx::GpuMemoryBufferHandle handle) {
TRACE_EVENT0("gpu", "GpuProcessHost::OnGpuMemoryBufferCreated");
DCHECK(!create_gpu_memory_buffer_requests_.empty());
auto callback = std::move(create_gpu_memory_buffer_requests_.front());
create_gpu_memory_buffer_requests_.pop();
- std::move(callback).Run(handle, BufferCreationStatus::SUCCESS);
+ std::move(callback).Run(std::move(handle), BufferCreationStatus::SUCCESS);
}
#if defined(OS_ANDROID)
@@ -1056,6 +1135,11 @@ void GpuProcessHost::OnProcessLaunched() {
}
void GpuProcessHost::OnProcessLaunchFailed(int error_code) {
+ // TODO(crbug.com/849639): Ensure |error_code| is included in crash minidumps.
+ // This is for debugging and should be removed when bug is closed.
+ int process_launch_error_code = error_code;
+ base::debug::Alias(&process_launch_error_code);
+
#if defined(OS_WIN)
if (kind_ == GPU_PROCESS_KIND_SANDBOXED)
RecordAppContainerStatus(error_code, crashed_before_);
@@ -1064,6 +1148,14 @@ void GpuProcessHost::OnProcessLaunchFailed(int error_code) {
}
void GpuProcessHost::OnProcessCrashed(int exit_code) {
+ // TODO(crbug.com/849639): Ensure |exit_code| is included in crash minidumps.
+ // This is for debugging and should be removed when bug is closed.
+ int process_crash_exit_code = exit_code;
+ base::debug::Alias(&process_crash_exit_code);
+
+ // Record crash before doing anything that could start a new GPU process.
+ RecordProcessCrash();
+
// If the GPU process crashed while compiling a shader, we may have invalid
// cached binaries. Completely clear the shader cache to force shader binaries
// to be re-created.
@@ -1079,7 +1171,6 @@ void GpuProcessHost::OnProcessCrashed(int exit_code) {
}
}
SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID);
- RecordProcessCrash();
ChildProcessTerminationInfo info =
process_->GetTerminationInfo(true /* known_dead */);
@@ -1117,7 +1208,8 @@ void GpuProcessHost::DidFailInitialize() {
UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", false);
status_ = FAILURE;
GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
- gpu_data_manager->OnGpuProcessInitFailure();
+ if (kind_ == GPU_PROCESS_KIND_SANDBOXED)
+ gpu_data_manager->FallBackToNextGpuMode();
RunRequestGPUInfoCallbacks(gpu_data_manager->GetGPUInfo());
}
@@ -1126,7 +1218,7 @@ void GpuProcessHost::DidCreateContextSuccessfully() {
// Android may kill the GPU process to free memory, especially when the app
// is the background, so Android cannot have a hard limit on GPU starts.
// Reset crash count on Android when context creation succeeds.
- gpu_recent_crash_count_ = 0;
+ hardware_accelerated_recent_crash_count_ = 0;
#endif
}
@@ -1193,6 +1285,18 @@ void GpuProcessHost::DidLoseContext(bool offscreen,
GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(active_url, guilt);
}
+void GpuProcessHost::DisableGpuCompositing() {
+#if !defined(OS_ANDROID)
+ // TODO(crbug.com/819474): The switch from GPU to software compositing should
+ // be handled here instead of by ImageTransportFactory.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE, base::BindOnce([]() {
+ if (auto* factory = ImageTransportFactory::GetInstance())
+ factory->DisableGpuCompositing();
+ }));
+#endif
+}
+
void GpuProcessHost::SetChildSurface(gpu::SurfaceHandle parent_handle,
gpu::SurfaceHandle window_handle) {
#if defined(OS_WIN)
@@ -1317,6 +1421,8 @@ bool GpuProcessHost::LaunchGpuProcess() {
GetContentClient()->browser()->AppendExtraCommandLineSwitches(
cmd_line.get(), process_->GetData().id);
+ // TODO(kylechar): The command line flags added here should be based on
+ // |mode_|.
GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line.get());
bool swiftshader_rendering =
(cmd_line->GetSwitchValueASCII(switches::kUseGL) ==
@@ -1338,8 +1444,19 @@ bool GpuProcessHost::LaunchGpuProcess() {
process_->Launch(std::move(delegate), std::move(cmd_line), true);
process_launched_ = true;
- UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
- LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX);
+ if (kind_ == GPU_PROCESS_KIND_SANDBOXED) {
+ if (mode_ == gpu::GpuMode::HARDWARE_ACCELERATED) {
+ UMA_HISTOGRAM_ENUMERATION(kProcessLifetimeEventsHardwareAccelerated,
+ LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX);
+ } else if (mode_ == gpu::GpuMode::SWIFTSHADER) {
+ UMA_HISTOGRAM_ENUMERATION(kProcessLifetimeEventsSwiftShader, LAUNCHED,
+ GPU_PROCESS_LIFETIME_EVENT_MAX);
+ } else if (mode_ == gpu::GpuMode::DISPLAY_COMPOSITOR) {
+ UMA_HISTOGRAM_ENUMERATION(kProcessLifetimeEventsDisplayCompositor,
+ LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX);
+ }
+ }
+
return true;
}
@@ -1384,89 +1501,85 @@ void GpuProcessHost::BlockLiveOffscreenContexts() {
}
void GpuProcessHost::RecordProcessCrash() {
-#if !defined(OS_ANDROID)
- // Maximum number of times the GPU process is allowed to crash in a session.
- // Once this limit is reached, any request to launch the GPU process will
- // fail.
- const int kGpuMaxCrashCount = 3;
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+ // Maximum number of times the GPU process can crash before we try something
+ // different, like disabling hardware acceleration or all GL.
+ constexpr int kGpuFallbackCrashCount = 3;
#else
- // On android there is no way to recover without gpu, and the OS can kill the
- // gpu process arbitrarily, so use a higher count to allow for that.
- const int kGpuMaxCrashCount = 6;
+ // Android and Chrome OS switch to software compositing and fallback crashes
+ // the browser process. For Android the OS can also kill the GPU process
+ // arbitrarily. Use a larger maximum crash count here.
+ constexpr int kGpuFallbackCrashCount = 6;
#endif
- bool disable_crash_limit = base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableGpuProcessCrashLimit);
-
// Ending only acts as a failure if the GPU process was actually started and
// was intended for actual rendering (and not just checking caps or other
// options).
- if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) {
- if (GpuDataManagerImpl::GetInstance()->HardwareAccelerationEnabled()) {
- int count = static_cast<int>(
- base::subtle::NoBarrier_AtomicIncrement(&gpu_crash_count_, 1));
- UMA_HISTOGRAM_EXACT_LINEAR(
- "GPU.GPUProcessLifetimeEvents",
- std::min(DIED_FIRST_TIME + count, GPU_PROCESS_LIFETIME_EVENT_MAX - 1),
- static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
-
- IncrementCrashCount(&gpu_recent_crash_count_);
- if ((gpu_recent_crash_count_ >= kGpuMaxCrashCount ||
- status_ == FAILURE) &&
- !disable_crash_limit) {
-#if defined(OS_ANDROID)
- // Android can not fall back to software. If things are too unstable
- // then we just crash chrome to reset everything. Sorry.
- LOG(FATAL) << "Unable to start gpu process, giving up.";
-#elif defined(OS_CHROMEOS)
- // ChromeOS also can not fall back to software. There we will just
- // keep retrying to make the gpu process forever. Good luck.
- DLOG(ERROR) << "Gpu process is unstable and crashing repeatedly, if "
- "you didn't notice already.";
-#else
- // The GPU process is too unstable to use. Disable it for current
- // session.
- GpuDataManagerImpl::GetInstance()->DisableHardwareAcceleration();
-#endif
- }
- } else if (GpuDataManagerImpl::GetInstance()->SwiftShaderAllowed()) {
- UMA_HISTOGRAM_EXACT_LINEAR(
- "GPU.SwiftShaderLifetimeEvents",
- DIED_FIRST_TIME + swiftshader_crash_count_,
- static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
- ++swiftshader_crash_count_;
-
- IncrementCrashCount(&swiftshader_recent_crash_count_);
- if (swiftshader_recent_crash_count_ >= kGpuMaxCrashCount &&
- !disable_crash_limit) {
- // SwiftShader is too unstable to use. Disable it for current session.
- GpuDataManagerImpl::GetInstance()->BlockSwiftShader();
- }
- } else {
- UMA_HISTOGRAM_EXACT_LINEAR(
- "GPU.DisplayCompositorLifetimeEvents",
- DIED_FIRST_TIME + display_compositor_crash_count_,
- static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
- ++display_compositor_crash_count_;
-
- IncrementCrashCount(&display_compositor_recent_crash_count_);
- if (display_compositor_recent_crash_count_ >= kGpuMaxCrashCount &&
- !disable_crash_limit) {
- // Viz display compositor is too unstable. Crash chrome to reset
- // everything.
- LOG(FATAL) << "Unable to start viz process, giving up.";
- }
- }
+ if (!process_launched_ || kind_ != GPU_PROCESS_KIND_SANDBOXED)
+ return;
+
+ // Keep track of the total number of GPU crashes.
+ base::subtle::NoBarrier_AtomicIncrement(&gpu_crash_count_, 1);
+
+ int recent_crash_count = 0;
+ if (mode_ == gpu::GpuMode::HARDWARE_ACCELERATED) {
+ IncrementCrashCount(kForgiveGpuCrashMinutes,
+ &hardware_accelerated_recent_crash_count_);
+ UMA_HISTOGRAM_EXACT_LINEAR(
+ kProcessLifetimeEventsHardwareAccelerated,
+ DIED_FIRST_TIME + hardware_accelerated_recent_crash_count_ - 1,
+ static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
+ recent_crash_count = hardware_accelerated_recent_crash_count_;
+ } else if (mode_ == gpu::GpuMode::SWIFTSHADER) {
+ IncrementCrashCount(kForgiveGpuCrashMinutes,
+ &swiftshader_recent_crash_count_);
+ UMA_HISTOGRAM_EXACT_LINEAR(
+ kProcessLifetimeEventsSwiftShader,
+ DIED_FIRST_TIME + swiftshader_recent_crash_count_ - 1,
+ static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
+ recent_crash_count = swiftshader_recent_crash_count_;
+ } else if (mode_ == gpu::GpuMode::DISPLAY_COMPOSITOR) {
+ IncrementCrashCount(kForgiveDisplayCompositorCrashMinutes,
+ &display_compositor_recent_crash_count_);
+ UMA_HISTOGRAM_EXACT_LINEAR(
+ kProcessLifetimeEventsDisplayCompositor,
+ DIED_FIRST_TIME + display_compositor_recent_crash_count_ - 1,
+ static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
+ recent_crash_count = display_compositor_recent_crash_count_;
}
+
+ // TODO(crbug.com/849639): Ensure crash counts are included in crash
+ // minidumps. This is for debugging and should be removed when bug is closed.
+ int hardware_accelerated_crash_count =
+ hardware_accelerated_recent_crash_count_;
+ base::debug::Alias(&hardware_accelerated_crash_count);
+ int swiftshader_crash_count = swiftshader_recent_crash_count_;
+ base::debug::Alias(&swiftshader_crash_count);
+ int display_compositor_crash_count = display_compositor_recent_crash_count_;
+ base::debug::Alias(&display_compositor_crash_count);
+
+ // GPU process initialization failed and fallback already happened.
+ if (status_ == FAILURE)
+ return;
+
+ bool disable_crash_limit = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGpuProcessCrashLimit);
+
+ // GPU process crashed too many times, fallback on a different GPU process
+ // mode.
+ if (recent_crash_count >= kGpuFallbackCrashCount && !disable_crash_limit)
+ GpuDataManagerImpl::GetInstance()->FallBackToNextGpuMode();
}
std::string GpuProcessHost::GetShaderPrefixKey() {
if (shader_prefix_key_.empty()) {
- gpu::GPUInfo info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
+ const gpu::GPUInfo info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
+ const gpu::GPUInfo::GPUDevice& active_gpu = info.active_gpu();
shader_prefix_key_ = GetContentClient()->GetProduct() + "-" +
info.gl_vendor + "-" + info.gl_renderer + "-" +
- info.driver_version + "-" + info.driver_vendor;
+ active_gpu.driver_version + "-" +
+ active_gpu.driver_vendor;
#if defined(OS_ANDROID)
std::string build_fp =
@@ -1511,4 +1624,8 @@ void GpuProcessHost::CreateChannelCache(int32_t client_id) {
client_id_to_shader_cache_[client_id] = cache;
}
+int GpuProcessHost::GetIDForTesting() const {
+ return process_->GetData().id;
+}
+
} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h
index e08bcf72fc1..3ca9cf5c561 100644
--- a/chromium/content/browser/gpu/gpu_process_host.h
+++ b/chromium/content/browser/gpu/gpu_process_host.h
@@ -28,6 +28,7 @@
#include "gpu/command_buffer/common/constants.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_info.h"
+#include "gpu/config/gpu_mode.h"
#include "gpu/ipc/common/surface_handle.h"
#include "ipc/ipc_sender.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -43,6 +44,10 @@ namespace base {
class Thread;
}
+namespace gfx {
+struct FontRenderParams;
+}
+
namespace gpu {
class ShaderDiskCache;
struct SyncToken;
@@ -51,6 +56,10 @@ struct SyncToken;
namespace content {
class BrowserChildProcessHostImpl;
+#if defined(OS_MACOSX)
+class CATransactionGPUCoordinator;
+#endif
+
class GpuProcessHost : public BrowserChildProcessHostDelegate,
public IPC::Sender,
public viz::mojom::GpuHost {
@@ -80,7 +89,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
SUCCESS,
};
using CreateGpuMemoryBufferCallback =
- base::OnceCallback<void(const gfx::GpuMemoryBufferHandle& handle,
+ base::OnceCallback<void(gfx::GpuMemoryBufferHandle handle,
BufferCreationStatus status)>;
using RequestGPUInfoCallback = base::Callback<void(const gpu::GPUInfo&)>;
@@ -110,6 +119,8 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
bool force_create,
const base::Callback<void(GpuProcessHost*)>& callback);
+ static void InitFontRenderParamsOnIO(const gfx::FontRenderParams& params);
+
void BindInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe);
@@ -155,12 +166,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void RequestGPUInfo(RequestGPUInfoCallback request_cb);
void RequestHDRStatus(RequestHDRStatusCallback request_cb);
-#if defined(OS_ANDROID)
- // Tells the GPU process that the given surface is being destroyed so that it
- // can stop using it.
- void SendDestroyingVideoSurface(int surface_id, const base::Closure& done_cb);
-#endif
-
// What kind of GPU process, e.g. sandboxed or unsandboxed.
GpuProcessKind kind();
@@ -175,6 +180,8 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
return wake_up_gpu_before_drawing_;
}
+ CONTENT_EXPORT int GetIDForTesting() const;
+
private:
class ConnectionFilterImpl;
@@ -182,9 +189,10 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
static bool ValidateHost(GpuProcessHost* host);
- // Increments the given crash count. Also, for each hour passed since the
- // previous crash, removes an old crash from the count.
- static void IncrementCrashCount(int* crash_count);
+ // Increments |crash_count| by one. Before incrementing |crash_count|, for
+ // each |forgive_minutes| that has passed since the previous crash remove one
+ // old crash.
+ static void IncrementCrashCount(int forgive_minutes, int* crash_count);
GpuProcessHost(int host_id, GpuProcessKind kind);
~GpuProcessHost() override;
@@ -217,6 +225,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void DidLoseContext(bool offscreen,
gpu::error::ContextLostReason reason,
const GURL& active_url) override;
+ void DisableGpuCompositing() override;
void SetChildSurface(gpu::SurfaceHandle parent,
gpu::SurfaceHandle child) override;
void StoreShaderToDisk(int32_t client_id,
@@ -229,7 +238,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void OnChannelEstablished(int client_id,
const EstablishChannelCallback& callback,
mojo::ScopedMessagePipeHandle channel_handle);
- void OnGpuMemoryBufferCreated(const gfx::GpuMemoryBufferHandle& handle);
+ void OnGpuMemoryBufferCreated(gfx::GpuMemoryBufferHandle handle);
// Message handlers.
#if defined(OS_ANDROID)
@@ -279,6 +288,8 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
GpuProcessKind kind_;
+ gpu::GpuMode mode_ = gpu::GpuMode::UNKNOWN;
+
// Whether we actually launched a GPU process.
bool process_launched_;
@@ -287,12 +298,11 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// Time Init started. Used to log total GPU process startup time to UMA.
base::TimeTicks init_start_time_;
+ // The total number of GPU process crashes.
static base::subtle::Atomic32 gpu_crash_count_;
- static int gpu_recent_crash_count_;
static bool crashed_before_;
- static int swiftshader_crash_count_;
+ static int hardware_accelerated_recent_crash_count_;
static int swiftshader_recent_crash_count_;
- static int display_compositor_crash_count_;
static int display_compositor_recent_crash_count_;
// Here the bottom-up destruction order matters:
@@ -302,6 +312,10 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
std::unique_ptr<BrowserChildProcessHostImpl> process_;
std::unique_ptr<base::Thread> in_process_gpu_thread_;
+#if defined(OS_MACOSX)
+ scoped_refptr<CATransactionGPUCoordinator> ca_transaction_gpu_coordinator_;
+#endif
+
// Track the URLs of the pages which have live offscreen contexts,
// assumed to be associated with untrusted content such as WebGL.
// For best robustness, when any context lost notification is
diff --git a/chromium/content/browser/host_zoom_map_impl.cc b/chromium/content/browser/host_zoom_map_impl.cc
index 939d89cc27f..34775d0204d 100644
--- a/chromium/content/browser/host_zoom_map_impl.cc
+++ b/chromium/content/browser/host_zoom_map_impl.cc
@@ -238,7 +238,7 @@ void HostZoomMapImpl::SetZoomLevelForHostInternal(const std::string& host,
}
// TODO(wjmaclean) Should we use a GURL here? crbug.com/384486
- SendZoomLevelChange(std::string(), host, level);
+ SendZoomLevelChange(std::string(), host);
HostZoomMap::ZoomLevelChange change;
change.mode = HostZoomMap::ZOOM_CHANGED_FOR_HOST;
@@ -257,7 +257,7 @@ void HostZoomMapImpl::SetZoomLevelForHostAndScheme(const std::string& scheme,
// not persistet and are used for special cases only.
scheme_host_zoom_levels_[scheme][host].level = level;
- SendZoomLevelChange(scheme, host, level);
+ SendZoomLevelChange(scheme, host);
HostZoomMap::ZoomLevelChange change;
change.mode = HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST;
@@ -324,7 +324,7 @@ void HostZoomMapImpl::SetDefaultZoomLevel(double level) {
!UsesTemporaryZoomLevel(render_process_id, render_view_id);
if (uses_default_zoom) {
- web_contents->UpdateZoom(level);
+ web_contents->UpdateZoom();
HostZoomMap::ZoomLevelChange change;
change.mode = HostZoomMap::ZOOM_CHANGED_FOR_HOST;
@@ -460,7 +460,7 @@ void HostZoomMapImpl::SetTemporaryZoomLevel(int render_process_id,
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(
RenderViewHost::FromID(render_process_id, render_view_id)));
- web_contents->SetTemporaryZoomLevel(level, true);
+ web_contents->UpdateZoom();
HostZoomMap::ZoomLevelChange change;
change.mode = HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM;
@@ -507,13 +507,11 @@ void HostZoomMapImpl::ClearTemporaryZoomLevel(int render_process_id,
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(
RenderViewHost::FromID(render_process_id, render_view_id)));
- web_contents->SetTemporaryZoomLevel(GetZoomLevelForHost(
- GetHostFromProcessView(render_process_id, render_view_id)), false);
+ web_contents->UpdateZoom();
}
void HostZoomMapImpl::SendZoomLevelChange(const std::string& scheme,
- const std::string& host,
- double level) {
+ const std::string& host) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// We'll only send to WebContents not using temporary zoom levels. The one
// other case of interest is where the renderer is hosting a plugin document;
@@ -530,7 +528,7 @@ void HostZoomMapImpl::SendZoomLevelChange(const std::string& scheme,
int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID();
if (!UsesTemporaryZoomLevel(render_process_id, render_view_id))
- web_contents->UpdateZoomIfNecessary(scheme, host, level);
+ web_contents->UpdateZoomIfNecessary(scheme, host);
}
}
@@ -538,9 +536,8 @@ void HostZoomMapImpl::SendErrorPageZoomLevelRefresh() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GURL error_url(kUnreachableWebDataURL);
std::string host = net::GetHostOrSpecFromURL(error_url);
- double error_page_zoom_level = GetZoomLevelForHost(host);
- SendZoomLevelChange(std::string(), host, error_page_zoom_level);
+ SendZoomLevelChange(std::string(), host);
}
void HostZoomMapImpl::WillCloseRenderView(int render_process_id,
diff --git a/chromium/content/browser/host_zoom_map_impl.h b/chromium/content/browser/host_zoom_map_impl.h
index b7eef9b1983..51a26a5272e 100644
--- a/chromium/content/browser/host_zoom_map_impl.h
+++ b/chromium/content/browser/host_zoom_map_impl.h
@@ -129,10 +129,10 @@ class CONTENT_EXPORT HostZoomMapImpl : public HostZoomMap {
// Notifies the renderers from this browser context to change the zoom level
// for the specified host and scheme.
+ // |zoom level| will be extracted from |host_zoom_levels_| when needed, so no
+ // need to pass them in.
// TODO(wjmaclean) Should we use a GURL here? crbug.com/384486
- void SendZoomLevelChange(const std::string& scheme,
- const std::string& host,
- double level);
+ void SendZoomLevelChange(const std::string& scheme, const std::string& host);
// Callbacks called when zoom level changes.
base::CallbackList<void(const ZoomLevelChange&)>
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 6dde8e246d8..8dc3131ee8a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -3072,9 +3072,7 @@ bool IndexedDBBackingStore::IsBlobCleanupPending() {
}
void IndexedDBBackingStore::ForceRunBlobCleanup() {
- base::OnceClosure task = journal_cleaning_timer_.user_task();
- journal_cleaning_timer_.AbandonAndStop();
- std::move(task).Run();
+ journal_cleaning_timer_.FireNow();
}
IndexedDBBackingStore::Transaction::Transaction(
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 e976df908b2..eaa915e6d42 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
@@ -1446,7 +1446,7 @@ TEST_F(IndexedDBBackingStoreTest, ReadCorruptionInfo) {
TEST_F(IndexedDBBackingStoreTest, SchemaUpgradeWithoutBlobsSurvives) {
struct TestState {
int64_t database_id;
- const int64_t object_store_id = 99;
+ int64_t object_store_id = 99;
} state;
// The database metadata needs to be written so we can verify the blob entry
@@ -1568,6 +1568,9 @@ TEST_F(IndexedDBBackingStoreTest, SchemaUpgradeWithoutBlobsSurvives) {
EXPECT_TRUE(found);
EXPECT_EQ(3, found_int);
+
+ // Clean up Transactions, etc on the IDB thread.
+ *state = TestState();
},
base::Unretained(backing_store()), key1_, value1_,
base::Unretained(&state)));
@@ -1582,7 +1585,7 @@ TEST_F(IndexedDBBackingStoreTest, SchemaUpgradeWithoutBlobsSurvives) {
TEST_F(IndexedDBBackingStoreTestWithBlobs, SchemaUpgradeWithBlobsCorrupt) {
struct TestState {
int64_t database_id;
- const int64_t object_store_id = 99;
+ int64_t object_store_id = 99;
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1;
scoped_refptr<TestCallback> callback1;
std::unique_ptr<IndexedDBBackingStore::Transaction> transaction3;
@@ -1677,6 +1680,9 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, SchemaUpgradeWithBlobsCorrupt) {
const std::string schema_version_key = SchemaVersionKey::Encode();
indexed_db::PutInt(transaction.get(), schema_version_key, 2);
ASSERT_TRUE(transaction->Commit().ok());
+
+ // Clean up Transactions, etc on the IDB thread.
+ *state = TestState();
},
base::Unretained(this), base::Unretained(&state)));
RunAllTasksUntilIdle();
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 f063f01ae1d..cd079aedd08 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "base/callback_helpers.h"
+#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
@@ -110,7 +111,7 @@ const base::Feature kIDBTombstoneStatistics{"IDBTombstoneStatistics",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIDBTombstoneDeletion{"IDBTombstoneDeletion",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
constexpr const base::TimeDelta
IndexedDBFactoryImpl::kMaxEarliestGlobalSweepFromNow;
@@ -179,6 +180,12 @@ void IndexedDBFactoryImpl::ReleaseBackingStore(const Origin& origin,
return;
}
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ kIDBCloseImmediatelySwitch)) {
+ MaybeCloseBackingStore(origin);
+ return;
+ }
+
// Start a timer to close the backing store, unless something else opens it
// in the mean time.
DCHECK(!backing_store_map_[origin]->close_timer()->IsRunning());
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_impl.h b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
index 4ae17600381..3935f9b319f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -32,6 +32,8 @@ class IndexedDBContextImpl;
CONTENT_EXPORT extern const base::Feature kIDBTombstoneStatistics;
CONTENT_EXPORT extern const base::Feature kIDBTombstoneDeletion;
+constexpr const char kIDBCloseImmediatelySwitch[] = "idb-close-immediately";
+
class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
public:
// Maximum time interval between runs of the IndexedDBSweeper. Sweeping only
@@ -141,6 +143,8 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
BackingStoreReleaseDelayedOnClose);
FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, BackingStoreRunPreCloseTasks);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
+ BackingStoreCloseImmediatelySwitch);
FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, BackingStoreNoSweeping);
FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, DatabaseFailedOpen);
FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
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 2384f769124..0031ef8024b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -180,6 +180,9 @@ TEST_F(IndexedDBFactoryTest, BackingStoreLazyClose) {
}
TEST_F(IndexedDBFactoryTest, BackingStoreNoSweeping) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatures(
+ {}, {kIDBTombstoneDeletion, kIDBTombstoneStatistics});
context()->TaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
@@ -209,7 +212,7 @@ TEST_F(IndexedDBFactoryTest, BackingStoreNoSweeping) {
EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
factory->TestReleaseBackingStore(store_ptr, false);
EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
- store_ptr->close_timer()->user_task().Run();
+ store_ptr->close_timer()->FireNow();
// Backing store should be totally closed.
EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
@@ -225,7 +228,7 @@ TEST_F(IndexedDBFactoryTest, BackingStoreNoSweeping) {
// Sweep should NOT be occurring.
EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
- store_ptr->close_timer()->user_task().Run();
+ store_ptr->close_timer()->FireNow();
// Backing store should be totally closed.
EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
@@ -268,7 +271,7 @@ TEST_F(IndexedDBFactoryTest, BackingStoreRunPreCloseTasks) {
EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
factory->TestReleaseBackingStore(store_ptr, false);
EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
- store_ptr->close_timer()->user_task().Run();
+ store_ptr->close_timer()->FireNow();
// Backing store should be totally closed.
EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
@@ -284,8 +287,7 @@ TEST_F(IndexedDBFactoryTest, BackingStoreRunPreCloseTasks) {
// Sweep should be occuring.
EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
- store_ptr->close_timer()->user_task().Run();
- store_ptr->close_timer()->AbandonAndStop();
+ store_ptr->close_timer()->FireNow();
ASSERT_NE(nullptr, store_ptr->pre_close_task_queue());
EXPECT_TRUE(store_ptr->pre_close_task_queue()->started());
@@ -309,8 +311,7 @@ TEST_F(IndexedDBFactoryTest, BackingStoreRunPreCloseTasks) {
// Sweep should be occuring.
EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
- store_ptr->close_timer()->user_task().Run();
- store_ptr->close_timer()->AbandonAndStop();
+ store_ptr->close_timer()->FireNow();
ASSERT_NE(nullptr, store_ptr->pre_close_task_queue());
EXPECT_TRUE(store_ptr->pre_close_task_queue()->started());
@@ -324,6 +325,41 @@ TEST_F(IndexedDBFactoryTest, BackingStoreRunPreCloseTasks) {
RunAllTasksUntilIdle();
}
+TEST_F(IndexedDBFactoryTest, BackingStoreCloseImmediatelySwitch) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatures({kIDBTombstoneStatistics},
+ {kIDBTombstoneDeletion});
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ kIDBCloseImmediatelySwitch);
+
+ context()->TaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](IndexedDBContextImpl* context) {
+ base::SimpleTestClock clock;
+ clock.SetNow(base::Time::Now());
+
+ scoped_refptr<MockIDBFactory> factory =
+ base::MakeRefCounted<MockIDBFactory>(context, &clock);
+
+ const Origin origin = Origin::Create(GURL("http://localhost:81"));
+
+ scoped_refptr<IndexedDBBackingStore> store =
+ factory->TestOpenBackingStore(origin, context->data_path());
+
+ // Give up the local refptr so that the factory has the only
+ // outstanding reference.
+ IndexedDBBackingStore* store_ptr = store.get();
+ store = nullptr;
+ EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
+ factory->TestReleaseBackingStore(store_ptr, false);
+ EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
+ },
+ base::Unretained(context())));
+
+ RunAllTasksUntilIdle();
+}
+
TEST_F(IndexedDBFactoryTest, MemoryBackingStoreLifetime) {
context()->TaskRunner()->PostTask(
FROM_HERE,
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 616d0b0f0d5..b548e8953e4 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -65,6 +65,8 @@ IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui)
WebUIDataSource* source =
WebUIDataSource::Create(kChromeUIIndexedDBInternalsHost);
+ source->OverrideContentSecurityPolicyScriptSrc(
+ "script-src chrome://resources 'self' 'unsafe-eval';");
source->SetJsonPath("strings.js");
source->AddResourcePath("indexeddb_internals.js",
IDR_INDEXED_DB_INTERNALS_JS);
diff --git a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc
index e04bbb4e965..0be77f326e1 100644
--- a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc
@@ -16,7 +16,7 @@ IndexedDBPreCloseTaskQueue::IndexedDBPreCloseTaskQueue(
std::list<std::unique_ptr<IndexedDBPreCloseTaskQueue::PreCloseTask>> tasks,
base::OnceClosure on_complete,
base::TimeDelta max_run_time,
- std::unique_ptr<base::Timer> timer)
+ std::unique_ptr<base::OneShotTimer> timer)
: tasks_(std::move(tasks)),
on_done_(std::move(on_complete)),
timeout_time_(max_run_time),
diff --git a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.h b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.h
index 4010a5a4271..7e2aa847c55 100644
--- a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.h
+++ b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.h
@@ -64,7 +64,7 @@ class CONTENT_EXPORT IndexedDBPreCloseTaskQueue {
IndexedDBPreCloseTaskQueue(std::list<std::unique_ptr<PreCloseTask>> tasks,
base::OnceClosure on_complete,
base::TimeDelta max_run_time,
- std::unique_ptr<base::Timer> timer);
+ std::unique_ptr<base::OneShotTimer> timer);
~IndexedDBPreCloseTaskQueue();
bool started() const { return started_; }
@@ -96,7 +96,7 @@ class CONTENT_EXPORT IndexedDBPreCloseTaskQueue {
base::OnceClosure on_done_;
base::TimeDelta timeout_time_;
- std::unique_ptr<base::Timer> timeout_timer_;
+ std::unique_ptr<base::OneShotTimer> timeout_timer_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
base::WeakPtrFactory<IndexedDBPreCloseTaskQueue> ptr_factory_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
index 138b8d149ca..48bf2edc32f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
@@ -80,7 +80,7 @@ TEST_F(IndexedDBPreCloseTaskQueueTest, NoTasks) {
bool done_called = false;
bool metadata_called = false;
- base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ base::MockOneShotTimer* fake_timer = new base::MockOneShotTimer;
IndexedDBPreCloseTaskQueue queue(
std::list<std::unique_ptr<PreCloseTask>>(),
base::BindOnce(&SetBoolValue, &done_called, true), kTestMaxRunTime,
@@ -104,7 +104,7 @@ TEST_F(IndexedDBPreCloseTaskQueueTest, TaskOneRound) {
EXPECT_CALL(*task,
SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
- base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ base::MockOneShotTimer* fake_timer = new base::MockOneShotTimer;
std::list<std::unique_ptr<PreCloseTask>> tasks;
tasks.push_back(base::WrapUnique(task));
IndexedDBPreCloseTaskQueue queue(
@@ -134,7 +134,7 @@ TEST_F(IndexedDBPreCloseTaskQueueTest, TaskTwoRounds) {
EXPECT_CALL(*task,
SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
- base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ base::MockOneShotTimer* fake_timer = new base::MockOneShotTimer;
std::list<std::unique_ptr<PreCloseTask>> tasks;
tasks.push_back(base::WrapUnique(task));
IndexedDBPreCloseTaskQueue queue(
@@ -178,7 +178,7 @@ TEST_F(IndexedDBPreCloseTaskQueueTest, TwoTasks) {
EXPECT_CALL(*task1,
SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
- base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ base::MockOneShotTimer* fake_timer = new base::MockOneShotTimer;
std::list<std::unique_ptr<PreCloseTask>> tasks;
tasks.push_back(base::WrapUnique(task1));
tasks.push_back(base::WrapUnique(task2));
@@ -227,7 +227,7 @@ TEST_F(IndexedDBPreCloseTaskQueueTest, StopForNewConnectionBeforeStart) {
EXPECT_CALL(*task1,
SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
- base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ base::MockOneShotTimer* fake_timer = new base::MockOneShotTimer;
std::list<std::unique_ptr<PreCloseTask>> tasks;
tasks.push_back(base::WrapUnique(task1));
tasks.push_back(base::WrapUnique(task2));
@@ -260,7 +260,7 @@ TEST_F(IndexedDBPreCloseTaskQueueTest, StopForNewConnectionAfterRound) {
EXPECT_CALL(*task,
SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
- base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ base::MockOneShotTimer* fake_timer = new base::MockOneShotTimer;
std::list<std::unique_ptr<PreCloseTask>> tasks;
tasks.push_back(base::WrapUnique(task));
IndexedDBPreCloseTaskQueue queue(
@@ -301,7 +301,7 @@ TEST_F(IndexedDBPreCloseTaskQueueTest, StopForNewConnectionAfterTaskCompletes) {
EXPECT_CALL(*task1,
SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
- base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ base::MockOneShotTimer* fake_timer = new base::MockOneShotTimer;
std::list<std::unique_ptr<PreCloseTask>> tasks;
tasks.push_back(base::WrapUnique(task1));
tasks.push_back(base::WrapUnique(task2));
@@ -345,7 +345,7 @@ TEST_F(IndexedDBPreCloseTaskQueueTest, StopForTimout) {
EXPECT_CALL(*task1,
SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
- base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ base::MockOneShotTimer* fake_timer = new base::MockOneShotTimer;
std::list<std::unique_ptr<PreCloseTask>> tasks;
tasks.push_back(base::WrapUnique(task1));
tasks.push_back(base::WrapUnique(task2));
@@ -387,7 +387,7 @@ TEST_F(IndexedDBPreCloseTaskQueueTest, MetadataError) {
MockPreCloseTask* task1 = new testing::StrictMock<MockPreCloseTask>();
MockPreCloseTask* task2 = new testing::StrictMock<MockPreCloseTask>();
- base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ base::MockOneShotTimer* fake_timer = new base::MockOneShotTimer;
std::list<std::unique_ptr<PreCloseTask>> tasks;
tasks.push_back(base::WrapUnique(task1));
tasks.push_back(base::WrapUnique(task2));
diff --git a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
index d53addc85b2..2793b7449b7 100644
--- a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
@@ -9,7 +9,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/time/tick_clock.h"
#include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
diff --git a/chromium/content/browser/isolated_origin_browsertest.cc b/chromium/content/browser/isolated_origin_browsertest.cc
index 417972f21b9..365f03302cb 100644
--- a/chromium/content/browser/isolated_origin_browsertest.cc
+++ b/chromium/content/browser/isolated_origin_browsertest.cc
@@ -30,6 +30,7 @@
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/network/public/cpp/features.h"
+#include "third_party/blink/public/common/features.h"
#include "url/gurl.h"
namespace content {
@@ -997,11 +998,12 @@ IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, IsolatedOriginWithSubdomain) {
// This class allows intercepting the OpenLocalStorage method and changing
// the parameters to the real implementation of it.
class StoragePartitonInterceptor
- : public mojom::StoragePartitionServiceInterceptorForTesting,
+ : public blink::mojom::StoragePartitionServiceInterceptorForTesting,
public RenderProcessHostObserver {
public:
- StoragePartitonInterceptor(RenderProcessHostImpl* rph,
- mojom::StoragePartitionServiceRequest request) {
+ StoragePartitonInterceptor(
+ RenderProcessHostImpl* rph,
+ blink::mojom::StoragePartitionServiceRequest request) {
StoragePartitionImpl* storage_partition =
static_cast<StoragePartitionImpl*>(rph->GetStoragePartition());
@@ -1030,7 +1032,7 @@ class StoragePartitonInterceptor
// Allow all methods that aren't explicitly overriden to pass through
// unmodified.
- mojom::StoragePartitionService* GetForwardingInterface() override {
+ blink::mojom::StoragePartitionService* GetForwardingInterface() override {
return storage_partition_service_;
}
@@ -1038,7 +1040,7 @@ class StoragePartitonInterceptor
// renderer process sending incorrect data to the browser process, so
// security checks can be tested.
void OpenLocalStorage(const url::Origin& origin,
- mojom::LevelDBWrapperRequest request) override {
+ blink::mojom::StorageAreaRequest request) override {
url::Origin mismatched_origin =
url::Origin::Create(GURL("http://abc.foo.com"));
GetForwardingInterface()->OpenLocalStorage(mismatched_origin,
@@ -1048,14 +1050,14 @@ class StoragePartitonInterceptor
private:
// Keep a pointer to the original implementation of the service, so all
// calls can be forwarded to it.
- mojom::StoragePartitionService* storage_partition_service_;
+ blink::mojom::StoragePartitionService* storage_partition_service_;
DISALLOW_COPY_AND_ASSIGN(StoragePartitonInterceptor);
};
void CreateTestStoragePartitionService(
RenderProcessHostImpl* rph,
- mojom::StoragePartitionServiceRequest request) {
+ blink::mojom::StoragePartitionServiceRequest request) {
// This object will register as RenderProcessHostObserver, so it will
// clean itself automatically on process exit.
new StoragePartitonInterceptor(rph, std::move(request));
@@ -1235,25 +1237,14 @@ IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, SubframeErrorPages) {
class IsolatedOriginTestWithMojoBlobURLs : public IsolatedOriginTest {
public:
IsolatedOriginTestWithMojoBlobURLs() {
- // Enabling NetworkService implies enabling MojoBlobURLs.
- scoped_feature_list_.InitAndEnableFeature(
- network::features::kNetworkService);
+ scoped_feature_list_.InitAndEnableFeature(blink::features::kMojoBlobURLs);
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
-#if defined(OS_ANDROID) || defined(OS_MACOSX)
-// Times out on android, and crashes on mac due to its dependency on network
-// service.
-#define MAYBE_NavigateToBlobURL DISABLED_NavigateToBlobURL
-#else
-#define MAYBE_NavigateToBlobURL NavigateToBlobURL
-#endif
-
-IN_PROC_BROWSER_TEST_F(IsolatedOriginTestWithMojoBlobURLs,
- MAYBE_NavigateToBlobURL) {
+IN_PROC_BROWSER_TEST_F(IsolatedOriginTestWithMojoBlobURLs, NavigateToBlobURL) {
GURL top_url(
embedded_test_server()->GetURL("www.foo.com", "/page_with_iframe.html"));
EXPECT_TRUE(NavigateToURL(shell(), top_url));
diff --git a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc
index a0b9c10d77b..f783d5356c8 100644
--- a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc
+++ b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc
@@ -80,21 +80,24 @@ void KeyboardLockServiceImpl::RequestKeyboardLock(
// Per base::flat_set usage notes, the proper way to init a flat_set is
// inserting into a vector and using that to init the flat_set.
std::vector<ui::DomCode> dom_codes;
+ bool invalid_key_code_found = false;
for (const std::string& code : key_codes) {
ui::DomCode dom_code = ui::KeycodeConverter::CodeStringToDomCode(code);
if (dom_code != ui::DomCode::NONE) {
dom_codes.push_back(dom_code);
} else {
+ invalid_key_code_found = true;
render_frame_host_->AddMessageToConsole(
ConsoleMessageLevel::CONSOLE_MESSAGE_LEVEL_WARNING,
"Invalid DOMString passed into keyboard.lock(): '" + code + "'");
}
}
- // If we are provided with a vector containing only invalid keycodes, then
- // exit without enabling keyboard lock. An empty vector is treated as
- // 'capture all keys' which is not what the caller intended.
- if (!key_codes.empty() && dom_codes.empty()) {
+ // If we are provided with a vector containing one or more invalid key codes,
+ // then exit without enabling keyboard lock. Also cancel any previous
+ // keyboard lock request since the most recent request failed.
+ if (invalid_key_code_found) {
+ render_frame_host_->GetRenderWidgetHost()->CancelKeyboardLock();
std::move(callback).Run(KeyboardLockRequestResult::kNoValidKeyCodesError);
return;
}
diff --git a/chromium/content/browser/keyboard_lock_browsertest.cc b/chromium/content/browser/keyboard_lock_browsertest.cc
index 2a4739de4af..4894106e59f 100644
--- a/chromium/content/browser/keyboard_lock_browsertest.cc
+++ b/chromium/content/browser/keyboard_lock_browsertest.cc
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/metrics/histogram_base.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "components/network_session_configurator/common/network_switches.h"
@@ -90,10 +90,11 @@ constexpr char kKeyboardLockMethodCallWithAllInvalidKeys[] =
" () => { window.domAutomationController.send(true); },"
");";
+// Calling lock() with some invalid key codes will reject the promise.
constexpr char kKeyboardLockMethodCallWithSomeInvalidKeys[] =
"navigator.keyboard.lock(['Tab', 'BlarghTab', 'Space', 'BlerghLeft']).then("
- " () => { window.domAutomationController.send(true); },"
" () => { window.domAutomationController.send(false); },"
+ " () => { window.domAutomationController.send(true); },"
");";
constexpr char kKeyboardUnlockMethodCall[] = "navigator.keyboard.unlock()";
@@ -634,7 +635,7 @@ IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, LockCallWithAllInvalidKeys) {
web_contents(), kKeyboardLockMethodCallWithAllInvalidKeys, &result));
ASSERT_TRUE(result);
- // If no valid Keys are passed in, then KeyboardLock will not be requested.
+ // If no valid Keys are passed in, then keyboard lock will not be requested.
ASSERT_FALSE(web_contents()->GetKeyboardLockWidget());
EnterFullscreen(FROM_HERE, url_for_test);
@@ -649,10 +650,24 @@ IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, LockCallWithSomeInvalidKeys) {
web_contents(), kKeyboardLockMethodCallWithSomeInvalidKeys, &result));
ASSERT_TRUE(result);
- // If some valid Keys are passed in, then KeyboardLock will be requested.
+ // If some valid Keys are passed in, then keyboard lock will not be requested.
+ ASSERT_FALSE(web_contents()->GetKeyboardLockWidget());
+}
+
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
+ ValidLockCallFollowedByInvalidLockCall) {
+ NavigateToTestURL(https_fullscreen_frame());
+
+ RequestKeyboardLock(FROM_HERE);
ASSERT_TRUE(web_contents()->GetKeyboardLockWidget());
- EnterFullscreen(FROM_HERE, url_for_test);
+ bool result;
+ ASSERT_TRUE(ExecuteScriptAndExtractBool(
+ web_contents(), kKeyboardLockMethodCallWithSomeInvalidKeys, &result));
+ ASSERT_TRUE(result);
+
+ // An invalid call will cancel any previous lock request.
+ ASSERT_FALSE(web_contents()->GetKeyboardLockWidget());
}
IN_PROC_BROWSER_TEST_F(KeyboardLockDisabledBrowserTest,
@@ -917,26 +932,6 @@ IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
}
IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- SubsequentLockCallSupersedesPreviousCall) {
- // TODO(joedow): Added per code review feedback.
- // Steps: 1. Request all keys, verify keys are locked
- // 2. Request subset of keys, verify the subset of keys are locked, but
- // non-requested keys are no longer locked
- // 3. Request all keys again, verify keys are now locked
-}
-
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- BrowserShortcutsHandledCorrectly) {
- // TODO(joedow): Added per code review feedback.
- // Steps: 1. Request keyboard lock for all keys
- // 2. Simulate browser shortcut (Ctrl+T)
- // 3. Verify new tab is not created
- // 4. Unlock keyboard
- // 5. Simulate browser shortcut (Ctrl+T)
- // 6. Verify new tab was created
-}
-
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
InnerContentsFullscreenBehavior) {
// TODO(joedow): Added per code review feedback. Need to define the behavior
// for KeyboardLock when an attached InnerWebContents goes fullscreen.
diff --git a/chromium/content/browser/linux_ipc_browsertest.cc b/chromium/content/browser/linux_ipc_browsertest.cc
deleted file mode 100644
index 7be05896fec..00000000000
--- a/chromium/content/browser/linux_ipc_browsertest.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <map>
-#include <set>
-#include <string>
-
-#include "base/command_line.h"
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-#include "content/browser/sandbox_ipc_linux.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 "services/service_manager/sandbox/switches.h"
-#include "testing/gmock/include/gmock/gmock-matchers.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class LinuxIPCBrowserTest : public ContentBrowserTest,
- public SandboxIPCHandler::TestObserver,
- public testing::WithParamInterface<std::string> {
- public:
- LinuxIPCBrowserTest() {
- SandboxIPCHandler::SetObserverForTests(this);
- }
- ~LinuxIPCBrowserTest() override {}
-
- protected:
- void SetUpCommandLine(base::CommandLine* command_line) override {
- ContentBrowserTest::SetUpCommandLine(command_line);
- if (GetParam() == "no-zygote") {
- command_line->AppendSwitch(service_manager::switches::kNoSandbox);
- command_line->AppendSwitch(switches::kNoZygote);
- }
- }
-
- void OnFontOpen(int id) override {
- base::AutoLock lock(lock_);
- opened_fonts_.insert(font_names_[id]);
- }
-
- void OnGetFallbackFontForChar(UChar32 c, std::string name, int id) override {
- base::AutoLock lock(lock_);
- fallback_fonts_[c] = name;
- font_names_[id] = name;
- }
-
- std::string FallbackFontName(UChar32 c) {
- base::AutoLock lock(lock_);
- return fallback_fonts_[c];
- }
-
- std::set<std::string> OpenedFonts() {
- base::AutoLock lock(lock_);
- return opened_fonts_;
- }
-
- // These variables are accessed on the IPC thread and the test thread.
- // All accesses on the IPC thread should be before the renderer process
- // completes navigation, and all accesses on the test thread should be after.
- // However we still need a mutex for the accesses to be sequenced according to
- // the C++ memory model.
- base::Lock lock_;
- std::map<UChar32, std::string> fallback_fonts_;
- std::map<int, std::string> font_names_;
- std::set<std::string> opened_fonts_;
-
- DISALLOW_COPY_AND_ASSIGN(LinuxIPCBrowserTest);
-};
-
-// Tests that Linux IPC font fallback code runs round-trip when Zygote is
-// disabled. It doesn't care what font is chosen, just that the IPC messages are
-// flowing. This test assumes that U+65E5 (CJK "Sun" character) will trigger the
-// font fallback codepath.
-IN_PROC_BROWSER_TEST_P(LinuxIPCBrowserTest, FontFallbackIPCWorks) {
- GURL test_url = GetTestUrl("font", "font_fallback.html");
- EXPECT_TRUE(NavigateToURL(shell(), test_url));
- EXPECT_THAT(FallbackFontName(U'\U000065E5'), testing::Ne(""));
- EXPECT_THAT(OpenedFonts(),
- testing::Contains(FallbackFontName(U'\U000065E5')));
-}
-
-INSTANTIATE_TEST_CASE_P(LinuxIPCBrowserTest,
- LinuxIPCBrowserTest,
- ::testing::Values("zygote", "no-zygote"));
-
-} // namespace
diff --git a/chromium/content/browser/loader/cors_file_origin_browsertest.cc b/chromium/content/browser/loader/cors_file_origin_browsertest.cc
index af3ed282f18..2b0e7a609ba 100644
--- a/chromium/content/browser/loader/cors_file_origin_browsertest.cc
+++ b/chromium/content/browser/loader/cors_file_origin_browsertest.cc
@@ -12,7 +12,10 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/scoped_command_line.h"
+#include "base/test/scoped_feature_list.h"
#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -24,6 +27,7 @@
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/embedded_test_server/request_handler_util.h"
#include "services/network/public/cpp/cors/cors.h"
+#include "services/network/public/cpp/features.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -37,11 +41,20 @@ using net::test_server::HttpResponse;
// Tests end to end Origin header and CORS check behaviors without
// --allow-file-access-from-files flag.
-class CORSFileOriginBrowserTest : public ContentBrowserTest {
+class CORSFileOriginBrowserTest : public ContentBrowserTest,
+ public testing::WithParamInterface<bool> {
public:
CORSFileOriginBrowserTest()
: pass_string_(base::ASCIIToUTF16("PASS")),
- fail_string_(base::ASCIIToUTF16("FAIL")) {}
+ fail_string_(base::ASCIIToUTF16("FAIL")) {
+ if (GetParam()) {
+ scoped_feature_list_.InitAndEnableFeature(
+ network::features::kOutOfBlinkCORS);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ network::features::kOutOfBlinkCORS);
+ }
+ }
~CORSFileOriginBrowserTest() override = default;
protected:
@@ -84,7 +97,15 @@ class CORSFileOriginBrowserTest : public ContentBrowserTest {
private:
bool AllowFileAccessFromFiles() const override { return false; }
+ virtual bool IsWebSecurityEnabled() const { return true; }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ if (!IsWebSecurityEnabled()) {
+ command_line->AppendSwitch(switches::kDisableWebSecurity);
+ }
+ ContentBrowserTest::SetUpCommandLine(command_line);
+ }
void SetUpOnMainThread() override {
base::AutoLock lock(lock_);
@@ -147,6 +168,9 @@ class CORSFileOriginBrowserTest : public ContentBrowserTest {
const base::string16 pass_string_;
const base::string16 fail_string_;
+ base::test::ScopedFeatureList scoped_command_line_;
+ base::test::ScopedFeatureList scoped_feature_list_;
+
DISALLOW_COPY_AND_ASSIGN(CORSFileOriginBrowserTest);
};
@@ -158,7 +182,16 @@ class CORSFileOriginBrowserTestWithAllowFileAccessFromFiles
bool AllowFileAccessFromFiles() const override { return true; }
};
-IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTest,
+// Tests end to end Origin header and CORS check behaviors with
+// --disable-web-security flag.
+class CORSFileOriginBrowserTestWithDisableWebSecurity
+ : public CORSFileOriginBrowserTest {
+ private:
+ bool AllowFileAccessFromFiles() const override { return false; }
+ bool IsWebSecurityEnabled() const override { return false; }
+};
+
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTest,
AccessControlAllowOriginIsNull) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
@@ -170,7 +203,7 @@ IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTest,
EXPECT_TRUE(is_preflight_requested());
}
-IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTest,
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTest,
AccessControlAllowOriginIsFile) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
@@ -182,7 +215,7 @@ IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTest,
EXPECT_TRUE(is_preflight_requested());
}
-IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
AccessControlAllowOriginIsNull) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
@@ -194,7 +227,7 @@ IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
EXPECT_TRUE(is_preflight_requested());
}
-IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
AccessControlAllowOriginIsFile) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
@@ -206,6 +239,47 @@ IN_PROC_BROWSER_TEST_F(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
EXPECT_TRUE(is_preflight_requested());
}
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithDisableWebSecurity,
+ AccessControlAllowOriginIsNull) {
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(), CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?port=%d&allow=%s&origin=%s",
+ port(), "unused", ""))));
+
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
+ EXPECT_FALSE(is_preflight_requested());
+}
+
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithDisableWebSecurity,
+ AccessControlAllowOriginIsFile) {
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(), CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?port=%d&allow=%s&origin=%s",
+ port(), "unused", ""))));
+
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
+ EXPECT_FALSE(is_preflight_requested());
+}
+
+// --allow-file-access-from-files is currently not supported by OOR-CORS.
+// We may remove the feature.
+INSTANTIATE_TEST_CASE_P(
+ /* No test prefix */,
+ CORSFileOriginBrowserTest,
+ ::testing::Values(false));
+
+INSTANTIATE_TEST_CASE_P(
+ /* No test prefix */,
+ CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
+ ::testing::Values(false));
+
+INSTANTIATE_TEST_CASE_P(
+ /* No test prefix */,
+ CORSFileOriginBrowserTestWithDisableWebSecurity,
+ ::testing::Values(false, true));
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc b/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
index 494ecda070c..321ab2c8e87 100644
--- a/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
+++ b/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -7,11 +7,12 @@
#include <utility>
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/strings/pattern.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/loader/cross_site_document_resource_handler.h"
@@ -31,15 +32,19 @@
#include "content/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/test/test_content_browser_client.h"
+#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
using testing::Not;
using testing::HasSubstr;
+using Action = network::CrossOriginReadBlocking::Action;
namespace {
@@ -83,6 +88,14 @@ void InspectHistograms(const base::HistogramTester& histograms,
const HistogramExpectations& expectations,
const std::string& resource_name,
ResourceType resource_type) {
+ // //services/network doesn't have access to content::ResourceType and
+ // therefore cannot log some XSDB UMAs.
+ bool is_restricted_uma_expected = false;
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ is_restricted_uma_expected = true;
+ FetchHistogramsFromChildProcesses();
+ }
+
std::string bucket;
if (base::MatchPattern(resource_name, "*.html")) {
bucket = "HTML";
@@ -103,16 +116,23 @@ void InspectHistograms(const base::HistogramTester& histograms,
std::string base = "SiteIsolation.XSD.Browser";
expected_counts[base + ".Action"] = 2;
if ((base::MatchPattern(resource_name, "*prefixed*") || bucket == "Others") &&
- (0 != (expectations & kShouldBeBlocked))) {
+ (0 != (expectations & kShouldBeBlocked)) && !is_restricted_uma_expected) {
expected_counts[base + ".BlockedForParserBreaker"] = 1;
}
if (0 != (expectations & kShouldBeSniffed))
expected_counts[base + ".BytesReadForSniffing"] = 1;
- if (0 != (expectations & kShouldBeBlocked)) {
+ if (0 != (expectations & kShouldBeBlocked && !is_restricted_uma_expected)) {
expected_counts[base + ".Blocked"] = 1;
expected_counts[base + ".Blocked." + bucket] = 1;
+ }
+ if (0 != (expectations & kShouldBeBlocked)) {
expected_counts[base + ".Blocked.ContentLength.WasAvailable"] = 1;
- if (0 != (expectations & kShouldHaveContentLength))
+ bool should_have_content_length =
+ 0 != (expectations & kShouldHaveContentLength);
+ histograms.ExpectBucketCount(base + ".Blocked.ContentLength.WasAvailable",
+ should_have_content_length, 1);
+
+ if (should_have_content_length)
expected_counts[base + ".Blocked.ContentLength.ValueIfAvailable"] = 1;
}
@@ -124,7 +144,7 @@ void InspectHistograms(const base::HistogramTester& histograms,
<< ", expectations=" << expectations;
// Determine if the bucket for the resource type (XHR) was incremented.
- if (0 != (expectations & kShouldBeBlocked)) {
+ if (0 != (expectations & kShouldBeBlocked) && !is_restricted_uma_expected) {
EXPECT_THAT(histograms.GetAllSamples(base + ".Blocked"),
testing::ElementsAre(base::Bucket(resource_type, 1)))
<< "The wrong Blocked bucket was incremented.";
@@ -132,6 +152,26 @@ void InspectHistograms(const base::HistogramTester& histograms,
testing::ElementsAre(base::Bucket(resource_type, 1)))
<< "The wrong Blocked bucket was incremented.";
}
+
+ // SiteIsolation.XSD.Browser.Action should always include kResponseStarted.
+ histograms.ExpectBucketCount(base + ".Action",
+ static_cast<int>(Action::kResponseStarted), 1);
+
+ // Second value in SiteIsolation.XSD.Browser.Action depends on |expectations|.
+ Action expected_action = static_cast<Action>(-1);
+ if (expectations & kShouldBeBlocked) {
+ if (expectations & kShouldBeSniffed)
+ expected_action = Action::kBlockedAfterSniffing;
+ else
+ expected_action = Action::kBlockedWithoutSniffing;
+ } else {
+ if (expectations & kShouldBeSniffed)
+ expected_action = Action::kAllowedAfterSniffing;
+ else
+ expected_action = Action::kAllowedWithoutSniffing;
+ }
+ histograms.ExpectBucketCount(base + ".Action",
+ static_cast<int>(expected_action), 1);
}
// Helper for intercepting a resource request to the given URL and capturing the
@@ -290,16 +330,18 @@ class DisableWebSecurityContentBrowserClient : public TestContentBrowserClient {
// Note that this BaseTest class does not specify an isolation mode via
// command-line flags. Most of the tests are in the --site-per-process subclass
// below.
-class CrossSiteDocumentBlockingBaseTest : public ContentBrowserTest {
+class CrossSiteDocumentBlockingTest : public ContentBrowserTest {
public:
- CrossSiteDocumentBlockingBaseTest() {}
- ~CrossSiteDocumentBlockingBaseTest() override {}
+ CrossSiteDocumentBlockingTest() {}
+ ~CrossSiteDocumentBlockingTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
// EmbeddedTestServer::InitializeAndListen() initializes its |base_url_|
// which is required below. This cannot invoke Start() however as that kicks
// off the "EmbeddedTestServer IO Thread" which then races with
// initialization in ContentBrowserTest::SetUp(), http://crbug.com/674545.
+ // Additionally the server should not be started prior to setting up
+ // ControllableHttpResponse(s) in some individual tests below.
ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
// Add a host resolver rule to map all outgoing requests to the test server.
@@ -313,10 +355,6 @@ class CrossSiteDocumentBlockingBaseTest : public ContentBrowserTest {
}
void SetUpOnMainThread() override {
- // Complete the manual Start() after ContentBrowserTest's own
- // initialization, ref. comment on InitializeAndListen() above.
- embedded_test_server()->StartAcceptingConnections();
-
// Disable web security via the ContentBrowserClient and notify the current
// renderer process.
old_client = SetBrowserClientForTesting(&new_client);
@@ -329,22 +367,6 @@ class CrossSiteDocumentBlockingBaseTest : public ContentBrowserTest {
DisableWebSecurityContentBrowserClient new_client;
ContentBrowserClient* old_client = nullptr;
- DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentBlockingBaseTest);
-};
-
-// Most tests here use --site-per-process, which enables document blocking
-// everywhere.
-class CrossSiteDocumentBlockingTest : public CrossSiteDocumentBlockingBaseTest {
- public:
- CrossSiteDocumentBlockingTest() {}
- ~CrossSiteDocumentBlockingTest() override {}
-
- void SetUpCommandLine(base::CommandLine* command_line) override {
- IsolateAllSitesForTesting(command_line);
- CrossSiteDocumentBlockingBaseTest::SetUpCommandLine(command_line);
- }
-
- private:
DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentBlockingTest);
};
@@ -355,6 +377,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockDocuments) {
// possible since we run the browser without the same origin policy, allowing
// it to see the response body if it makes it to the renderer (even if the
// renderer would normally block access to it).
+ embedded_test_server()->StartAcceptingConnections();
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -417,7 +440,8 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockDocuments) {
// jsonp.* - JSONP (i.e., script) mislabeled as a document.
// img.* - Contents that won't match the document label.
// valid.* - Correctly labeled responses of non-document types.
- const char* sniff_allowed_resources[] = {"js.html",
+ const char* sniff_allowed_resources[] = {"html-prefix.txt",
+ "js.html",
"comment_js.html",
"js.xml",
"js.json",
@@ -469,6 +493,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockDocuments) {
// be a problem for script files mislabeled as HTML/XML/JSON/text (i.e., the
// reason for sniffing), since script tags won't send Range headers.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, RangeRequest) {
+ embedded_test_server()->StartAcceptingConnections();
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -519,6 +544,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockForVariousTargets) {
// TODO(nick): Split up these cases, and add positive assertions here about
// what actually happens in these various resource-block cases.
+ embedded_test_server()->StartAcceptingConnections();
GURL foo("http://foo.com/cross_site_document_blocking/request_target.html");
EXPECT_TRUE(NavigateToURL(shell(), foo));
@@ -530,6 +556,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockForVariousTargets) {
// Regression test for https://crbug.com/814913.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest,
BlockRequestFromErrorPage) {
+ embedded_test_server()->StartAcceptingConnections();
GURL error_url = embedded_test_server()->GetURL("bar.com", "/close-socket");
GURL subresource_url =
embedded_test_server()->GetURL("foo.com", "/site_isolation/json.js");
@@ -560,10 +587,10 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest,
}
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
- GURL foo_url("http://foo.com/title1.html");
- EXPECT_TRUE(NavigateToURL(shell(), foo_url));
+ embedded_test_server()->StartAcceptingConnections();
// Prepare to intercept the network request at the IPC layer.
+ // This has to be done before the RenderFrameHostImpl is created.
//
// Note: we want to verify that the blocking prevents the data from being sent
// over IPC. Testing later (e.g. via Response/Headers Web APIs) might give a
@@ -572,6 +599,10 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
GURL bar_url("http://bar.com/cross_site_document_blocking/headers-test.json");
RequestInterceptor interceptor(bar_url);
+ // Navigate to the test page.
+ GURL foo_url("http://foo.com/title1.html");
+ EXPECT_TRUE(NavigateToURL(shell(), foo_url));
+
// Issue the request that will be intercepted
EXPECT_TRUE(ExecuteScript(shell(),
base::StringPrintf("fetch('%s').catch(error => {})",
@@ -580,7 +611,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
// Verify that the response completed successfully and was blocked.
ASSERT_EQ(net::OK, interceptor.completion_status().error_code);
- ASSERT_TRUE(interceptor.completion_status().blocked_cross_site_document);
+ ASSERT_TRUE(interceptor.completion_status().should_report_corb_blocking);
// Verify that safelisted headers have not been removed by XSDB.
// See https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name.
@@ -623,6 +654,113 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
EXPECT_EQ(0u, interceptor.response_head().content_length);
}
+IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, PrefetchIsNotImpacted) {
+ // Prepare for intercepting the resource request for testing prefetching.
+ const char* kPrefetchResourcePath = "/prefetch-test";
+ net::test_server::ControllableHttpResponse response(embedded_test_server(),
+ kPrefetchResourcePath);
+
+ // Navigate to a webpage containing a cross-origin frame.
+ embedded_test_server()->StartAcceptingConnections();
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Inject a cross-origin <link rel="prefetch" ...> into the main frame.
+ // TODO(lukasza): https://crbug.com/827633#c5: We might need to switch to
+ // listening to the onload event below (after/if CORB starts to consistently
+ // avoid injecting net errors).
+ const char* prefetch_injection_script_template = R"(
+ var link = document.createElement("link");
+ link.rel = "prefetch";
+ link.href = "/cross-site/b.com%s";
+ link.as = "fetch";
+
+ window.is_prefetch_done = false;
+ function mark_prefetch_as_done() { window.is_prefetch_done = true }
+ link.onerror = mark_prefetch_as_done;
+
+ document.getElementsByTagName('head')[0].appendChild(link);
+ )";
+ std::string prefetch_injection_script = base::StringPrintf(
+ prefetch_injection_script_template, kPrefetchResourcePath);
+ EXPECT_TRUE(
+ ExecuteScript(shell()->web_contents(), prefetch_injection_script));
+
+ // Respond to the prefetch request in a way that:
+ // 1) will enable caching
+ // 2) won't finish until after CORB has blocked the response.
+ FetchHistogramsFromChildProcesses();
+ base::HistogramTester histograms;
+ std::string response_bytes =
+ "HTTP/1.1 200 OK\r\n"
+ "Cache-Control: public, max-age=10\r\n"
+ "Content-Type: text/html\r\n"
+ "X-Content-Type-Options: nosniff\r\n"
+ "\r\n"
+ "<p>contents of the response</p>";
+ response.WaitForRequest();
+ response.Send(response_bytes);
+
+ // Verify that CORB blocked the response.
+ // TODO(lukasza): https://crbug.com/827633#c5: We might need to switch to
+ // listening to the onload event below (after/if CORB starts to consistently
+ // avoid injecting net errors).
+ std::string wait_script = R"(
+ function notify_prefetch_is_done() { domAutomationController.send(123); }
+
+ if (window.is_prefetch_done) {
+ // Can notify immediately if |window.is_prefetch_done| has already been
+ // set by |prefetch_injection_script|.
+ notify_prefetch_is_done();
+ } else {
+ // Otherwise wait for CORB's empty response to reach the renderer.
+ link = document.getElementsByTagName('link')[0];
+ link.onerror = notify_prefetch_is_done;
+ }
+ )";
+ int answer;
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(shell()->web_contents(), wait_script,
+ &answer));
+ EXPECT_EQ(123, answer);
+ InspectHistograms(histograms, kShouldBeBlockedWithoutSniffing, "x.html",
+ RESOURCE_TYPE_PREFETCH);
+
+ // Finish the HTTP response - this should store the response in the cache.
+ response.Done();
+
+ // Stop the HTTP server - this means the only way to get the response in
+ // the |fetch_script| below is to get it from the cache (e.g. if the request
+ // goes to the network there will be no HTTP server to handle it).
+ // Note that stopping the HTTP server is not strictly required for the test to
+ // be robust - ControllableHttpResponse handles only a single request, so
+ // wouldn't handle the |fetch_script| request even if the HTTP server was
+ // still running.
+ EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+
+ // Verify that the cached response is available to the same-origin subframe
+ // (e.g. that the network cache in the browser process got populated despite
+ // CORB blocking).
+ const char* fetch_script_template = R"(
+ fetch('%s')
+ .then(response => response.text())
+ .then(responseBody => {
+ domAutomationController.send(responseBody);
+ })
+ .catch(error => {
+ var errorMessage = 'error: ' + error;
+ console.log(errorMessage);
+ domAutomationController.send(errorMessage);
+ }); )";
+ std::string fetch_script =
+ base::StringPrintf(fetch_script_template, kPrefetchResourcePath);
+ std::string response_body;
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractString(shell()->web_contents()->GetAllFrames()[1],
+ fetch_script, &response_body));
+ EXPECT_EQ("<p>contents of the response</p>", response_body);
+}
+
// This test class sets up a service worker that can be used to try to respond
// to same-origin requests with cross-origin responses.
class CrossSiteDocumentBlockingServiceWorkerTest : public ContentBrowserTest {
@@ -735,6 +873,12 @@ class CrossSiteDocumentBlockingServiceWorkerTest : public ContentBrowserTest {
// TODO(lukasza): https://crbug.com/715640: This test might become invalid
// after servicification of service workers.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingServiceWorkerTest, NoNetwork) {
+ // Skip this test when servicification of service workers (S13nServiceWorker)
+ // is enabled because the browser process doesn't see the request or response
+ // when the request is handled entirely within the service worker.
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
SetUpServiceWorker();
base::HistogramTester histograms;
@@ -766,6 +910,11 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingServiceWorkerTest,
NetworkToServiceWorkerResponse) {
SetUpServiceWorker();
+ // Make sure that the histograms generated by a service worker registration
+ // have been recorded.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ FetchHistogramsFromChildProcesses();
+
// Build a script for XHR-ing a cross-origin, nosniff HTML document.
GURL cross_origin_url =
GetURLOnCrossOriginServer("/site_isolation/nosniff.txt");
@@ -826,6 +975,7 @@ class CrossSiteDocumentBlockingKillSwitchTest
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingKillSwitchTest,
NoBlockingWithKillSwitch) {
// Load a page that issues illegal cross-site document requests to bar.com.
+ embedded_test_server()->StartAcceptingConnections();
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -855,6 +1005,7 @@ class CrossSiteDocumentBlockingDisableWebSecurityTest
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingDisableWebSecurityTest,
DisableBlocking) {
// Load a page that issues illegal cross-site document requests.
+ embedded_test_server()->StartAcceptingConnections();
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -885,6 +1036,7 @@ class CrossSiteDocumentBlockingDisableVsFeatureTest
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingDisableVsFeatureTest,
DisableBlocking) {
// Load a page that issues illegal cross-site document requests.
+ embedded_test_server()->StartAcceptingConnections();
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -894,23 +1046,9 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingDisableVsFeatureTest,
EXPECT_FALSE(was_blocked);
}
-// Even without any Site Isolation, document blocking should be turned on by
-// default.
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingBaseTest,
- BlockDocumentsByDefault) {
- // Load a page that issues illegal cross-site document requests to bar.com.
- GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
- EXPECT_TRUE(NavigateToURL(shell(), foo_url));
-
- bool was_blocked;
- ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell(), "sendRequest(\"valid.html\");", &was_blocked));
- EXPECT_TRUE(was_blocked);
-}
-
// Test class to verify that documents are blocked for isolated origins as well.
class CrossSiteDocumentBlockingIsolatedOriginTest
- : public CrossSiteDocumentBlockingBaseTest {
+ : public CrossSiteDocumentBlockingTest {
public:
CrossSiteDocumentBlockingIsolatedOriginTest() {}
~CrossSiteDocumentBlockingIsolatedOriginTest() override {}
@@ -918,7 +1056,7 @@ class CrossSiteDocumentBlockingIsolatedOriginTest
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kIsolateOrigins,
"http://bar.com");
- CrossSiteDocumentBlockingBaseTest::SetUpCommandLine(command_line);
+ CrossSiteDocumentBlockingTest::SetUpCommandLine(command_line);
}
private:
@@ -927,6 +1065,7 @@ class CrossSiteDocumentBlockingIsolatedOriginTest
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingIsolatedOriginTest,
BlockDocumentsFromIsolatedOrigin) {
+ embedded_test_server()->StartAcceptingConnections();
if (AreAllSitesIsolatedForTesting())
return;
diff --git a/chromium/content/browser/loader/cross_site_document_resource_handler.cc b/chromium/content/browser/loader/cross_site_document_resource_handler.cc
index 9924a53b147..90792270128 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler.cc
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler.cc
@@ -20,6 +20,7 @@
#include "content/browser/loader/detachable_resource_handler.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/site_instance_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
@@ -66,16 +67,15 @@ void CrossSiteDocumentResourceHandler::LogBlockedResponseOnUIThread(
if (!web_contents)
return;
- ukm::UkmRecorder* recorder = ukm::UkmRecorder::Get();
- ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
- recorder->UpdateSourceURL(source_id, web_contents->GetLastCommittedURL());
+ ukm::SourceId source_id = static_cast<WebContentsImpl*>(web_contents)
+ ->GetUkmSourceIdForLastCommittedSource();
ukm::builders::SiteIsolation_XSD_Browser_Blocked(source_id)
.SetCanonicalMimeType(static_cast<int64_t>(canonical_mime_type))
.SetContentLengthWasZero(content_length == 0)
.SetContentResourceType(resource_type)
.SetHttpResponseCode(http_response_code)
.SetNeededSniffing(needed_sniffing)
- .Record(recorder);
+ .Record(ukm::UkmRecorder::Get());
}
void CrossSiteDocumentResourceHandler::LogBlockedResponse(
@@ -166,6 +166,14 @@ class CrossSiteDocumentResourceHandler::Controller : public ResourceController {
}
}
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ Resume();
+ }
+
void Cancel() override {
MarkAsUsed();
document_handler_->Cancel();
@@ -212,8 +220,6 @@ void CrossSiteDocumentResourceHandler::OnResponseStarted(
network::ResourceResponse* response,
std::unique_ptr<ResourceController> controller) {
has_response_started_ = true;
- http_response_code_ =
- response->head.headers ? response->head.headers->response_code() : 0;
network::CrossOriginReadBlocking::LogAction(
network::CrossOriginReadBlocking::Action::kResponseStarted);
@@ -388,8 +394,8 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
// If we have some new data, ask the |analyzer_| to sniff it.
analyzer_->SniffResponseBody(data, new_data_offset);
- const bool confirmed_allowed = analyzer_->should_allow();
- confirmed_blockable = analyzer_->should_block();
+ const bool confirmed_allowed = analyzer_->ShouldAllow();
+ confirmed_blockable = analyzer_->ShouldBlock();
DCHECK(!(confirmed_blockable && confirmed_allowed));
// If sniffing didn't yield a conclusive response, and we haven't read too
@@ -425,11 +431,13 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
: "null",
"url", request()->url().spec());
- LogBlockedResponse(info, http_response_code_);
+ LogBlockedResponse(info, analyzer_->http_response_code());
// Block the response and throw away the data. Report zero bytes read.
blocked_read_completed_ = true;
- info->set_blocked_cross_site_document(true);
+ info->set_blocked_response_from_reaching_renderer(true);
+ if (analyzer_->ShouldReportBlockedResponse())
+ info->set_should_report_corb_blocking(true);
network::CrossOriginReadBlocking::SanitizeBlockedResponse(
pending_response_start_);
@@ -535,10 +543,17 @@ void CrossSiteDocumentResourceHandler::OnResponseCompleted(
bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
const network::ResourceResponse& response) {
+ // Give embedder a chance to skip document blocking for this response.
+ const char* initiator_scheme_exception =
+ GetContentClient()
+ ->browser()
+ ->GetInitatorSchemeBypassingDocumentBlocking();
+
+ // Delegate most decisions to CrossOriginReadBlocking::ResponseAnalyzer.
analyzer_ =
std::make_unique<network::CrossOriginReadBlocking::ResponseAnalyzer>(
- *request(), response);
- if (analyzer_->should_allow())
+ *request(), response, initiator_scheme_exception);
+ if (analyzer_->ShouldAllow())
return false;
// Check if the response's site needs to have its documents protected. By
@@ -567,21 +582,12 @@ bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
if (!info || info->GetChildID() == -1)
return false;
- // Give embedder a chance to skip document blocking for this response.
- const char* initiator_scheme_exception =
- GetContentClient()
- ->browser()
- ->GetInitatorSchemeBypassingDocumentBlocking();
- if (initiator_scheme_exception && request()->initiator().has_value() &&
- request()->initiator()->scheme() == initiator_scheme_exception) {
- return false;
- }
-
- // Don't block plugin requests with universal access (e.g., Flash). Such
- // requests are made without CORS, and thus dont have an Origin request
- // header. Other plugin requests (e.g., NaCl) are made using CORS and have an
- // Origin request header. If they fail the CORS check above, they should be
- // blocked.
+ // Don't block plugin requests.
+ // TODO(lukasza): Only disable CORB for plugins with universal access (see
+ // PepperURLLoaderHost::has_universal_access_), because only such plugins may
+ // have their own CORS-like mechanisms - e.g. crossdomain.xml in Flash). We
+ // should still enforce CORB for other kinds of plugins (i.e. ones without
+ // universal access).
if (info->GetResourceType() == RESOURCE_TYPE_PLUGIN_RESOURCE &&
is_nocors_plugin_request_) {
return false;
diff --git a/chromium/content/browser/loader/cross_site_document_resource_handler.h b/chromium/content/browser/loader/cross_site_document_resource_handler.h
index 447c6ed2699..1598fb024bd 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler.h
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler.h
@@ -164,10 +164,6 @@ class CONTENT_EXPORT CrossSiteDocumentResourceHandler
// completed, and thus it is safe to cancel or detach on the next read.
bool blocked_read_completed_ = false;
- // The HTTP response code (e.g. 200 or 404) received in response to this
- // resource request.
- int http_response_code_ = 0;
-
base::WeakPtrFactory<CrossSiteDocumentResourceHandler> weak_this_;
DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentResourceHandler);
diff --git a/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc b/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc
index 7f66b566c8b..99405d1b48e 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc
@@ -20,7 +20,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/loader/intercepting_resource_handler.h"
#include "content/browser/loader/mime_sniffing_resource_handler.h"
diff --git a/chromium/content/browser/loader/data_pipe_to_source_stream.cc b/chromium/content/browser/loader/data_pipe_to_source_stream.cc
index 8a5c372798f..4a3694f5b01 100644
--- a/chromium/content/browser/loader/data_pipe_to_source_stream.cc
+++ b/chromium/content/browser/loader/data_pipe_to_source_stream.cc
@@ -4,6 +4,8 @@
#include "content/browser/loader/data_pipe_to_source_stream.h"
+#include <utility>
+
#include "base/auto_reset.h"
#include "net/base/io_buffer.h"
@@ -30,7 +32,7 @@ std::string DataPipeToSourceStream::Description() const {
int DataPipeToSourceStream::Read(net::IOBuffer* buf,
int buf_size,
- const net::CompletionCallback& callback) {
+ net::CompletionOnceCallback callback) {
base::AutoReset<bool>(&inside_read_, true);
if (!body_.get()) {
@@ -56,7 +58,7 @@ int DataPipeToSourceStream::Read(net::IOBuffer* buf,
return 0;
case MOJO_RESULT_SHOULD_WAIT:
// Data is not available yet.
- pending_callback_ = callback;
+ pending_callback_ = std::move(callback);
output_buf_ = buf;
output_buf_size_ = buf_size;
handle_watcher_.ArmOrNotify();
diff --git a/chromium/content/browser/loader/data_pipe_to_source_stream.h b/chromium/content/browser/loader/data_pipe_to_source_stream.h
index e45d2482e87..f77287f0611 100644
--- a/chromium/content/browser/loader/data_pipe_to_source_stream.h
+++ b/chromium/content/browser/loader/data_pipe_to_source_stream.h
@@ -8,6 +8,7 @@
#include "content/common/content_export.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
+#include "net/base/completion_once_callback.h"
#include "net/filter/source_stream.h"
namespace content {
@@ -19,7 +20,7 @@ class CONTENT_EXPORT DataPipeToSourceStream final : public net::SourceStream {
int Read(net::IOBuffer* buf,
int buf_size,
- const net::CompletionCallback& callback) override;
+ net::CompletionOnceCallback callback) override;
std::string Description() const override;
private:
@@ -33,7 +34,7 @@ class CONTENT_EXPORT DataPipeToSourceStream final : public net::SourceStream {
scoped_refptr<net::IOBuffer> output_buf_;
int output_buf_size_ = 0;
- net::CompletionCallback pending_callback_;
+ net::CompletionOnceCallback pending_callback_;
DISALLOW_COPY_AND_ASSIGN(DataPipeToSourceStream);
};
diff --git a/chromium/content/browser/loader/detachable_resource_handler.cc b/chromium/content/browser/loader/detachable_resource_handler.cc
index b8222d203d1..26593e97ec0 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.cc
+++ b/chromium/content/browser/loader/detachable_resource_handler.cc
@@ -38,6 +38,14 @@ class DetachableResourceHandler::Controller : public ResourceController {
detachable_handler_->ResumeInternal();
}
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ Resume();
+ }
+
void Cancel() override {
MarkAsUsed();
detachable_handler_->Cancel();
@@ -249,13 +257,6 @@ void DetachableResourceHandler::OnResponseCompleted(
std::make_unique<Controller>(this));
}
-void DetachableResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- if (!next_handler_)
- return;
-
- next_handler_->OnDataDownloaded(bytes_downloaded);
-}
-
void DetachableResourceHandler::ResumeInternal() {
parent_read_buffer_ = nullptr;
parent_read_buffer_size_ = nullptr;
diff --git a/chromium/content/browser/loader/detachable_resource_handler.h b/chromium/content/browser/loader/detachable_resource_handler.h
index 972ffd13523..9e7e418a2f2 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.h
+++ b/chromium/content/browser/loader/detachable_resource_handler.h
@@ -69,7 +69,6 @@ class CONTENT_EXPORT DetachableResourceHandler : public ResourceHandler {
void OnResponseCompleted(
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- void OnDataDownloaded(int bytes_downloaded) override;
private:
class Controller;
diff --git a/chromium/content/browser/loader/navigation_loader_util.cc b/chromium/content/browser/loader/download_utils_impl.cc
index 96a7879b520..4af0a41e592 100644
--- a/chromium/content/browser/loader/navigation_loader_util.cc
+++ b/chromium/content/browser/loader/download_utils_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/loader/navigation_loader_util.h"
+#include "content/browser/loader/download_utils_impl.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
@@ -10,13 +10,12 @@
#include "net/http/http_response_headers.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "url/gurl.h"
-#include "url/origin.h"
namespace content {
-namespace navigation_loader_util {
+namespace download_utils {
bool MustDownload(const GURL& url,
- net::HttpResponseHeaders* headers,
+ const net::HttpResponseHeaders* headers,
const std::string& mime_type) {
if (headers) {
std::string disposition;
@@ -43,7 +42,7 @@ bool MustDownload(const GURL& url,
}
bool IsDownload(const GURL& url,
- net::HttpResponseHeaders* headers,
+ const net::HttpResponseHeaders* headers,
const std::string& mime_type) {
if (MustDownload(url, headers, mime_type))
return true;
@@ -54,5 +53,5 @@ bool IsDownload(const GURL& url,
return !headers || headers->response_code() / 100 == 2;
}
-} // namespace navigation_loader_util
+} // namespace download_utils
} // namespace content
diff --git a/chromium/content/browser/loader/download_utils_impl.h b/chromium/content/browser/loader/download_utils_impl.h
new file mode 100644
index 00000000000..724e45ba529
--- /dev/null
+++ b/chromium/content/browser/loader/download_utils_impl.h
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_LOADER_DOWNLOAD_UTILS_IMPL_H_
+#define CONTENT_BROWSER_LOADER_DOWNLOAD_UTILS_IMPL_H_
+
+#include "content/public/browser/download_utils.h"
+
+namespace content {
+namespace download_utils {
+
+// Determines whether given response would result in a download.
+// Note this doesn't handle the case when a plugin exists for the |mime_type|.
+bool IsDownload(const GURL& url,
+ const net::HttpResponseHeaders* headers,
+ const std::string& mime_type);
+
+} // namespace download_utils
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_DOWNLOAD_UTILS_IMPL_H_
diff --git a/chromium/content/browser/loader/downloaded_temp_file_impl.cc b/chromium/content/browser/loader/downloaded_temp_file_impl.cc
deleted file mode 100644
index f699d84df04..00000000000
--- a/chromium/content/browser/loader/downloaded_temp_file_impl.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/downloaded_temp_file_impl.h"
-
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace content {
-
-// static
-network::mojom::DownloadedTempFilePtr DownloadedTempFileImpl::Create(
- int child_id,
- int request_id) {
- mojo::InterfacePtr<network::mojom::DownloadedTempFile> ptr;
- mojo::MakeStrongBinding(
- std::make_unique<DownloadedTempFileImpl>(child_id, request_id),
- mojo::MakeRequest(&ptr));
- return ptr;
-}
-
-DownloadedTempFileImpl::~DownloadedTempFileImpl() {
- ResourceDispatcherHostImpl::Get()->UnregisterDownloadedTempFile(child_id_,
- request_id_);
-}
-DownloadedTempFileImpl::DownloadedTempFileImpl(int child_id, int request_id)
- : child_id_(child_id), request_id_(request_id) {}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/downloaded_temp_file_impl.h b/chromium/content/browser/loader/downloaded_temp_file_impl.h
deleted file mode 100644
index 07deff40610..00000000000
--- a/chromium/content/browser/loader/downloaded_temp_file_impl.h
+++ /dev/null
@@ -1,40 +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_LOADER_DOWNLOADED_TEMP_FILE_IMPL_H_
-#define CONTENT_BROWSER_LOADER_DOWNLOADED_TEMP_FILE_IMPL_H_
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-
-namespace content {
-
-// DownloadedTempFileImpl is created on the download_to_file mode of resource
-// loading. The instance is held by the client and lives until the client
-// destroys the interface, slightly after the URLLoader is destroyed.
-class CONTENT_EXPORT DownloadedTempFileImpl final
- : public network::mojom::DownloadedTempFile {
- public:
- // Creates a DownloadedTempFileImpl, binds it as a strong interface, and
- // returns the interface ptr to be passed to the client.
- // That means:
- // * The DownloadedTempFile object created here is essentially owned by the
- // client. It keeps alive until the client destroys the other endpoint.
- static network::mojom::DownloadedTempFilePtr Create(int child_id,
- int request_id);
-
- DownloadedTempFileImpl(int child_id, int request_id);
- ~DownloadedTempFileImpl() override;
-
- private:
- const int child_id_;
- const int request_id_;
-
- DISALLOW_COPY_AND_ASSIGN(DownloadedTempFileImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_DOWNLOADED_TEMP_FILE_IMPL_H_
diff --git a/chromium/content/browser/loader/intercepting_resource_handler.cc b/chromium/content/browser/loader/intercepting_resource_handler.cc
index 0b038d238a1..a7c3a1010ea 100644
--- a/chromium/content/browser/loader/intercepting_resource_handler.cc
+++ b/chromium/content/browser/loader/intercepting_resource_handler.cc
@@ -29,6 +29,14 @@ class InterceptingResourceHandler::Controller : public ResourceController {
intercepting_handler_->ResumeInternal();
}
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ Resume();
+ }
+
void Cancel() override {
MarkAsUsed();
intercepting_handler_->Cancel();
diff --git a/chromium/content/browser/loader/layered_resource_handler.cc b/chromium/content/browser/loader/layered_resource_handler.cc
index 340025a4b70..9a163e7d18b 100644
--- a/chromium/content/browser/loader/layered_resource_handler.cc
+++ b/chromium/content/browser/loader/layered_resource_handler.cc
@@ -69,9 +69,4 @@ void LayeredResourceHandler::OnResponseCompleted(
next_handler_->OnResponseCompleted(status, std::move(controller));
}
-void LayeredResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- DCHECK(next_handler_.get());
- next_handler_->OnDataDownloaded(bytes_downloaded);
-}
-
} // namespace content
diff --git a/chromium/content/browser/loader/layered_resource_handler.h b/chromium/content/browser/loader/layered_resource_handler.h
index 47d37bca55f..2aa0e245127 100644
--- a/chromium/content/browser/loader/layered_resource_handler.h
+++ b/chromium/content/browser/loader/layered_resource_handler.h
@@ -45,7 +45,6 @@ class CONTENT_EXPORT LayeredResourceHandler : public ResourceHandler {
void OnResponseCompleted(
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- void OnDataDownloaded(int bytes_downloaded) override;
std::unique_ptr<ResourceHandler> next_handler_;
};
diff --git a/chromium/content/browser/loader/loader_browsertest.cc b/chromium/content/browser/loader/loader_browsertest.cc
index 450919d3c3b..024fadee921 100644
--- a/chromium/content/browser/loader/loader_browsertest.cc
+++ b/chromium/content/browser/loader/loader_browsertest.cc
@@ -273,17 +273,20 @@ namespace {
// Responds with a HungResponse for the specified URL to hang on the request.
// If the network service is enabled, crashes the process. If it's disabled,
// cancels all requests from specifield |child_id|.
+//
+// |crash_network_service_callback| crashes the network service when invoked,
+// and must be called on the UI thread.
std::unique_ptr<net::test_server::HttpResponse> CancelOnRequest(
const std::string& relative_url,
int child_id,
+ base::RepeatingClosure crash_network_service_callback,
const net::test_server::HttpRequest& request) {
if (request.relative_url != relative_url)
return nullptr;
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
- base::BindOnce(SimulateNetworkServiceCrash));
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ crash_network_service_callback);
} else {
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
@@ -303,7 +306,9 @@ std::unique_ptr<net::test_server::HttpResponse> CancelOnRequest(
IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, SyncXMLHttpRequest_Cancelled) {
embedded_test_server()->RegisterRequestHandler(base::Bind(
&CancelOnRequest, "/hung",
- shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(),
+ base::BindRepeating(&BrowserTestBase::SimulateNetworkServiceCrash,
+ base::Unretained(this))));
ASSERT_TRUE(embedded_test_server()->Start());
WaitForLoadStop(shell()->web_contents());
@@ -813,25 +818,6 @@ IN_PROC_BROWSER_TEST_F(PreviewsStateBrowserTest,
CheckResourcesRequested(true);
}
-// Test that reloading with Lo-Fi disabled doesn't call ShouldEnableLoFiMode and
-// already has LOFI_OFF.
-IN_PROC_BROWSER_TEST_F(PreviewsStateBrowserTest,
- ShouldEnableLoFiModeReloadDisableLoFi) {
- // Navigate with GetPreviewsState returning SERVER_LOFI_ON.
- Reset(SERVER_LOFI_ON);
- NavigateToURLBlockUntilNavigationsComplete(
- shell(), embedded_test_server()->GetURL("/page_with_iframe.html"), 1);
- CheckResourcesRequested(true);
-
- // Reload with Lo-Fi disabled.
- Reset(PREVIEWS_NO_TRANSFORM);
- TestNavigationObserver tab_observer(shell()->web_contents(), 1);
- shell()->web_contents()->GetController().Reload(ReloadType::DISABLE_PREVIEWS,
- true);
- tab_observer.Wait();
- CheckResourcesRequested(false);
-}
-
namespace {
struct RequestData {
@@ -871,6 +857,19 @@ class RequestDataBrowserTest : public ContentBrowserTest {
return copy;
}
+ void WaitForRequests(size_t count) {
+ while (true) {
+ base::RunLoop run_loop;
+ {
+ base::AutoLock auto_lock(requests_lock_);
+ if (requests_.size() == count)
+ return;
+ requests_closure_ = run_loop.QuitClosure();
+ }
+ run_loop.Run();
+ }
+ }
+
private:
void SetUpOnMainThread() override {
ContentBrowserTest::SetUpOnMainThread();
@@ -893,10 +892,13 @@ class RequestDataBrowserTest : public ContentBrowserTest {
void RequestCreated(RequestData data) {
base::AutoLock auto_lock(requests_lock_);
requests_.push_back(data);
+ if (requests_closure_)
+ requests_closure_.Run();
}
base::Lock requests_lock_;
std::vector<RequestData> requests_;
+ base::Closure requests_closure_;
std::unique_ptr<URLLoaderInterceptor> interceptor_;
};
@@ -928,6 +930,7 @@ IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, LinkRelPrefetch) {
url::Origin top_origin = url::Origin::Create(top_url);
NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+ WaitForRequests(2u);
auto requests = data();
EXPECT_EQ(2u, requests.size());
@@ -944,6 +947,7 @@ IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, LinkRelPrefetchReferrerPolicy) {
url::Origin top_origin = url::Origin::Create(top_url);
NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+ WaitForRequests(2u);
auto requests = data();
EXPECT_EQ(2u, requests.size());
diff --git a/chromium/content/browser/loader/merkle_integrity_source_stream.cc b/chromium/content/browser/loader/merkle_integrity_source_stream.cc
index 4643113b761..94c532f18e2 100644
--- a/chromium/content/browser/loader/merkle_integrity_source_stream.cc
+++ b/chromium/content/browser/loader/merkle_integrity_source_stream.cc
@@ -19,7 +19,7 @@ namespace {
// maximum record size in TLS and the default maximum frame size in HTTP/2.
constexpr uint64_t kMaxRecordSize = 16 * 1024;
-constexpr char kMiSha256Header[] = "mi-sha256=";
+constexpr char kMiSha256Header[] = "mi-sha256-draft2=";
constexpr size_t kMiSha256HeaderLength = sizeof(kMiSha256Header) - 1;
// Copies as many bytes from |input| as will fit in |output| and advances both.
diff --git a/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc b/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
index dc1d802e457..61c61692ec5 100644
--- a/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
+++ b/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
@@ -17,13 +17,13 @@ const int kBigBufferSize = 4096;
const int kSmallBufferSize = 1;
const char kMIEmptyBody[] =
- "mi-sha256=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0";
+ "mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0";
const char kMISingleRecord[] =
- "mi-sha256=dcRDgR2GM35DluAV13PzgnG6-pvQwPywfFvAu1UeFrs";
+ "mi-sha256-draft2=dcRDgR2GM35DluAV13PzgnG6-pvQwPywfFvAu1UeFrs";
const char kMIMultipleRecords[] =
- "mi-sha256=IVa9shfs0nyKEhHqtB3WVNANJ2Njm5KjQLjRtnbkYJ4";
+ "mi-sha256-draft2=IVa9shfs0nyKEhHqtB3WVNANJ2Njm5KjQLjRtnbkYJ4";
const char kMIWholeNumberOfRecords[] =
- "mi-sha256=L2vdwBplKvIr0ZPkcuskWZfEVDgVdHa6aD363UpKuZs";
+ "mi-sha256-draft2=L2vdwBplKvIr0ZPkcuskWZfEVDgVdHa6aD363UpKuZs";
enum class ReadResultType {
// Each call to AddReadResult is a separate read from the lower layer
@@ -180,7 +180,7 @@ TEST_P(MerkleIntegritySourceStreamTest, MalformedMIHeader) {
}
TEST_P(MerkleIntegritySourceStreamTest, WrongMIAttributeName) {
- Init("mi-sha255=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0");
+ Init("mi-sha256-draft1=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0");
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int result = ReadStream(&actual_output);
@@ -188,7 +188,7 @@ TEST_P(MerkleIntegritySourceStreamTest, WrongMIAttributeName) {
}
TEST_P(MerkleIntegritySourceStreamTest, HashTooShort) {
- Init("mi-sha256=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoA");
+ Init("mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoA");
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int result = ReadStream(&actual_output);
@@ -196,7 +196,7 @@ TEST_P(MerkleIntegritySourceStreamTest, HashTooShort) {
}
TEST_P(MerkleIntegritySourceStreamTest, HashTooLong) {
- Init("mi-sha256=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0A");
+ Init("mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0A");
source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode);
std::string actual_output;
int result = ReadStream(&actual_output);
@@ -470,7 +470,7 @@ TEST_P(MerkleIntegritySourceStreamTest, Truncated) {
// represent the empty string. Update the code and possibly this test depending
// on how https://github.com/martinthomson/http-mice/issues/3 is resolved.
TEST_P(MerkleIntegritySourceStreamTest, EmptyFinalRecord) {
- Init("mi-sha256=JJnIuaOEc2247K9V88VQAQy1GJuQ6ylaVM7mG69QkE4");
+ Init("mi-sha256-draft2=JJnIuaOEc2247K9V88VQAQy1GJuQ6ylaVM7mG69QkE4");
const uint8_t kRecordSize[] = {0, 0, 0, 0, 0, 0, 0, 16};
const std::string kMessage(
"When I grow up, I want to be a watermelon!! \xf0\x9f\x8d\x89");
diff --git a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
index bed70acf54d..89e2c5351c4 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
@@ -24,7 +24,6 @@
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader/stream_resource_handler.h"
#include "content/browser/web_package/signed_exchange_utils.h"
-#include "content/browser/web_package/web_package_request_handler.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/resource_context.h"
@@ -75,6 +74,14 @@ class MimeSniffingResourceHandler::Controller : public ResourceController {
mime_handler_->ResumeInternal();
}
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ Resume();
+ }
+
void Cancel() override {
MarkAsUsed();
mime_handler_->Cancel();
diff --git a/chromium/content/browser/loader/mock_resource_loader.cc b/chromium/content/browser/loader/mock_resource_loader.cc
index 7444b0ad792..e43c857841a 100644
--- a/chromium/content/browser/loader/mock_resource_loader.cc
+++ b/chromium/content/browser/loader/mock_resource_loader.cc
@@ -10,6 +10,7 @@
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_handler.h"
#include "net/base/io_buffer.h"
+#include "net/http/http_request_headers.h"
#include "net/url_request/url_request_status.h"
#include "services/network/public/cpp/resource_response.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -24,6 +25,14 @@ class MockResourceLoader::TestResourceController : public ResourceController {
void Resume() override { mock_loader_->OnResume(); }
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ Resume();
+ }
+
void Cancel() override { CancelWithError(net::ERR_ABORTED); }
void CancelWithError(int error_code) override {
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.cc b/chromium/content/browser/loader/mojo_async_resource_handler.cc
index 08d0708f93c..4910201a2d1 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.cc
@@ -12,9 +12,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
-#include "content/browser/loader/downloaded_temp_file_impl.h"
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -40,24 +38,19 @@ constexpr size_t kMinAllocationSize = 2 * net::kMaxBytesToSniff;
constexpr size_t kMaxChunkSize = 32 * 1024;
-// Records histograms for the time spent between several events in the
-// MojoAsyncResourceHandler for a navigation.
-// - |response_started| is when the response's headers and metadata are
-// available. Loading is paused at this time.
-// - |proceed_with_response| is when loading is resumed.
-// - |first_read_completed| is when the first part of the body has been read.
-void RecordNavigationResourceHandlerMetrics(
- base::TimeTicks response_started,
- base::TimeTicks proceed_with_response,
- base::TimeTicks first_read_completed) {
- UMA_HISTOGRAM_TIMES(
- "Navigation.ResourceHandler."
- "ResponseStartedUntilProceedWithResponse",
- proceed_with_response - response_started);
- UMA_HISTOGRAM_TIMES(
- "Navigation.ResourceHandler."
- "ProceedWithResponseUntilFirstReadCompleted",
- first_read_completed - proceed_with_response);
+// Time between sending the transfer size updates to renderer. This threshold is
+// chosen as a compromise between sending too frequent updates and the limit its
+// consumers (DevTools and page load metrics) expect.
+constexpr base::TimeDelta kTransferSizeReportInterval =
+ base::TimeDelta::FromMilliseconds(500);
+
+bool ShouldReportTransferSize(
+ const ResourceRequestInfoImpl* resource_request_info) {
+ // Transfer size is reported only when report_raw_headers is set or the
+ // renderer is allowed to receive the resource response metadata (e.g. by
+ // Cross-Origin Read Blocking).
+ return resource_request_info->ShouldReportRawHeaders() ||
+ !resource_request_info->blocked_response_from_reaching_renderer();
}
} // namespace
@@ -124,6 +117,7 @@ MojoAsyncResourceHandler::MojoAsyncResourceHandler(
url_loader_client_(std::move(url_loader_client)),
weak_factory_(this) {
DCHECK(IsResourceTypeFrame(resource_type) ||
+ resource_type == RESOURCE_TYPE_SERVICE_WORKER ||
!(url_loader_options_ &
network::mojom::kURLLoadOptionSendSSLInfoWithResponse));
DCHECK(resource_type == RESOURCE_TYPE_MAIN_FRAME ||
@@ -178,37 +172,26 @@ void MojoAsyncResourceHandler::OnResponseStarted(
network::ResourceResponse* response,
std::unique_ptr<ResourceController> controller) {
DCHECK(!has_controller());
- time_response_started_ = base::TimeTicks::Now();
if (upload_progress_tracker_) {
upload_progress_tracker_->OnUploadCompleted();
upload_progress_tracker_ = nullptr;
}
- const ResourceRequestInfoImpl* info = GetRequestInfo();
response->head.encoded_data_length = request()->raw_header_size();
reported_total_received_bytes_ = response->head.encoded_data_length;
response->head.request_start = request()->creation_time();
- response->head.response_start = time_response_started_;
+ response->head.response_start = base::TimeTicks::Now();
sent_received_response_message_ = true;
- network::mojom::DownloadedTempFilePtr downloaded_file_ptr;
- if (!response->head.download_file_path.empty()) {
- downloaded_file_ptr = DownloadedTempFileImpl::Create(info->GetChildID(),
- info->GetRequestID());
- rdh_->RegisterDownloadedTempFile(info->GetChildID(), info->GetRequestID(),
- response->head.download_file_path);
- }
-
if ((url_loader_options_ &
network::mojom::kURLLoadOptionSendSSLInfoWithResponse) &&
request()->ssl_info().cert) {
response->head.ssl_info = request()->ssl_info();
}
- url_loader_client_->OnReceiveResponse(response->head,
- std::move(downloaded_file_ptr));
+ url_loader_client_->OnReceiveResponse(response->head);
net::IOBufferWithSize* metadata = GetResponseMetadata(request());
if (metadata) {
@@ -335,21 +318,18 @@ void MojoAsyncResourceHandler::OnReadCompleted(
return;
}
- const ResourceRequestInfoImpl* info = GetRequestInfo();
- if (info->ShouldReportRawHeaders()) {
+ if (ShouldReportTransferSize(GetRequestInfo()) &&
+ (time_transfer_size_next_report_.is_null() ||
+ time_transfer_size_next_report_ <= base::TimeTicks::Now())) {
auto transfer_size_diff = CalculateRecentlyReceivedBytes();
- if (transfer_size_diff > 0)
+ if (transfer_size_diff > 0) {
url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
+ time_transfer_size_next_report_ =
+ base::TimeTicks::Now() + kTransferSizeReportInterval;
+ }
}
if (response_body_consumer_handle_.is_valid()) {
- if (url_loader_options_ &
- network::mojom::kURLLoadOptionPauseOnResponseStarted) {
- base::TimeTicks time_first_read_completed = base::TimeTicks::Now();
- RecordNavigationResourceHandlerMetrics(time_response_started_,
- time_proceed_with_response_,
- time_first_read_completed);
- }
// Send the data pipe on the first OnReadCompleted call.
url_loader_client_->OnStartLoadingResponseBody(
std::move(response_body_consumer_handle_));
@@ -384,16 +364,10 @@ void MojoAsyncResourceHandler::OnReadCompleted(
controller->Resume();
}
-void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- url_loader_client_->OnDataDownloaded(bytes_downloaded,
- CalculateRecentlyReceivedBytes());
-}
-
void MojoAsyncResourceHandler::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
- DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
- "headers was not supported "
- "yet. crbug.com/845683";
if (!request()->status().is_success()) {
DVLOG(1) << "FollowRedirect for invalid request";
return;
@@ -408,14 +382,12 @@ void MojoAsyncResourceHandler::FollowRedirect(
DCHECK(!did_defer_on_writing_);
did_defer_on_redirect_ = false;
request()->LogUnblocked();
- Resume();
+ ResumeForRedirect(modified_request_headers);
}
void MojoAsyncResourceHandler::ProceedWithResponse() {
DCHECK(did_defer_on_response_started_);
- time_proceed_with_response_ = base::TimeTicks::Now();
-
request()->LogUnblocked();
Resume();
}
@@ -524,8 +496,8 @@ void MojoAsyncResourceHandler::OnResponseCompleted(
loader_status.encoded_data_length = request()->GetTotalReceivedBytes();
loader_status.encoded_body_length = request()->GetRawBodyBytes();
loader_status.decoded_body_length = total_written_bytes_;
- loader_status.blocked_cross_site_document =
- GetRequestInfo()->blocked_cross_site_document();
+ loader_status.should_report_corb_blocking =
+ GetRequestInfo()->should_report_corb_blocking();
if ((url_loader_options_ &
network::mojom::kURLLoadOptionSendSSLInfoForCertificateError) &&
@@ -534,6 +506,12 @@ void MojoAsyncResourceHandler::OnResponseCompleted(
loader_status.ssl_info = request()->ssl_info();
}
+ if (ShouldReportTransferSize(GetRequestInfo())) {
+ auto transfer_size_diff = CalculateRecentlyReceivedBytes();
+ if (transfer_size_diff > 0)
+ url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
+ }
+
url_loader_client_->OnComplete(loader_status);
controller->Resume();
}
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.h b/chromium/content/browser/loader/mojo_async_resource_handler.h
index c612b2f72e2..ad87065771e 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.h
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.h
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
#include "content/browser/loader/resource_handler.h"
#include "content/common/content_export.h"
#include "content/public/common/resource_type.h"
@@ -82,10 +81,11 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
void OnResponseCompleted(
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- void OnDataDownloaded(int bytes_downloaded) override;
// network::mojom::URLLoader implementation:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
@@ -149,13 +149,12 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
bool did_defer_on_writing_ = false;
bool did_defer_on_redirect_ = false;
bool did_defer_on_response_started_ = false;
+
+ // The time transfer size should be reported next.
+ base::TimeTicks time_transfer_size_next_report_;
int64_t reported_total_received_bytes_ = 0;
int64_t total_written_bytes_ = 0;
- // Used for UMA histograms.
- base::TimeTicks time_response_started_;
- base::TimeTicks time_proceed_with_response_;
-
// Pointer to parent's information about the read buffer. Only non-null while
// OnWillRead is deferred.
scoped_refptr<net::IOBuffer>* parent_buffer_ = nullptr;
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc b/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
index f6ca9da8125..a4170df9f58 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/logging.h"
@@ -49,7 +50,9 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_status.h"
+#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
@@ -304,9 +307,9 @@ class MojoAsyncResourceHandlerTestBase {
// Create and initialize |request_|. None of this matters, for these tests,
// just need something non-NULL.
- net::URLRequestContext* request_context =
+ request_context_ =
browser_context_->GetResourceContext()->GetRequestContext();
- request_ = request_context->CreateRequest(
+ request_ = request_context_->CreateRequest(
GURL("http://foo/"), net::DEFAULT_PRIORITY, &url_request_delegate_,
TRAFFIC_ANNOTATION_FOR_TESTS);
request_->set_upload(std::move(upload_stream));
@@ -403,6 +406,7 @@ class MojoAsyncResourceHandlerTestBase {
network::TestURLLoaderClient url_loader_client_;
std::unique_ptr<TestBrowserContext> browser_context_;
net::TestDelegate url_request_delegate_;
+ net::URLRequestContext* request_context_;
std::unique_ptr<net::URLRequest> request_;
std::unique_ptr<MojoAsyncResourceHandlerWithStubOperations> handler_;
std::unique_ptr<MockResourceLoader> mock_loader_;
@@ -1211,7 +1215,7 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, RedirectHandling) {
ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
mock_loader_->status());
- handler_->FollowRedirect(base::nullopt);
+ handler_->FollowRedirect(base::nullopt, base::nullopt);
ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
url_loader_client_.ClearHasReceivedRedirect();
@@ -1232,7 +1236,7 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, RedirectHandling) {
ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
mock_loader_->status());
- handler_->FollowRedirect(base::nullopt);
+ handler_->FollowRedirect(base::nullopt, base::nullopt);
ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
// Give the final response.
@@ -1256,7 +1260,7 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, RedirectHandling) {
// redirect, despite the fact that no redirect has been received yet.
TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
MalformedFollowRedirectRequest) {
- handler_->FollowRedirect(base::nullopt);
+ handler_->FollowRedirect(base::nullopt, base::nullopt);
EXPECT_TRUE(handler_->has_received_bad_message());
}
@@ -1459,6 +1463,66 @@ TEST_F(MojoAsyncResourceHandlerSendSSLInfoForCertificateError,
EXPECT_FALSE(url_loader_client_.completion_status().ssl_info);
};
+TEST_F(MojoAsyncResourceHandlerTest,
+ TransferSizeUpdateCalledForNonBlockedResponse) {
+ net::URLRequestJobFactoryImpl test_job_factory_;
+ auto test_job = std::make_unique<net::URLRequestTestJob>(
+ request_.get(), request_context_->network_delegate(), "response headers",
+ "response body", true);
+ auto test_job_interceptor = std::make_unique<net::TestJobInterceptor>();
+ net::TestJobInterceptor* raw_test_job_interceptor =
+ test_job_interceptor.get();
+ EXPECT_TRUE(test_job_factory_.SetProtocolHandler(
+ url::kHttpScheme, std::move(test_job_interceptor)));
+
+ request_context_->set_job_factory(&test_job_factory_);
+ raw_test_job_interceptor->set_main_intercept_job(std::move(test_job));
+ request_->Start();
+
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
+ url_request_delegate_.RunUntilComplete();
+
+ net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK);
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnResponseCompleted(status));
+ url_loader_client_.RunUntilComplete();
+ EXPECT_LT(0, url_loader_client_.body_transfer_size());
+ EXPECT_EQ(request_->GetTotalReceivedBytes(),
+ url_loader_client_.body_transfer_size());
+}
+
+TEST_F(MojoAsyncResourceHandlerTest,
+ TransferSizeUpdateNotCalledForBlockedResponse) {
+ net::URLRequestJobFactoryImpl test_job_factory_;
+ auto test_job = std::make_unique<net::URLRequestTestJob>(
+ request_.get(), request_context_->network_delegate(), "response headers",
+ "response body", true);
+ auto test_job_interceptor = std::make_unique<net::TestJobInterceptor>();
+ net::TestJobInterceptor* raw_test_job_interceptor =
+ test_job_interceptor.get();
+ EXPECT_TRUE(test_job_factory_.SetProtocolHandler(
+ url::kHttpScheme, std::move(test_job_interceptor)));
+
+ request_context_->set_job_factory(&test_job_factory_);
+ raw_test_job_interceptor->set_main_intercept_job(std::move(test_job));
+ request_->Start();
+
+ // Block the response to reach renderer.
+ ResourceRequestInfoImpl::ForRequest(request_.get())
+ ->set_blocked_response_from_reaching_renderer(true);
+
+ ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
+
+ net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK);
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnResponseCompleted(status));
+ url_request_delegate_.RunUntilComplete();
+ EXPECT_TRUE(ResourceRequestInfoImpl::ForRequest(request_.get())
+ ->blocked_response_from_reaching_renderer());
+ EXPECT_EQ(0, url_loader_client_.body_transfer_size());
+ EXPECT_LT(0, request_->GetTotalReceivedBytes());
+}
+
INSTANTIATE_TEST_CASE_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
MojoAsyncResourceHandlerWithAllocationSizeTest,
::testing::Values(8, 32 * 2014));
diff --git a/chromium/content/browser/loader/navigation_loader_util.h b/chromium/content/browser/loader/navigation_loader_util.h
deleted file mode 100644
index d5741554aff..00000000000
--- a/chromium/content/browser/loader/navigation_loader_util.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_NAVIGATION_LOADER_UTIL_H_
-#define CONTENT_BROWSER_LOADER_NAVIGATION_LOADER_UTIL_H_
-
-#include "base/optional.h"
-
-#include <string>
-
-class GURL;
-namespace net {
-class HttpResponseHeaders;
-}
-
-namespace content {
-namespace navigation_loader_util {
-
-// Returns true if the given response must be downloaded because of the headers.
-bool MustDownload(const GURL& url,
- net::HttpResponseHeaders* headers,
- const std::string& mime_type);
-
-// Determines whether given response would result in a download.
-// Note this doesn't handle the case when a plugin exists for the |mime_type|.
-bool IsDownload(const GURL& url,
- net::HttpResponseHeaders* headers,
- const std::string& mime_type);
-
-} // namespace navigation_loader_util
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_NAVIGATION_LOADER_UTIL_H_
diff --git a/chromium/content/browser/loader/navigation_url_loader.h b/chromium/content/browser/loader/navigation_url_loader.h
index e0151260cfc..e2b961d6715 100644
--- a/chromium/content/browser/loader/navigation_url_loader.h
+++ b/chromium/content/browser/loader/navigation_url_loader.h
@@ -8,8 +8,13 @@
#include <memory>
#include "base/macros.h"
+#include "base/optional.h"
#include "content/common/content_export.h"
+namespace net {
+class HttpRequestHeaders;
+}
+
namespace content {
class AppCacheNavigationHandle;
@@ -51,7 +56,10 @@ class CONTENT_EXPORT NavigationURLLoader {
// Called in response to OnRequestRedirected to continue processing the
// request.
- virtual void FollowRedirect() = 0;
+ virtual void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) = 0;
// Called in response to OnResponseStarted to process the response.
virtual void ProceedWithResponse() = 0;
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
index 3dc15070498..0fb15c7c1be 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -10,6 +10,7 @@
#include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
#include "base/task_scheduler/post_task.h"
#include "base/trace_event/trace_event.h"
#include "components/download/public/common/download_stats.h"
@@ -22,7 +23,6 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
-#include "content/browser/loader/navigation_loader_util.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -34,17 +34,18 @@
#include "content/browser/url_loader_factory_getter.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_package/signed_exchange_consts.h"
+#include "content/browser/web_package/signed_exchange_request_handler.h"
#include "content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h"
#include "content/browser/web_package/signed_exchange_utils.h"
-#include "content/browser/web_package/web_package_request_handler.h"
#include "content/browser/webui/url_data_manager_backend.h"
#include "content/browser/webui/web_ui_url_loader_factory_internal.h"
#include "content/common/navigation_subresource_loader_params.h"
-#include "content/common/service_worker/service_worker_utils.h"
+#include "content/common/net/record_load_histograms.h"
#include "content/common/throttling_url_loader.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/download_utils.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/navigation_data.h"
#include "content/public/browser/navigation_ui_data.h"
@@ -59,6 +60,7 @@
#include "content/public/common/webplugininfo.h"
#include "net/base/load_flags.h"
#include "net/http/http_content_disposition.h"
+#include "net/http/http_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_util.h"
#include "net/url_request/url_request.h"
@@ -73,6 +75,7 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
@@ -108,7 +111,7 @@ base::LazyInstance<NavigationURLLoaderImpl::BeginNavigationInterceptor>::Leaky
// of them is enabled.
bool IsLoaderInterceptionEnabled() {
return base::FeatureList::IsEnabled(network::features::kNetworkService) ||
- ServiceWorkerUtils::IsServicificationEnabled() ||
+ blink::ServiceWorkerUtils::IsServicificationEnabled() ||
signed_exchange_utils::IsSignedExchangeHandlingEnabled();
}
@@ -243,6 +246,8 @@ std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
new_request->fetch_redirect_mode = network::mojom::FetchRedirectMode::kManual;
new_request->fetch_request_context_type =
request_info->begin_params->request_context_type;
+ new_request->upgrade_if_insecure = request_info->upgrade_if_insecure;
+ new_request->throttling_profile_id = request_info->devtools_frame_token;
return new_request;
}
@@ -258,12 +263,11 @@ std::unique_ptr<NavigationRequestInfo> CreateNavigationRequestInfoForRedirect(
previous_request_info.common_params;
new_common_params.url = updated_resource_request.url;
new_common_params.referrer =
- Referrer(updated_resource_request.url,
+ Referrer(updated_resource_request.referrer,
Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
updated_resource_request.referrer_policy));
new_common_params.method = updated_resource_request.method;
new_common_params.post_data = updated_resource_request.request_body;
- // TODO(shimazu): Set correct base url and history url for a data URL.
mojom::BeginNavigationParamsPtr new_begin_params =
previous_request_info.begin_params.Clone();
@@ -279,8 +283,10 @@ std::unique_ptr<NavigationRequestInfo> CreateNavigationRequestInfoForRedirect(
previous_request_info.is_for_guests_only,
previous_request_info.report_raw_headers,
previous_request_info.is_prerendering,
+ previous_request_info.upgrade_if_insecure,
nullptr /* blob_url_loader_factory */,
- previous_request_info.devtools_navigation_token);
+ previous_request_info.devtools_navigation_token,
+ previous_request_info.devtools_frame_token);
}
// Called for requests that we don't have a URLLoaderFactory for.
@@ -308,7 +314,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
initial_interceptors,
std::unique_ptr<network::ResourceRequest> resource_request,
ResourceContext* resource_context,
- scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter,
const GURL& url,
network::mojom::URLLoaderFactoryRequest proxied_factory_request,
network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info,
@@ -317,7 +322,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
: interceptors_(std::move(initial_interceptors)),
resource_request_(std::move(resource_request)),
resource_context_(resource_context),
- default_url_loader_factory_getter_(default_url_loader_factory_getter),
url_(url),
owner_(owner),
response_loader_binding_(this),
@@ -328,6 +332,18 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
~URLLoaderRequestController() override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // If neither OnCompleted nor OnReceivedResponse has been invoked, the
+ // request was canceled before receiving a response, so log a cancellation.
+ // Results after receiving a non-error response are logged in the renderer,
+ // if the request is passed to one. If it's a download, or not passed to a
+ // renderer for some other reason, results will not be logged for the
+ // request. The net::OK check may not be necessary - the case where OK is
+ // received without receiving any headers looks broken, anyways.
+ if (!received_response_ && (!status_ || status_->error_code != net::OK)) {
+ RecordLoadHistograms(url_, resource_request_->resource_type,
+ status_ ? status_->error_code : net::ERR_ABORTED);
+ }
}
static uint32_t GetURLLoaderOptions(bool is_main_frame) {
@@ -352,15 +368,30 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
net::URLRequestContextGetter* url_request_context_getter,
storage::FileSystemContext* upload_file_system_context,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
- AppCacheNavigationHandleCore* appcache_handle_core) const {
+ AppCacheNavigationHandleCore* appcache_handle_core,
+ bool was_request_intercepted) const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ DCHECK(started_);
+
return base::BindOnce(
&URLLoaderRequestController::CreateNonNetworkServiceURLLoader,
weak_factory_.GetWeakPtr(),
base::Unretained(url_request_context_getter),
base::Unretained(upload_file_system_context),
std::make_unique<NavigationRequestInfo>(*request_info_),
- base::Unretained(service_worker_navigation_handle_core),
- base::Unretained(appcache_handle_core));
+ // If the request has already been intercepted, the request should not
+ // be intercepted again.
+ // S13nServiceWorker: Requests are intercepted by S13nServiceWorker
+ // before the default request handler when needed, so we never need to
+ // pass |service_worker_navigation_handle_core| here.
+ base::Unretained(
+ blink::ServiceWorkerUtils::IsServicificationEnabled() ||
+ was_request_intercepted
+ ? nullptr
+ : service_worker_navigation_handle_core),
+ base::Unretained(was_request_intercepted ? nullptr
+ : appcache_handle_core));
}
void CreateNonNetworkServiceURLLoader(
@@ -371,23 +402,25 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
AppCacheNavigationHandleCore* appcache_handle_core,
network::mojom::URLLoaderRequest url_loader,
network::mojom::URLLoaderClientPtr url_loader_client) {
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ DCHECK(started_);
default_loader_used_ = true;
if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
- DCHECK(!default_url_loader_factory_getter_);
+ DCHECK(!network_loader_factory_);
// It is safe to pass the callback of CreateURLLoaderThrottles with the
// unretained |this|, because the passed callback will be used by a
// SignedExchangeHandler which is indirectly owned by |this| until its
// header is verified and parsed, that's where the getter is used.
- interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
+ interceptors_.push_back(std::make_unique<SignedExchangeRequestHandler>(
url::Origin::Create(request_info->common_params.url),
request_info->common_params.url,
GetURLLoaderOptions(request_info->is_main_frame),
request_info->frame_tree_node_id,
request_info->devtools_navigation_token,
- request_info->report_raw_headers,
+ request_info->devtools_frame_token, request_info->report_raw_headers,
+ request_info->begin_params->load_flags,
base::MakeRefCounted<
SignedExchangeURLLoaderFactoryForNonNetworkService>(
resource_context_, url_request_context_getter),
@@ -415,7 +448,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
upload_file_system_context, *request_info,
std::move(navigation_ui_data_), std::move(url_loader_client),
std::move(url_loader), service_worker_navigation_handle_core,
- appcache_handle_core, options, &global_request_id_);
+ appcache_handle_core, options, global_request_id_);
}
// TODO(arthursonzogni): Detect when the ResourceDispatcherHost didn't
@@ -434,8 +467,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
AppCacheNavigationHandleCore* appcache_handle_core,
std::unique_ptr<NavigationRequestInfo> request_info,
std::unique_ptr<NavigationUIData> navigation_ui_data) {
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK(!started_);
started_ = true;
request_info_ = std::move(request_info);
@@ -443,6 +476,11 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
web_contents_getter_ = base::BindRepeating(
&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id_);
navigation_ui_data_ = std::move(navigation_ui_data);
+ // The ResourceDispatcherHostImpl can be null in unit tests.
+ ResourceDispatcherHostImpl* rph = ResourceDispatcherHostImpl::Get();
+ if (rph)
+ global_request_id_ = rph->MakeGlobalRequestID();
+
default_request_handler_factory_ = base::BindRepeating(
&URLLoaderRequestController::
CreateDefaultRequestHandlerForNonNetworkService,
@@ -453,16 +491,31 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
base::Unretained(service_worker_navigation_handle_core),
base::Unretained(appcache_handle_core));
+ // Requests to Blob scheme won't get redirected to/from other schemes
+ // or be intercepted, so we just let it go here.
+ if (request_info_->common_params.url.SchemeIsBlob() &&
+ request_info_->blob_url_loader_factory) {
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ network::SharedURLLoaderFactory::Create(
+ std::move(request_info_->blob_url_loader_factory)),
+ CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id? */,
+ network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
+ kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ return;
+ }
+
// If S13nServiceWorker is disabled, just use
// |default_request_handler_factory_| and return. The non network service
// request handling goes through ResourceDispatcherHost which has legacy
// hooks for service worker (ServiceWorkerRequestInterceptor), so no service
// worker interception is needed here.
- if (!ServiceWorkerUtils::IsServicificationEnabled() ||
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled() ||
!service_worker_navigation_handle_core) {
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- default_request_handler_factory_.Run()),
+ default_request_handler_factory_.Run(
+ false /* was_request_intercepted */)),
CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
network::mojom::kURLLoadOptionNone, resource_request_.get(),
this /* client */, kNavigationUrlLoaderTrafficAnnotation,
@@ -481,7 +534,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
if (!service_worker_interceptor) {
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- default_request_handler_factory_.Run()),
+ default_request_handler_factory_.Run(
+ false /* was_request_intercepted */)),
CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
network::mojom::kURLLoadOptionNone, resource_request_.get(),
this /* client */, kNavigationUrlLoaderTrafficAnnotation,
@@ -491,14 +545,13 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
interceptors_.push_back(std::move(service_worker_interceptor));
- // TODO(shimazu): Make sure we have a consistent global id for the
- // navigation request.
- global_request_id_ = MakeGlobalRequestID();
Restart();
}
void Start(
net::URLRequestContextGetter* url_request_context_getter,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ network_loader_factory_info,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
std::unique_ptr<NavigationRequestInfo> request_info,
@@ -506,8 +559,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
network::mojom::URLLoaderFactoryPtrInfo factory_for_webui,
int frame_tree_node_id,
std::unique_ptr<service_manager::Connector> connector) {
- DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK(!started_);
global_request_id_ = MakeGlobalRequestID();
frame_tree_node_id_ = frame_tree_node_id;
@@ -516,6 +569,10 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id);
navigation_ui_data_ = std::move(navigation_ui_data);
+ DCHECK(network_loader_factory_info);
+ network_loader_factory_ = network::SharedURLLoaderFactory::Create(
+ std::move(network_loader_factory_info));
+
if (resource_request_->request_body) {
GetBodyBlobDataHandles(resource_request_->request_body.get(),
resource_context_, &blob_handles_);
@@ -527,9 +584,9 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
std::move(factory_for_webui)),
- CreateURLLoaderThrottles(), 0 /* routing_id */, 0 /* request_id? */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
+ CreateURLLoaderThrottles(), 0 /* routing_id */,
+ global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
+ resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
return;
}
@@ -541,9 +598,9 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
network::SharedURLLoaderFactory::Create(
std::move(request_info->blob_url_loader_factory)),
- CreateURLLoaderThrottles(), 0 /* routing_id */, 0 /* request_id? */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
+ CreateURLLoaderThrottles(), 0 /* routing_id */,
+ global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
+ resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
return;
}
@@ -560,24 +617,29 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
AppCacheRequestHandler::InitializeForNavigationNetworkService(
*resource_request_, appcache_handle_core,
- default_url_loader_factory_getter_.get());
+ network_loader_factory_);
if (appcache_interceptor)
interceptors_.push_back(std::move(appcache_interceptor));
}
if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
+ // Signed Exchange is currently disabled when Network Service is enabled
+ // (https://crbug.com/849935), but still create
+ // SignedExchangeRequestHandler in order to show error message (and
+ // devtools warning) to users.
+
// It is safe to pass the callback of CreateURLLoaderThrottles with the
// unretained |this|, because the passed callback will be used by a
// SignedExchangeHandler which is indirectly owned by |this| until its
// header is verified and parsed, that's where the getter is used.
- interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
+ interceptors_.push_back(std::make_unique<SignedExchangeRequestHandler>(
url::Origin::Create(request_info->common_params.url),
request_info->common_params.url,
GetURLLoaderOptions(request_info->is_main_frame),
request_info->frame_tree_node_id,
request_info->devtools_navigation_token,
- request_info->report_raw_headers,
- default_url_loader_factory_getter_->GetNetworkFactory(),
+ request_info->devtools_frame_token, request_info->report_raw_headers,
+ request_info->begin_params->load_flags, network_loader_factory_,
base::BindRepeating(
&URLLoaderRequestController::CreateURLLoaderThrottles,
base::Unretained(this)),
@@ -624,7 +686,10 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
void MaybeStartLoader(
NavigationLoaderInterceptor* interceptor,
SingleRequestURLLoaderFactory::RequestHandler single_request_handler) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(IsLoaderInterceptionEnabled());
+ DCHECK(started_);
+
if (single_request_handler) {
// |interceptor| wants to handle the request with
// |single_request_handler|.
@@ -633,9 +698,9 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
base::MakeRefCounted<SingleRequestURLLoaderFactory>(
std::move(single_request_handler)),
- CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id? */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
+ CreateURLLoaderThrottles(), frame_tree_node_id_,
+ global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
+ resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
subresource_loader_params_ =
@@ -677,7 +742,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// so let it just follow the redirect.
if (url_loader_) {
DCHECK(!redirect_info_.new_url.is_empty());
- url_loader_->FollowRedirect();
+ url_loader_->FollowRedirect(
+ std::move(url_loader_modified_request_headers_));
return;
}
@@ -693,28 +759,36 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
DCHECK(!interceptors_.empty());
DCHECK(default_request_handler_factory_);
+ // The only way to come here is to enable ServiceWorkerServicification
+ // without NetworkService. We know that the service worker's request
+ // interceptor has already intercepted and decided not to handle the
+ // request.
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
default_loader_used_ = true;
// Update |request_info_| when following a redirect.
if (url_chain_.size() > 0) {
request_info_ = CreateNavigationRequestInfoForRedirect(
*request_info_, *resource_request_);
}
+ // When |subresource_loader_params_| has its value, the request should not
+ // be intercepted by any other interceptors since it means that a request
+ // interceptor already intercepted the request and it attached its info to
+ // the request.
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- default_request_handler_factory_.Run()),
- CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(),
- this /* client */, kNavigationUrlLoaderTrafficAnnotation,
+ default_request_handler_factory_.Run(
+ subresource_loader_params_.has_value()
+ /* was_request_intercepted */)),
+ CreateURLLoaderThrottles(), frame_tree_node_id_,
+ global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
+ resource_request_.get(), this /* client */,
+ kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
return;
}
- if (resource_request_->url.SchemeIs(url::kBlobScheme)) {
- factory =
- base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
- default_url_loader_factory_getter_->GetBlobFactory());
- } else if (!IsURLHandledByNetworkService(resource_request_->url) &&
- !resource_request_->url.SchemeIs(url::kDataScheme)) {
+ if (!IsURLHandledByNetworkService(resource_request_->url) &&
+ !resource_request_->url.SchemeIs(url::kDataScheme)) {
if (known_schemes_.find(resource_request_->url.scheme()) ==
known_schemes_.end()) {
bool handled = GetContentClient()->browser()->HandleExternalProtocol(
@@ -754,12 +828,11 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
!resource_request_->url.SchemeIs(url::kDataScheme)) {
DCHECK(proxied_factory_info_.is_valid());
// We don't worry about reconnection since it's a single navigation.
- default_url_loader_factory_getter_->CloneNetworkFactory(
- std::move(proxied_factory_request_));
+ network_loader_factory_->Clone(std::move(proxied_factory_request_));
factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
std::move(proxied_factory_info_));
} else {
- factory = default_url_loader_factory_getter_->GetNetworkFactory();
+ factory = network_loader_factory_;
}
}
url_chain_.push_back(resource_request_->url);
@@ -767,17 +840,18 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
RESOURCE_TYPE_MAIN_FRAME);
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
factory, CreateURLLoaderThrottles(), frame_tree_node_id_,
- 0 /* request_id? */, options, resource_request_.get(), this,
+ global_request_id_.request_id, options, resource_request_.get(), this,
kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
}
- void FollowRedirect() {
+ void FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!redirect_info_.new_url.is_empty());
if (!IsLoaderInterceptionEnabled()) {
- url_loader_->FollowRedirect();
+ url_loader_->FollowRedirect(modified_request_headers);
return;
}
@@ -794,7 +868,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
bool should_clear_upload = false;
net::RedirectUtil::UpdateHttpRequest(
resource_request_->url, resource_request_->method, redirect_info_,
- &resource_request_->headers, &should_clear_upload);
+ modified_request_headers, &resource_request_->headers,
+ &should_clear_upload);
if (should_clear_upload) {
// The request body is no longer applicable.
resource_request_->request_body = nullptr;
@@ -808,6 +883,10 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
resource_request_->referrer_policy = redirect_info_.new_referrer_policy;
url_chain_.push_back(redirect_info_.new_url);
+ // Need to cache modified headers for |url_loader_| since it doesn't use
+ // |resource_request_| during redirect.
+ url_loader_modified_request_headers_ = modified_request_headers;
+
Restart();
}
@@ -817,9 +896,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
private:
// network::mojom::URLLoaderClient implementation:
- void OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override {
+ void OnReceiveResponse(const network::ResourceResponseHead& head) override {
received_response_ = true;
// If the default loader (network) was used to handle the URL load request
@@ -847,15 +924,14 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
bool is_stream;
std::unique_ptr<NavigationData> cloned_navigation_data;
if (IsLoaderInterceptionEnabled()) {
- bool must_download = navigation_loader_util::MustDownload(
+ bool must_download = download_utils::MustDownload(
url_, head.headers.get(), head.mime_type);
bool known_mime_type = blink::IsSupportedMimeType(head.mime_type);
#if BUILDFLAG(ENABLE_PLUGINS)
if (!response_intercepted && !must_download && !known_mime_type) {
CheckPluginAndContinueOnReceiveResponse(
- head, std::move(downloaded_file),
- std::move(url_loader_client_endpoints),
+ head, std::move(url_loader_client_endpoints),
std::vector<WebPluginInfo>());
return;
}
@@ -900,14 +976,16 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
subresource_loader_params_ = SubresourceLoaderParams();
subresource_loader_params_->controller_service_worker_info =
mojom::ControllerServiceWorkerInfo::New();
- base::WeakPtr<ServiceWorkerHandle> sw_handle =
- sw_provider_host->GetOrCreateServiceWorkerHandle(
+ subresource_loader_params_->controller_service_worker_info->mode =
+ sw_provider_host->GetControllerMode();
+ base::WeakPtr<ServiceWorkerObjectHost> sw_object_host =
+ sw_provider_host->GetOrCreateServiceWorkerObjectHost(
sw_provider_host->controller());
- if (sw_handle) {
- subresource_loader_params_->controller_service_worker_handle =
- sw_handle;
+ if (sw_object_host) {
+ subresource_loader_params_->controller_service_worker_object_host =
+ sw_object_host;
subresource_loader_params_->controller_service_worker_info
- ->object_info = sw_handle->CreateIncompleteObjectInfo();
+ ->object_info = sw_object_host->CreateIncompleteObjectInfo();
}
}
} else {
@@ -915,8 +993,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
}
}
- CallOnReceivedResponse(head, std::move(downloaded_file),
- std::move(url_loader_client_endpoints),
+ CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
std::move(cloned_navigation_data), is_download,
is_stream);
}
@@ -924,7 +1001,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
#if BUILDFLAG(ENABLE_PLUGINS)
void CheckPluginAndContinueOnReceiveResponse(
const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
const std::vector<WebPluginInfo>& plugins) {
bool stale;
@@ -943,7 +1019,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// Refresh the plugins asynchronously.
PluginService::GetInstance()->GetPlugins(base::BindOnce(
&URLLoaderRequestController::CheckPluginAndContinueOnReceiveResponse,
- weak_factory_.GetWeakPtr(), head, std::move(downloaded_file),
+ weak_factory_.GetWeakPtr(), head,
std::move(url_loader_client_endpoints)));
return;
}
@@ -952,15 +1028,13 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
!has_plugin &&
(!head.headers || head.headers->response_code() / 100 == 2);
- CallOnReceivedResponse(head, std::move(downloaded_file),
- std::move(url_loader_client_endpoints), nullptr,
- is_download, false /* is_stream */);
+ CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
+ nullptr, is_download, false /* is_stream */);
}
#endif
void CallOnReceivedResponse(
const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
std::unique_ptr<NavigationData> cloned_navigation_data,
bool is_download,
@@ -981,7 +1055,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
response->DeepCopy(),
std::move(url_loader_client_endpoints),
std::move(cloned_navigation_data), global_request_id_,
- is_download, is_stream, std::move(downloaded_file)));
+ is_download, is_stream));
}
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
@@ -1013,7 +1087,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
redirect_info, response->DeepCopy()));
}
- void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {}
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override {}
@@ -1117,10 +1190,14 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
ResourceContext* resource_context_;
base::Callback<WebContents*()> web_contents_getter_;
std::unique_ptr<NavigationUIData> navigation_ui_data_;
- scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_;
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
std::unique_ptr<ThrottlingURLLoader> url_loader_;
+ // Caches the modified request headers provided by clients during redirect,
+ // will be consumed by next |url_loader_->FollowRedirect()|.
+ base::Optional<net::HttpRequestHeaders> url_loader_modified_request_headers_;
+
BlobHandles blob_handles_;
std::vector<GURL> url_chain_;
@@ -1162,7 +1239,11 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// captures all of parameters to create a
// SingleRequestURLLoaderFactory::RequestHandler. Used only when
// NetworkService is disabled but IsLoaderInterceptionEnabled() is true.
- base::RepeatingCallback<SingleRequestURLLoaderFactory::RequestHandler()>
+ // Set |was_request_intercepted| to true if the request was intercepted by an
+ // interceptor and the request is falling back to the network. In that case,
+ // any interceptors won't intercept the request.
+ base::RepeatingCallback<SingleRequestURLLoaderFactory::RequestHandler(
+ bool /* was_request_intercepted */)>
default_request_handler_factory_;
// The completion status if it has been received. This is needed to handle
@@ -1223,6 +1304,7 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
std::unique_ptr<network::ResourceRequest> new_request = CreateResourceRequest(
request_info.get(), frame_tree_node_id, allow_download_);
+ new_request->transition_type = request_info->common_params.transition;
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
DCHECK(!request_controller_);
@@ -1230,7 +1312,6 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
/* initial_interceptors = */
std::vector<std::unique_ptr<NavigationLoaderInterceptor>>(),
std::move(new_request), resource_context,
- /* default_url_factory_getter = */ nullptr,
request_info->common_params.url,
/* proxied_url_loader_factory_request */ nullptr,
/* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
@@ -1255,7 +1336,7 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
network::mojom::URLLoaderFactoryPtrInfo factory_for_webui;
const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
std::string scheme = new_request->url.scheme();
- if (std::find(schemes.begin(), schemes.end(), scheme) != schemes.end()) {
+ if (base::ContainsValue(schemes, scheme)) {
factory_for_webui = CreateWebUIURLLoaderBinding(
frame_tree_node->current_frame_host(), scheme)
.PassInterface();
@@ -1278,8 +1359,8 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
network::mojom::URLLoaderFactoryPtrInfo factory_info;
auto factory_request = mojo::MakeRequest(&factory_info);
bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
- frame_tree_node->current_frame_host(), true /* is_navigation */,
- &factory_request);
+ partition->browser_context(), frame_tree_node->current_frame_host(),
+ true /* is_navigation */, &factory_request);
if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
frame_tree_node->current_frame_host(), true, false,
&factory_request)) {
@@ -1311,15 +1392,16 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
DCHECK(!request_controller_);
request_controller_ = std::make_unique<URLLoaderRequestController>(
std::move(initial_interceptors), std::move(new_request), resource_context,
- partition->url_loader_factory_getter(), request_info->common_params.url,
- std::move(proxied_factory_request), std::move(proxied_factory_info),
- std::move(known_schemes), weak_factory_.GetWeakPtr());
+ request_info->common_params.url, std::move(proxied_factory_request),
+ std::move(proxied_factory_info), std::move(known_schemes),
+ weak_factory_.GetWeakPtr());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&URLLoaderRequestController::Start,
base::Unretained(request_controller_.get()),
base::RetainedRef(storage_partition->GetURLRequestContext()),
+ partition->url_loader_factory_getter()->GetNetworkFactoryInfo(),
service_worker_navigation_handle_core, appcache_handle_core,
std::move(request_info), std::move(navigation_ui_data),
std::move(factory_for_webui), frame_tree_node_id,
@@ -1331,11 +1413,15 @@ NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
request_controller_.release());
}
-void NavigationURLLoaderImpl::FollowRedirect() {
+void NavigationURLLoaderImpl::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&URLLoaderRequestController::FollowRedirect,
- base::Unretained(request_controller_.get())));
+ base::Unretained(request_controller_.get()),
+ modified_request_headers));
}
void NavigationURLLoaderImpl::ProceedWithResponse() {}
@@ -1346,8 +1432,7 @@ void NavigationURLLoaderImpl::OnReceiveResponse(
std::unique_ptr<NavigationData> navigation_data,
const GlobalRequestID& global_request_id,
bool is_download,
- bool is_stream,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
+ bool is_stream) {
TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
"&NavigationURLLoaderImpl", this, "success", true);
@@ -1403,9 +1488,10 @@ void NavigationURLLoaderImpl::BindNonNetworkURLLoaderFactoryRequest(
}
FrameTreeNode* frame_tree_node =
FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+ auto* frame = frame_tree_node->current_frame_host();
GetContentClient()->browser()->WillCreateURLLoaderFactory(
- frame_tree_node->current_frame_host(), true /* is_navigation */,
- &factory);
+ frame->GetSiteInstance()->GetBrowserContext(), frame,
+ true /* is_navigation */, &factory);
it->second->Clone(std::move(factory));
}
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.h b/chromium/content/browser/loader/navigation_url_loader_impl.h
index 67c1d5bb8f7..ac5e384a04d 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.h
@@ -44,7 +44,10 @@ class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
~NavigationURLLoaderImpl() override;
// NavigationURLLoader implementation:
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void OnReceiveResponse(
@@ -53,8 +56,7 @@ class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
std::unique_ptr<NavigationData> navigation_data,
const GlobalRequestID& global_request_id,
bool is_download,
- bool is_stream,
- network::mojom::DownloadedTempFilePtr downloaded_file);
+ bool is_stream);
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
scoped_refptr<network::ResourceResponse> response);
void OnComplete(const network::URLLoaderCompletionStatus& status);
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
index 4cafe900bb2..538274d42a9 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -104,7 +104,7 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
}
private:
- void DeleteURLLoader(network::URLLoader* url_loader) {
+ void DeleteURLLoader(network::mojom::URLLoader* url_loader) {
DCHECK_EQ(url_loader_.get(), url_loader);
url_loader_.reset();
}
@@ -154,7 +154,8 @@ class NavigationURLLoaderImplTest : public testing::Test {
const std::string& method,
NavigationURLLoaderDelegate* delegate,
bool allow_download = false,
- bool is_main_frame = true) {
+ bool is_main_frame = true,
+ bool upgrade_if_insecure = false) {
mojom::BeginNavigationParamsPtr begin_params =
mojom::BeginNavigationParams::New(
headers, net::LOAD_NORMAL, false /* skip_service_worker */,
@@ -176,8 +177,10 @@ class NavigationURLLoaderImplTest : public testing::Test {
false /* parent_is_main_frame */, false /* are_ancestors_secure */,
-1 /* frame_tree_node_id */, false /* is_for_guests_only */,
false /* report_raw_headers */, false /* is_prerenering */,
+ upgrade_if_insecure /* upgrade_if_insecure */,
nullptr /* blob_url_loader_factory */,
- base::UnguessableToken::Create() /* devtools_navigation_token */));
+ base::UnguessableToken::Create() /* devtools_navigation_token */,
+ base::UnguessableToken::Create() /* devtools_frame_token */));
std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors;
most_recent_resource_request_ = base::nullopt;
interceptors.push_back(std::make_unique<TestNavigationLoaderInterceptor>(
@@ -210,7 +213,7 @@ class NavigationURLLoaderImplTest : public testing::Test {
redirect_url.GetOrigin().spec().c_str()),
request_method, &delegate);
delegate.WaitForRequestRedirected();
- loader->FollowRedirect();
+ loader->FollowRedirect(base::nullopt, base::nullopt);
EXPECT_EQ(expected_redirect_method, delegate.redirect_info().new_method);
@@ -251,12 +254,32 @@ class NavigationURLLoaderImplTest : public testing::Test {
url.GetOrigin().spec().c_str()),
"GET", &delegate, false /* allow_download */, is_main_frame);
delegate.WaitForRequestRedirected();
- loader->FollowRedirect();
+ loader->FollowRedirect(base::nullopt, base::nullopt);
delegate.WaitForResponseStarted();
return most_recent_resource_request_.value().priority;
}
+ net::RedirectInfo NavigateAndReturnRedirectInfo(const GURL& url,
+ bool upgrade_if_insecure,
+ bool expect_request_fail) {
+ TestNavigationURLLoaderDelegate delegate;
+ std::unique_ptr<NavigationURLLoader> loader = CreateTestLoader(
+ url,
+ base::StringPrintf("%s: %s", net::HttpRequestHeaders::kOrigin,
+ url.GetOrigin().spec().c_str()),
+ "GET", &delegate, false /* allow_download */, true /*is_main_frame*/,
+ upgrade_if_insecure);
+ delegate.WaitForRequestRedirected();
+ loader->FollowRedirect(base::nullopt, base::nullopt);
+ if (expect_request_fail) {
+ delegate.WaitForRequestFailed();
+ } else {
+ delegate.WaitForResponseStarted();
+ }
+ return delegate.redirect_info();
+ }
+
protected:
base::test::ScopedFeatureList feature_list_;
TestBrowserThreadBundle thread_bundle_;
@@ -345,4 +368,68 @@ TEST_F(NavigationURLLoaderImplTest, Redirect308Tests) {
true);
}
+TEST_F(NavigationURLLoaderImplTest, RedirectModifiedHeaders) {
+ ASSERT_TRUE(http_test_server_.Start());
+
+ const GURL redirect_url = http_test_server_.GetURL("/redirect301-to-echo");
+
+ TestNavigationURLLoaderDelegate delegate;
+ std::unique_ptr<NavigationURLLoader> loader = CreateTestLoader(
+ redirect_url, "Header1: Value1\r\nHeader2: Value2", "GET", &delegate);
+ delegate.WaitForRequestRedirected();
+
+ ASSERT_TRUE(most_recent_resource_request_);
+
+ // Initial request should only have initial headers.
+ std::string header1, header2;
+ EXPECT_TRUE(
+ most_recent_resource_request_->headers.GetHeader("Header1", &header1));
+ EXPECT_EQ("Value1", header1);
+ EXPECT_TRUE(
+ most_recent_resource_request_->headers.GetHeader("Header2", &header2));
+ EXPECT_EQ("Value2", header2);
+ EXPECT_FALSE(most_recent_resource_request_->headers.HasHeader("Header3"));
+
+ // Overwrite Header2 and add Header3.
+ net::HttpRequestHeaders redirect_headers;
+ redirect_headers.SetHeader("Header2", "");
+ redirect_headers.SetHeader("Header3", "Value3");
+ loader->FollowRedirect(base::nullopt, redirect_headers);
+ delegate.WaitForResponseStarted();
+
+ // Redirected request should also have modified headers.
+ EXPECT_TRUE(
+ most_recent_resource_request_->headers.GetHeader("Header1", &header1));
+ EXPECT_EQ("Value1", header1);
+ EXPECT_TRUE(
+ most_recent_resource_request_->headers.GetHeader("Header2", &header2));
+ EXPECT_EQ("", header2);
+ std::string header3;
+ EXPECT_TRUE(
+ most_recent_resource_request_->headers.GetHeader("Header3", &header3));
+ EXPECT_EQ("Value3", header3);
+}
+
+// Tests that the Upgrade If Insecure flag is obeyed.
+TEST_F(NavigationURLLoaderImplTest, UpgradeIfInsecureTest) {
+ ASSERT_TRUE(http_test_server_.Start());
+ const GURL url = http_test_server_.GetURL("/redirect301-to-http");
+ GURL expected_url = GURL("http://test.test/test");
+ // We expect the request to fail since there is no server listening at
+ // test.test, but for the purpose of this test we only need to validate the
+ // redirect URL was not changed.
+ net::RedirectInfo redirect_info = NavigateAndReturnRedirectInfo(
+ url, false /* upgrade_if_insecure */, true /* expect_request_fail */);
+ EXPECT_FALSE(redirect_info.insecure_scheme_was_upgraded);
+ EXPECT_EQ(expected_url, redirect_info.new_url);
+ GURL::Replacements replacements;
+ replacements.SetSchemeStr("https");
+ expected_url = expected_url.ReplaceComponents(replacements);
+ redirect_info = NavigateAndReturnRedirectInfo(
+ url, true /* upgrade_if_insecure */, true /* expect_request_fail */);
+ // Same as above, but validating the URL is upgraded to https.
+ EXPECT_TRUE(redirect_info.insecure_scheme_was_upgraded);
+ EXPECT_EQ(expected_url, redirect_info.new_url);
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
index ea806d87222..75f70ba50a4 100644
--- a/chromium/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
@@ -95,7 +95,9 @@ class NavigationURLLoaderTest : public testing::Test {
std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo(common_params, std::move(begin_params), url,
true, false, false, -1, false, false, false,
- nullptr, base::UnguessableToken::Create()));
+ false, nullptr,
+ base::UnguessableToken::Create(),
+ base::UnguessableToken::Create()));
return NavigationURLLoader::Create(
browser_context_->GetResourceContext(),
BrowserContext::GetDefaultStoragePartition(browser_context_.get()),
@@ -226,7 +228,7 @@ TEST_F(NavigationURLLoaderTest, CancelResponseRace) {
// In the same event loop iteration, follow the redirect (allowing the
// response to go through) and destroy the loader.
- loader->FollowRedirect();
+ loader->FollowRedirect(base::nullopt, base::nullopt);
loader.reset();
// Verify the URLRequestTestJob no longer has anything paused and that no
diff --git a/chromium/content/browser/loader/null_resource_controller.cc b/chromium/content/browser/loader/null_resource_controller.cc
index da79bb5843e..8ac719d3a6a 100644
--- a/chromium/content/browser/loader/null_resource_controller.cc
+++ b/chromium/content/browser/loader/null_resource_controller.cc
@@ -5,6 +5,7 @@
#include "content/browser/loader/null_resource_controller.h"
#include "base/logging.h"
+#include "net/http/http_request_headers.h"
namespace content {
@@ -27,4 +28,12 @@ void NullResourceController::Resume() {
*was_resumed_ = true;
}
+void NullResourceController::ResumeForRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
+ DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
+ "headers was not supported "
+ "yet. crbug.com/845683";
+ Resume();
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/null_resource_controller.h b/chromium/content/browser/loader/null_resource_controller.h
index 8dd10f7102a..66c9e039467 100644
--- a/chromium/content/browser/loader/null_resource_controller.h
+++ b/chromium/content/browser/loader/null_resource_controller.h
@@ -23,6 +23,8 @@ class NullResourceController : public ResourceController {
void Cancel() override;
void CancelWithError(int error_code) override;
void Resume() override;
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
private:
bool* was_resumed_;
diff --git a/chromium/content/browser/loader/prefetch_browsertest.cc b/chromium/content/browser/loader/prefetch_browsertest.cc
index da0ea6f9f64..fb0726ef37c 100644
--- a/chromium/content/browser/loader/prefetch_browsertest.cc
+++ b/chromium/content/browser/loader/prefetch_browsertest.cc
@@ -14,7 +14,7 @@
#include "content/browser/loader/prefetch_url_loader_service.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_package/mock_signed_exchange_handler.h"
-#include "content/browser/web_package/web_package_loader.h"
+#include "content/browser/web_package/signed_exchange_loader.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
@@ -40,10 +40,10 @@ struct PrefetchBrowserTestParam {
struct ScopedSignedExchangeHandlerFactory {
explicit ScopedSignedExchangeHandlerFactory(
SignedExchangeHandlerFactory* factory) {
- WebPackageLoader::SetSignedExchangeHandlerFactoryForTest(factory);
+ SignedExchangeLoader::SetSignedExchangeHandlerFactoryForTest(factory);
}
~ScopedSignedExchangeHandlerFactory() {
- WebPackageLoader::SetSignedExchangeHandlerFactoryForTest(nullptr);
+ SignedExchangeLoader::SetSignedExchangeHandlerFactoryForTest(nullptr);
}
};
@@ -333,31 +333,31 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
int target_fetch_count = 0;
int preload_fetch_count = 0;
const char* prefetch_url = "/prefetch.html";
- const char* target_htxg = "/target.htxg";
+ const char* target_sxg = "/target.sxg";
const char* target_url = "/target.html";
- const char* preload_url_in_htxg = "/preload.js";
+ const char* preload_url_in_sxg = "/preload.js";
RegisterResponse(
prefetch_url,
ResponseEntry(base::StringPrintf(
- "<body><link rel='prefetch' href='%s'></body>", target_htxg)));
+ "<body><link rel='prefetch' href='%s'></body>", target_sxg)));
RegisterResponse(
- target_htxg,
+ target_sxg,
// We mock the SignedExchangeHandler, so just return a HTML content
// as "application/signed-exchange;v=b0".
- ResponseEntry("<head><title>Prefetch Target (HTXG)</title></head>",
+ ResponseEntry("<head><title>Prefetch Target (SXG)</title></head>",
"application/signed-exchange;v=b0"));
- RegisterResponse(preload_url_in_htxg,
+ RegisterResponse(preload_url_in_sxg,
ResponseEntry("function foo() {}", "text/javascript"));
base::RunLoop preload_waiter;
base::RunLoop prefetch_waiter;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- target_htxg, &target_fetch_count, prefetch_waiter.QuitClosure()));
+ target_sxg, &target_fetch_count, prefetch_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- preload_url_in_htxg, &preload_fetch_count, preload_waiter.QuitClosure()));
+ preload_url_in_sxg, &preload_fetch_count, preload_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -367,7 +367,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
net::OK, GURL(target_url), "text/html",
{base::StringPrintf(
"Link: <%s>;rel=\"preload\";as=\"script\"",
- embedded_test_server()->GetURL(preload_url_in_htxg).spec().c_str())});
+ embedded_test_server()->GetURL(preload_url_in_sxg).spec().c_str())});
ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
// Loading a page that prefetches the target URL would increment both
@@ -377,11 +377,15 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
EXPECT_EQ(1, target_fetch_count);
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(1));
- // Test after this point requires SignedHTTPExchange support.
- if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
+ // Test after this point requires SignedHTTPExchange support, which is now
+ // disabled when Network Service is enabled.
+ // TODO(https://crbug.com/849935): Remove the second condition once we
+ // re-enable Signed Exchange with Network Service.
+ if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchange) ||
+ base::FeatureList::IsEnabled(network::features::kNetworkService))
return;
- // If the header in the .htxg file is correctly extracted, we should
+ // If the header in the .sxg file is correctly extracted, we should
// be able to also see the preload.
preload_waiter.Run();
EXPECT_EQ(1, preload_fetch_count);
diff --git a/chromium/content/browser/loader/prefetch_url_loader.cc b/chromium/content/browser/loader/prefetch_url_loader.cc
index c0d59319dd0..bbfd85fcc3c 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader.cc
@@ -5,8 +5,8 @@
#include "content/browser/loader/prefetch_url_loader.h"
#include "base/feature_list.h"
+#include "content/browser/web_package/signed_exchange_prefetch_handler.h"
#include "content/browser/web_package/signed_exchange_utils.h"
-#include "content/browser/web_package/web_package_prefetch_handler.h"
#include "content/public/common/content_features.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/features.h"
@@ -29,6 +29,8 @@ PrefetchURLLoader::PrefetchURLLoader(
: frame_tree_node_id_getter_(frame_tree_node_id_getter),
url_(resource_request.url),
report_raw_headers_(resource_request.report_raw_headers),
+ load_flags_(resource_request.load_flags),
+ throttling_profile_id_(resource_request.throttling_profile_id),
network_loader_factory_(std::move(network_loader_factory)),
client_binding_(this),
forwarding_client_(std::move(client)),
@@ -52,18 +54,20 @@ PrefetchURLLoader::PrefetchURLLoader(
PrefetchURLLoader::~PrefetchURLLoader() = default;
void PrefetchURLLoader::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
"headers was not supported "
"yet. crbug.com/845683";
- if (web_package_prefetch_handler_) {
+ if (signed_exchange_prefetch_handler_) {
// Rebind |client_binding_| and |loader_|.
- client_binding_.Bind(web_package_prefetch_handler_->FollowRedirect(
+ client_binding_.Bind(signed_exchange_prefetch_handler_->FollowRedirect(
mojo::MakeRequest(&loader_)));
return;
}
- loader_->FollowRedirect(base::nullopt);
+ loader_->FollowRedirect(base::nullopt, base::nullopt);
}
void PrefetchURLLoader::ProceedWithResponse() {
@@ -84,21 +88,22 @@ void PrefetchURLLoader::ResumeReadingBodyFromNet() {
}
void PrefetchURLLoader::OnReceiveResponse(
- const network::ResourceResponseHead& response,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
+ const network::ResourceResponseHead& response) {
if (signed_exchange_utils::ShouldHandleAsSignedHTTPExchange(url_, response)) {
- DCHECK(!web_package_prefetch_handler_);
+ DCHECK(!signed_exchange_prefetch_handler_);
// Note that after this point this doesn't directly get upcalls from the
// network. (Until |this| calls the handler's FollowRedirect.)
- web_package_prefetch_handler_ = std::make_unique<WebPackagePrefetchHandler>(
- frame_tree_node_id_getter_, report_raw_headers_, response,
- std::move(loader_), client_binding_.Unbind(), network_loader_factory_,
- request_initiator_, url_, url_loader_throttles_getter_,
- resource_context_, request_context_getter_, this);
+ signed_exchange_prefetch_handler_ =
+ std::make_unique<SignedExchangePrefetchHandler>(
+ frame_tree_node_id_getter_, report_raw_headers_, load_flags_,
+ throttling_profile_id_, response, std::move(loader_),
+ client_binding_.Unbind(), network_loader_factory_,
+ request_initiator_, url_, url_loader_throttles_getter_,
+ resource_context_, request_context_getter_, this);
return;
}
- forwarding_client_->OnReceiveResponse(response, std::move(downloaded_file));
+ forwarding_client_->OnReceiveResponse(response);
}
void PrefetchURLLoader::OnReceiveRedirect(
@@ -107,11 +112,6 @@ void PrefetchURLLoader::OnReceiveRedirect(
forwarding_client_->OnReceiveRedirect(redirect_info, head);
}
-void PrefetchURLLoader::OnDataDownloaded(int64_t data_length,
- int64_t encoded_length) {
- forwarding_client_->OnDataDownloaded(data_length, encoded_length);
-}
-
void PrefetchURLLoader::OnUploadProgress(int64_t current_position,
int64_t total_size,
base::OnceCallback<void()> callback) {
diff --git a/chromium/content/browser/loader/prefetch_url_loader.h b/chromium/content/browser/loader/prefetch_url_loader.h
index 3a63bb0c4cc..ef4ff33677d 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.h
+++ b/chromium/content/browser/loader/prefetch_url_loader.h
@@ -9,6 +9,8 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/optional.h"
+#include "base/unguessable_token.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
@@ -28,7 +30,7 @@ namespace content {
class ResourceContext;
class URLLoaderThrottle;
-class WebPackagePrefetchHandler;
+class SignedExchangePrefetchHandler;
// PrefetchURLLoader which basically just keeps draining the data.
class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
@@ -60,7 +62,9 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
private:
// network::mojom::URLLoader overrides:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
@@ -69,12 +73,9 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
void ResumeReadingBodyFromNet() override;
// network::mojom::URLLoaderClient overrides:
- void OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override;
+ void OnReceiveResponse(const network::ResourceResponseHead& head) override;
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) override;
- void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
base::OnceCallback<void()> callback) override;
@@ -94,6 +95,8 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
const base::RepeatingCallback<int(void)> frame_tree_node_id_getter_;
const GURL url_;
const bool report_raw_headers_;
+ const int load_flags_;
+ const base::Optional<base::UnguessableToken> throttling_profile_id_;
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
@@ -114,7 +117,8 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
std::unique_ptr<mojo::DataPipeDrainer> pipe_drainer_;
- std::unique_ptr<WebPackagePrefetchHandler> web_package_prefetch_handler_;
+ std::unique_ptr<SignedExchangePrefetchHandler>
+ signed_exchange_prefetch_handler_;
DISALLOW_COPY_AND_ASSIGN(PrefetchURLLoader);
};
diff --git a/chromium/content/browser/loader/prefetch_url_loader_service.cc b/chromium/content/browser/loader/prefetch_url_loader_service.cc
index a8c1638bf9e..b7baa69c5cf 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.cc
@@ -20,9 +20,22 @@
namespace content {
-PrefetchURLLoaderService::PrefetchURLLoaderService(
- scoped_refptr<URLLoaderFactoryGetter> factory_getter)
- : loader_factory_getter_(std::move(factory_getter)) {}
+struct PrefetchURLLoaderService::BindContext {
+ BindContext(int frame_tree_node_id,
+ scoped_refptr<URLLoaderFactoryBundle> factory)
+ : frame_tree_node_id(frame_tree_node_id), factory(factory) {}
+
+ explicit BindContext(const std::unique_ptr<BindContext>& other)
+ : frame_tree_node_id(other->frame_tree_node_id),
+ factory(other->factory) {}
+
+ ~BindContext() = default;
+
+ const int frame_tree_node_id;
+ scoped_refptr<URLLoaderFactoryBundle> factory;
+};
+
+PrefetchURLLoaderService::PrefetchURLLoaderService() = default;
void PrefetchURLLoaderService::InitializeResourceContext(
ResourceContext* resource_context,
@@ -34,17 +47,16 @@ void PrefetchURLLoaderService::InitializeResourceContext(
request_context_getter_ = request_context_getter;
}
-void PrefetchURLLoaderService::ConnectToService(
+void PrefetchURLLoaderService::GetFactory(
+ network::mojom::URLLoaderFactoryRequest request,
int frame_tree_node_id,
- blink::mojom::PrefetchURLLoaderServiceRequest request) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PrefetchURLLoaderService::ConnectToService, this,
- frame_tree_node_id, std::move(request)));
- return;
- }
- service_bindings_.AddBinding(this, std::move(request), frame_tree_node_id);
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factories) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ auto factory_bundle =
+ base::MakeRefCounted<URLLoaderFactoryBundle>(std::move(factories));
+ loader_factory_bindings_.AddBinding(
+ this, std::move(request),
+ std::make_unique<BindContext>(frame_tree_node_id, factory_bundle));
}
void PrefetchURLLoaderService::CreateLoaderAndStart(
@@ -82,13 +94,6 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
PrefetchURLLoaderService::~PrefetchURLLoaderService() = default;
-void PrefetchURLLoaderService::GetFactory(
- network::mojom::URLLoaderFactoryRequest request) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- loader_factory_bindings_.AddBinding(this, std::move(request),
- service_bindings_.dispatch_context());
-}
-
void PrefetchURLLoaderService::CreateLoaderAndStart(
network::mojom::URLLoaderRequest request,
int32_t routing_id,
@@ -99,11 +104,11 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
- int frame_tree_node_id = loader_factory_bindings_.dispatch_context();
+ const auto& dispatch_context = *loader_factory_bindings_.dispatch_context();
+ int frame_tree_node_id = dispatch_context.frame_tree_node_id;
CreateLoaderAndStart(
std::move(request), routing_id, request_id, options, resource_request,
- std::move(client), traffic_annotation,
- loader_factory_getter_->GetNetworkFactory(),
+ std::move(client), traffic_annotation, dispatch_context.factory,
base::BindRepeating([](int id) { return id; }, frame_tree_node_id));
}
@@ -111,7 +116,9 @@ void PrefetchURLLoaderService::Clone(
network::mojom::URLLoaderFactoryRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
loader_factory_bindings_.AddBinding(
- this, std::move(request), loader_factory_bindings_.dispatch_context());
+ this, std::move(request),
+ std::make_unique<BindContext>(
+ loader_factory_bindings_.dispatch_context()));
}
std::vector<std::unique_ptr<content::URLLoaderThrottle>>
diff --git a/chromium/content/browser/loader/prefetch_url_loader_service.h b/chromium/content/browser/loader/prefetch_url_loader_service.h
index 6573ee69d52..69c241394f2 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.h
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.h
@@ -9,10 +9,10 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+#include "content/common/url_loader_factory_bundle.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/strong_binding_set.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "third_party/blink/public/mojom/loader/prefetch_url_loader_service.mojom.h"
namespace net {
class URLRequestContextGetter;
@@ -20,6 +20,7 @@ class URLRequestContextGetter;
namespace network {
class SharedURLLoaderFactory;
+class URLLoaderFactoryBundleInfo;
}
namespace content {
@@ -31,13 +32,9 @@ class URLLoaderThrottle;
class CONTENT_EXPORT PrefetchURLLoaderService final
: public base::RefCountedThreadSafe<PrefetchURLLoaderService,
BrowserThread::DeleteOnIOThread>,
- public network::mojom::URLLoaderFactory,
- public blink::mojom::PrefetchURLLoaderService {
+ public network::mojom::URLLoaderFactory {
public:
- // |factory_getter| could be null in non-NetworkService case.
- // Created on the UI thread.
- PrefetchURLLoaderService(
- scoped_refptr<URLLoaderFactoryGetter> network_loader_factory);
+ PrefetchURLLoaderService();
// Must be called on the IO thread. The given |resource_context| will
// be valid as far as request_context_getter returns non-null context.
@@ -45,8 +42,9 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
ResourceContext* resource_context,
scoped_refptr<net::URLRequestContextGetter> request_context_getter);
- void ConnectToService(int frame_tree_node_id,
- blink::mojom::PrefetchURLLoaderServiceRequest request);
+ void GetFactory(network::mojom::URLLoaderFactoryRequest request,
+ int frame_tree_node_id,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_info);
// Used only when NetworkService is not enabled (or indirectly via the
// other CreateLoaderAndStart when NetworkService is enabled).
@@ -75,10 +73,9 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
private:
friend class base::DeleteHelper<content::PrefetchURLLoaderService>;
friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
- ~PrefetchURLLoaderService() override;
+ struct BindContext;
- // blink::mojom::PrefetchURLLoaderService:
- void GetFactory(network::mojom::URLLoaderFactoryRequest request) override;
+ ~PrefetchURLLoaderService() override;
// network::mojom::URLLoaderFactory:
void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
@@ -97,16 +94,12 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
const network::ResourceRequest& request,
base::RepeatingCallback<int(void)> frame_tree_node_id_getter);
- mojo::BindingSet<blink::mojom::PrefetchURLLoaderService,
- int /* frame_tree_node_id */>
- service_bindings_;
-
scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
ResourceContext* resource_context_ = nullptr;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
mojo::BindingSet<network::mojom::URLLoaderFactory,
- int /* frame_tree_node_id */>
+ std::unique_ptr<BindContext>>
loader_factory_bindings_;
base::RepeatingClosure prefetch_load_callback_for_testing_;
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
deleted file mode 100644
index a6ce3d0b48f..00000000000
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
+++ /dev/null
@@ -1,376 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/redirect_to_file_resource_handler.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/threading/thread_restrictions.h"
-#include "content/browser/loader/resource_controller.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/browser/loader/temporary_file_stream.h"
-#include "net/base/file_stream.h"
-#include "net/base/io_buffer.h"
-#include "net/base/mime_sniffer.h"
-#include "net/base/net_errors.h"
-#include "services/network/public/cpp/resource_response.h"
-#include "storage/browser/blob/shareable_file_reference.h"
-
-using storage::ShareableFileReference;
-
-namespace {
-
-// This class is similar to identically named classes in AsyncResourceHandler
-// and MimeTypeResourceHandler, but not quite.
-// TODO(ncbray): generalize and unify these cases?
-// In general, it's a bad idea to point to a subbuffer (particularly with
-// GrowableIOBuffer) because the backing IOBuffer may realloc its data. In this
-// particular case we know RedirectToFileResourceHandler will not realloc its
-// buffer while a write is occurring, so we should be safe. This property is
-// somewhat fragile, however, and depending on it is dangerous. A more
-// principled approach would require significant refactoring, however, so for
-// the moment we're relying on fragile properties.
-class DependentIOBufferForRedirectToFile : public net::WrappedIOBuffer {
- public:
- DependentIOBufferForRedirectToFile(net::IOBuffer* backing, char* memory)
- : net::WrappedIOBuffer(memory), backing_(backing) {}
-
- private:
- ~DependentIOBufferForRedirectToFile() override {}
-
- scoped_refptr<net::IOBuffer> backing_;
-};
-
-} // namespace
-
-namespace content {
-
-const int RedirectToFileResourceHandler::kInitialReadBufSize = 32768;
-const int RedirectToFileResourceHandler::kMaxReadBufSize = 524288;
-
-// A separate IO thread object to manage the lifetime of the net::FileStream and
-// the ShareableFileReference. When the handler is destroyed, it asynchronously
-// closes net::FileStream after all pending writes complete. Only after the
-// stream is closed is the ShareableFileReference released, to ensure the
-// temporary is not deleted before it is closed.
-class RedirectToFileResourceHandler::Writer {
- public:
- Writer(RedirectToFileResourceHandler* handler,
- std::unique_ptr<net::FileStream> file_stream,
- ShareableFileReference* deletable_file)
- : handler_(handler),
- file_stream_(std::move(file_stream)),
- is_writing_(false),
- deletable_file_(deletable_file) {
- DCHECK(!deletable_file_->path().empty());
- }
-
- bool is_writing() const { return is_writing_; }
- const base::FilePath& path() const { return deletable_file_->path(); }
-
- int Write(net::IOBuffer* buf, int buf_len) {
- DCHECK(!is_writing_);
- DCHECK(handler_);
- int result = file_stream_->Write(
- buf, buf_len,
- base::BindOnce(&Writer::DidWriteToFile, base::Unretained(this)));
- if (result == net::ERR_IO_PENDING)
- is_writing_ = true;
- return result;
- }
-
- void Close() {
- handler_ = nullptr;
- if (!is_writing_)
- CloseAndDelete();
- }
-
- private:
- // Only DidClose can delete this.
- ~Writer() {
- }
-
- void DidWriteToFile(int result) {
- DCHECK(is_writing_);
- is_writing_ = false;
- if (handler_) {
- handler_->DidWriteToFile(result);
- } else {
- CloseAndDelete();
- }
- }
-
- void CloseAndDelete() {
- DCHECK(!is_writing_);
- int result = file_stream_->Close(
- base::BindOnce(&Writer::DidClose, base::Unretained(this)));
- if (result != net::ERR_IO_PENDING)
- DidClose(result);
- }
-
- void DidClose(int result) {
- delete this;
- }
-
- RedirectToFileResourceHandler* handler_;
-
- std::unique_ptr<net::FileStream> file_stream_;
- bool is_writing_;
-
- // We create a ShareableFileReference that's deletable for the temp file
- // created as a result of the download.
- scoped_refptr<storage::ShareableFileReference> deletable_file_;
-
- DISALLOW_COPY_AND_ASSIGN(Writer);
-};
-
-RedirectToFileResourceHandler::RedirectToFileResourceHandler(
- std::unique_ptr<ResourceHandler> next_handler,
- net::URLRequest* request)
- : LayeredResourceHandler(request, std::move(next_handler)),
- buf_(new net::GrowableIOBuffer()),
- weak_factory_(this) {}
-
-RedirectToFileResourceHandler::~RedirectToFileResourceHandler() {
- // Orphan the writer to asynchronously close and release the temporary file.
- if (writer_) {
- writer_->Close();
- writer_ = nullptr;
- }
-}
-
-void RedirectToFileResourceHandler::
- SetCreateTemporaryFileStreamFunctionForTesting(
- const CreateTemporaryFileStreamFunction& create_temporary_file_stream) {
- create_temporary_file_stream_ = create_temporary_file_stream;
-}
-
-void RedirectToFileResourceHandler::OnResponseStarted(
- network::ResourceResponse* response,
- std::unique_ptr<ResourceController> controller) {
- if (!writer_) {
- response_pending_file_creation_ = response;
- HoldController(std::move(controller));
- request()->LogBlockedBy("RedirectToFileResourceHandler");
- return;
- }
- response->head.download_file_path = writer_->path();
- next_handler_->OnResponseStarted(response, std::move(controller));
-}
-
-void RedirectToFileResourceHandler::OnWillStart(
- const GURL& url,
- std::unique_ptr<ResourceController> controller) {
- DCHECK(!writer_);
-
- // Create the file ASAP but don't block.
- if (create_temporary_file_stream_.is_null()) {
- CreateTemporaryFileStream(
- base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile,
- weak_factory_.GetWeakPtr()));
- } else {
- create_temporary_file_stream_.Run(
- base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile,
- weak_factory_.GetWeakPtr()));
- }
- next_handler_->OnWillStart(url, std::move(controller));
-}
-
-void RedirectToFileResourceHandler::OnWillRead(
- scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- std::unique_ptr<ResourceController> controller) {
- if (buf_->capacity() < next_buffer_size_)
- buf_->SetCapacity(next_buffer_size_);
-
- // We should have paused this network request already if the buffer is full.
- DCHECK(!BufIsFull());
-
- *buf = buf_.get();
- *buf_size = buf_->RemainingCapacity();
-
- buf_write_pending_ = true;
- controller->Resume();
-}
-
-void RedirectToFileResourceHandler::OnReadCompleted(
- int bytes_read,
- std::unique_ptr<ResourceController> controller) {
- DCHECK(buf_write_pending_);
- buf_write_pending_ = false;
-
- // We use the buffer's offset field to record the end of the buffer.
- int new_offset = buf_->offset() + bytes_read;
- DCHECK(new_offset <= buf_->capacity());
- buf_->set_offset(new_offset);
-
- if (buf_->capacity() == bytes_read) {
- // The network layer has saturated our buffer in one read. Next time, we
- // should give it a bigger buffer for it to fill.
- next_buffer_size_ = std::min(next_buffer_size_ * 2, kMaxReadBufSize);
- }
-
- HoldController(std::move(controller));
- // WriteMore will resume the request if there's more buffer space.
- if (!WriteMore()) {
- CancelWithError(net::ERR_FAILED);
- return;
- }
-
- if (has_controller())
- request()->LogBlockedBy("RedirectToFileResourceHandler");
-}
-
-void RedirectToFileResourceHandler::OnResponseCompleted(
- const net::URLRequestStatus& status,
- std::unique_ptr<ResourceController> controller) {
- if (writer_ && writer_->is_writing()) {
- completed_during_write_ = true;
- completed_status_ = status;
- HoldController(std::move(controller));
- request()->LogBlockedBy("RedirectToFileResourceHandler");
- return;
- }
- next_handler_->OnResponseCompleted(status, std::move(controller));
-}
-
-int RedirectToFileResourceHandler::GetBufferSizeForTesting() const {
- return buf_->capacity();
-}
-
-void RedirectToFileResourceHandler::DidCreateTemporaryFile(
- base::File::Error error_code,
- std::unique_ptr<net::FileStream> file_stream,
- ShareableFileReference* deletable_file) {
- DCHECK(!writer_);
- if (error_code != base::File::FILE_OK) {
- if (has_controller()) {
- CancelWithError(net::FileErrorToNetError(error_code));
- } else {
- OutOfBandCancel(net::FileErrorToNetError(error_code),
- true /* tell_renderer */);
- }
- return;
- }
-
- writer_ = new Writer(this, std::move(file_stream), deletable_file);
-
- if (response_pending_file_creation_) {
- scoped_refptr<network::ResourceResponse> response =
- std::move(response_pending_file_creation_);
- request()->LogUnblocked();
- OnResponseStarted(response.get(), ReleaseController());
- }
-}
-
-void RedirectToFileResourceHandler::DidWriteToFile(int result) {
- bool failed = false;
- if (result > 0) {
- OnDataDownloaded(result);
- write_cursor_ += result;
- // WriteMore will resume the request if the request hasn't completed and
- // there's more buffer space.
- failed = !WriteMore();
- } else {
- failed = true;
- }
-
- if (failed) {
- DCHECK(!writer_->is_writing());
- // TODO(davidben): Recover the error code from WriteMore or |result|, as
- // appropriate.
- if (completed_during_write_ && completed_status_.is_success()) {
- // If the request successfully completed mid-write, but the write failed,
- // convert the status to a failure for downstream.
- completed_status_ = net::URLRequestStatus(net::URLRequestStatus::CANCELED,
- net::ERR_FAILED);
- }
- if (!completed_during_write_) {
- if (has_controller()) {
- // If the write buffer is full, |this| has deferred the request, and
- // can do an in-band cancel.
- CancelWithError(net::ERR_FAILED);
- } else {
- OutOfBandCancel(net::ERR_FAILED, true /* tell_renderer */);
- }
- return;
- }
- }
-
- if (completed_during_write_ && !writer_->is_writing()) {
- // Resume shutdown now that all data has been written to disk. Note that
- // this should run even in the |failed| case above, otherwise a failed write
- // leaves the handler stuck.
- DCHECK(has_controller());
- request()->LogUnblocked();
- next_handler_->OnResponseCompleted(completed_status_, ReleaseController());
- }
-}
-
-bool RedirectToFileResourceHandler::WriteMore() {
- DCHECK(writer_);
-
- for (;;) {
- if (write_cursor_ == buf_->offset()) {
- // We've caught up to the network load, but it may be in the process of
- // appending more data to the buffer.
- if (!buf_write_pending_) {
- buf_->set_offset(0);
- write_cursor_ = 0;
- }
- break;
- }
- if (writer_->is_writing())
- break;
- DCHECK(write_cursor_ < buf_->offset());
-
- // Create a temporary buffer pointing to a subsection of the data buffer so
- // that it can be passed to Write. This code makes some crazy scary
- // assumptions about object lifetimes, thread sharing, and that buf_ will
- // not realloc durring the write due to how the state machine in this class
- // works.
- // Note that buf_ is also shared with the code that writes data into the
- // cache, so modifying it can cause some pretty subtle race conditions:
- // https://code.google.com/p/chromium/issues/detail?id=152076
- // We're using DependentIOBuffer instead of DrainableIOBuffer to dodge some
- // of these issues, for the moment.
- // TODO(ncbray) make this code less crazy scary.
- // Also note that Write may increase the refcount of "wrapped" deep in the
- // bowels of its implementation, the use of scoped_refptr here is not
- // spurious.
- scoped_refptr<DependentIOBufferForRedirectToFile> wrapped =
- new DependentIOBufferForRedirectToFile(
- buf_.get(), buf_->StartOfBuffer() + write_cursor_);
- int write_len = buf_->offset() - write_cursor_;
-
- int rv = writer_->Write(wrapped.get(), write_len);
- if (rv == net::ERR_IO_PENDING)
- break;
- if (rv <= 0)
- return false;
- OnDataDownloaded(rv);
- write_cursor_ += rv;
- }
-
- // If the request was defered for a reason other than having been completed,
- // and the buffer has space, resume the request.
- if (has_controller() && !completed_during_write_ && !BufIsFull()) {
- request()->LogUnblocked();
- Resume();
- }
- return true;
-}
-
-bool RedirectToFileResourceHandler::BufIsFull() const {
- // This is a hack to workaround MimeTypeResourceHandler's inability to
- // deal with a ResourceHandler that returns a buffer size of less than
- // 2 * net::kMaxBytesToSniff from its OnWillRead method.
- // TODO(darin): Fix this retardation!
- return buf_->RemainingCapacity() <= (2 * net::kMaxBytesToSniff);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.h b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
deleted file mode 100644
index 41fb23c1301..00000000000
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.h
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_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/weak_ptr.h"
-#include "content/browser/loader/layered_resource_handler.h"
-#include "content/browser/loader/temporary_file_stream.h"
-#include "content/common/content_export.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_status.h"
-#include "url/gurl.h"
-
-namespace net {
-class FileStream;
-class GrowableIOBuffer;
-}
-
-namespace storage {
-class ShareableFileReference;
-}
-
-namespace content {
-
-class ResourceController;
-
-// Redirects network data to a file. This is intended to be layered in front of
-// either the AsyncResourceHandler or the SyncResourceHandler. The downstream
-// resource handler does not see OnWillRead or OnReadCompleted calls. Instead,
-// the ResourceResponse contains the path to a temporary file and
-// OnDataDownloaded is called as the file downloads.
-class CONTENT_EXPORT RedirectToFileResourceHandler
- : public LayeredResourceHandler {
- public:
- // Exposed for testing.
- static const int kInitialReadBufSize;
- static const int kMaxReadBufSize;
-
- typedef base::Callback<void(const CreateTemporaryFileStreamCallback&)>
- CreateTemporaryFileStreamFunction;
-
- // Create a RedirectToFileResourceHandler for |request| which wraps
- // |next_handler|.
- RedirectToFileResourceHandler(std::unique_ptr<ResourceHandler> next_handler,
- net::URLRequest* request);
- ~RedirectToFileResourceHandler() override;
-
- // Replace the CreateTemporaryFileStream implementation with a mocked one for
- // testing purposes. The function should create a net::FileStream and a
- // ShareableFileReference and then asynchronously pass them to the
- // CreateTemporaryFileStreamCallback.
- void SetCreateTemporaryFileStreamFunctionForTesting(
- const CreateTemporaryFileStreamFunction& create_temporary_file_stream);
-
- // LayeredResourceHandler implementation:
- void OnResponseStarted(
- network::ResourceResponse* response,
- std::unique_ptr<ResourceController> controller) override;
- void OnWillStart(const GURL& url,
- std::unique_ptr<ResourceController> controller) override;
- void OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- std::unique_ptr<ResourceController> controller) override;
- void OnReadCompleted(int bytes_read,
- std::unique_ptr<ResourceController> controller) override;
- void OnResponseCompleted(
- const net::URLRequestStatus& status,
- std::unique_ptr<ResourceController> controller) override;
-
- // Returns the size of |buf_|, to make sure it's being increased as expected.
- int GetBufferSizeForTesting() const;
-
- private:
- void DidCreateTemporaryFile(base::File::Error error_code,
- std::unique_ptr<net::FileStream> file_stream,
- storage::ShareableFileReference* deletable_file);
-
- // Called by RedirectToFileResourceHandler::Writer.
- void DidWriteToFile(int result);
-
- // Attempts to write more data to the file, if possible. Returns false on
- // error. Returns true if there's already a write in progress, all data was
- // written successfully, or a new write was started that will complete
- // asynchronously. Resumes the request if there's more data to read and more
- // buffer space available.
- bool WriteMore();
-
- bool BufIsFull() const;
-
- // If populated, OnResponseStarted completion is pending on file creation.
- scoped_refptr<network::ResourceResponse> response_pending_file_creation_;
- CreateTemporaryFileStreamFunction create_temporary_file_stream_;
-
- // We allocate a single, fixed-size IO buffer (buf_) used to read from the
- // network (buf_write_pending_ is true while the system is copying data into
- // buf_), and then write this buffer out to disk (write_callback_pending_ is
- // true while writing to disk). Reading from the network is suspended while
- // the buffer is full (BufIsFull returns true). The write_cursor_ member
- // tracks the offset into buf_ that we are writing to disk.
-
- scoped_refptr<net::GrowableIOBuffer> buf_;
- bool buf_write_pending_ = false;
- int write_cursor_ = 0;
-
- // Helper writer object which maintains references to the net::FileStream and
- // storage::ShareableFileReference. This is maintained separately so that,
- // on Windows, the temporary file isn't deleted until after it is closed.
- class Writer;
- Writer* writer_ = nullptr;
-
- // |next_buffer_size_| is the size of the buffer to be allocated on the next
- // OnWillRead() call. We exponentially grow the size of the buffer allocated
- // when our owner fills our buffers. On the first OnWillRead() call, we
- // allocate a buffer of 32k and double it in OnReadCompleted() if the buffer
- // was filled, up to a maximum size of 512k.
- int next_buffer_size_ = kInitialReadBufSize;
-
- bool completed_during_write_ = false;
- net::URLRequestStatus completed_status_;
-
- base::WeakPtrFactory<RedirectToFileResourceHandler> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(RedirectToFileResourceHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc b/chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc
deleted file mode 100644
index ac012a09e0e..00000000000
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc
+++ /dev/null
@@ -1,925 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/redirect_to_file_resource_handler.h"
-
-#include <algorithm>
-#include <limits>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/run_loop.h"
-#include "base/strings/string_piece.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/loader/mock_resource_loader.h"
-#include "content/browser/loader/temporary_file_stream.h"
-#include "content/browser/loader/test_resource_handler.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/base/completion_callback.h"
-#include "net/base/completion_once_callback.h"
-#include "net/base/file_stream.h"
-#include "net/base/io_buffer.h"
-#include "net/base/mime_sniffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/request_priority.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_status.h"
-#include "net/url_request/url_request_test_util.h"
-#include "services/network/public/cpp/resource_response.h"
-#include "storage/browser/blob/shareable_file_reference.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace content {
-namespace {
-
-// The maximum size for which the initial read will always be sync, even when
-// the wrote completes asynchronously. See
-// RedirectToFileResourceHandler::BufIsFull().
-const int kMaxInitialSyncReadSize =
- RedirectToFileResourceHandler::kInitialReadBufSize -
- 2 * net::kMaxBytesToSniff - 1;
-
-// Used to indicate whether FileStream operations and the lower-layer
-// TestResourceHandler operations should complete immediately or by
-// asynchronously invoking a callback. Each test is run with all operations set
-// by default to each mode, though some tests override the mode of some
-// operations.
-enum class CompletionMode {
- SYNC,
- ASYNC,
-};
-
-// Mock in-memory net::FileStream implementation that can be configured to
-// return errors and complete operations synchronously or asynchronously.
-class MockFileStream : public net::FileStream {
- public:
- struct OperationResult {
- OperationResult(int result, CompletionMode completion_mode)
- : result(result), completion_mode(completion_mode) {}
-
- OperationResult()
- : OperationResult(net::ERR_UNEXPECTED, CompletionMode::SYNC) {}
-
- int result;
- CompletionMode completion_mode;
- };
-
- MockFileStream() : FileStream(base::ThreadTaskRunnerHandle::Get()) {}
-
- ~MockFileStream() override {
- EXPECT_EQ(expect_closed_, closed_);
- // Most of these tests write 32k or more, which is a bit much for the
- // command line.
- EXPECT_TRUE(expected_written_data_ == written_data_);
- }
-
- // net::FileStream implementation:
-
- int Open(const base::FilePath& path,
- int open_flags,
- net::CompletionOnceCallback callback) override {
- return ReturnResult(open_result_, std::move(callback));
- }
-
- int Close(net::CompletionOnceCallback callback) override {
- EXPECT_FALSE(closed_);
- int result = ReturnResult(
- close_result_,
- base::BindOnce(&MockFileStream::SetClosedAndRunCallback,
- base::Unretained(this), std::move(callback)));
- if (result != net::ERR_IO_PENDING)
- closed_ = true;
- return result;
- }
-
- bool IsOpen() const override {
- NOTREACHED();
- return false;
- }
-
- int Seek(int64_t offset, net::Int64CompletionOnceCallback callback) override {
- NOTREACHED();
- return net::ERR_UNEXPECTED;
- }
-
- int Read(net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback) override {
- NOTREACHED();
- return net::ERR_UNEXPECTED;
- }
-
- int Write(net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback) override {
- // 0-byte writes aren't allowed.
- EXPECT_GT(buf_len, 0);
-
- OperationResult write_result = next_write_result_;
- next_write_result_ = all_write_results_;
- if (write_result.result > buf_len)
- write_result.result = buf_len;
- if (write_result.result > 0)
- written_data_ += std::string(buf->data(), write_result.result);
-
- return ReturnResult(write_result, std::move(callback));
- }
-
- int Flush(net::CompletionOnceCallback callback) override {
- NOTREACHED();
- return net::ERR_UNEXPECTED;
- }
-
- void set_open_result(OperationResult open_result) {
- open_result_ = open_result;
- }
- void set_close_result(OperationResult close_result) {
- close_result_ = close_result;
- }
-
- // Sets the result for all write operations. Returned result is capped at
- // number of bytes the consumer actually tried to write. Overrides
- // |next_write_result_|.
- void set_all_write_results(OperationResult all_write_results) {
- next_write_result_ = all_write_results_ = all_write_results;
- }
-
- // Sets the result of only the next write operation.
- void set_next_write_result(OperationResult next_write_result) {
- next_write_result_ = next_write_result;
- }
-
- void set_expected_written_data(const std::string& expected_written_data) {
- expected_written_data_ = expected_written_data;
- }
-
- // Sets whether the file should expect to be closed.
- void set_expect_closed(bool expect_closed) { expect_closed_ = expect_closed; }
-
- private:
- void SetClosedAndRunCallback(net::CompletionOnceCallback callback,
- int result) {
- EXPECT_FALSE(closed_);
- closed_ = true;
- std::move(callback).Run(result);
- }
-
- int ReturnResult(OperationResult result,
- net::CompletionOnceCallback callback) {
- if (result.completion_mode == CompletionMode::SYNC)
- return result.result;
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), result.result));
- return net::ERR_IO_PENDING;
- }
-
- OperationResult open_result_;
- OperationResult close_result_;
- OperationResult next_write_result_;
- OperationResult all_write_results_;
-
- std::string expected_written_data_;
- std::string written_data_;
-
- bool expect_closed_ = false;
- bool closed_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(MockFileStream);
-};
-
-class RedirectToFileResourceHandlerTest
- : public testing::TestWithParam<CompletionMode> {
- public:
- RedirectToFileResourceHandlerTest()
- : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
- url_request_(
- url_request_context_.CreateRequest(GURL("foo://bar/"),
- net::DEFAULT_PRIORITY,
- &url_request_delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS)) {
- base::CreateTemporaryFile(&temp_file_path_);
- std::unique_ptr<TestResourceHandler> test_handler =
- std::make_unique<TestResourceHandler>();
- test_handler->set_expect_on_data_downloaded(true);
- if (GetParam() == CompletionMode::ASYNC) {
- // Don't defer OnResponseCompleted, by default, since that's really
- // unusual.
- test_handler->set_defer_on_response_started(true);
- test_handler->set_defer_on_will_start(true);
- }
- test_handler_ = test_handler->GetWeakPtr();
-
- redirect_to_file_handler_ = std::make_unique<RedirectToFileResourceHandler>(
- std::move(test_handler), url_request_.get());
- mock_loader_ =
- std::make_unique<MockResourceLoader>(redirect_to_file_handler_.get());
- redirect_to_file_handler_->SetCreateTemporaryFileStreamFunctionForTesting(
- base::Bind(&RedirectToFileResourceHandlerTest::
- SetCreateTemporaryFileStreamCallback,
- base::Unretained(this)));
-
- file_stream_ = std::make_unique<MockFileStream>();
- file_stream_->set_open_result(
- MockFileStream::OperationResult(net::OK, GetParam()));
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), GetParam()));
- file_stream_->set_close_result(
- MockFileStream::OperationResult(net::OK, GetParam()));
- }
-
- ~RedirectToFileResourceHandlerTest() override {
- EXPECT_FALSE(test_handler_->on_read_completed_called());
-
- // This should post a task to delete the temporary file.
- redirect_to_file_handler_.reset();
- mock_loader_.reset();
- url_request_.reset();
- // This should delete the temporary file, and ensure
- // MockFileStream::Cancel() is called.
- base::RunLoop().RunUntilIdle();
-
- EXPECT_FALSE(base::PathExists(temp_file_path_));
- }
-
- // Creates a test string of the specified length, and sets that as the
- // expected data written to |file_stream_|.
- std::string CreateTestData(size_t length) {
- std::string test_data;
- test_data.reserve(length);
- for (size_t i = 0; i < length; ++i)
- test_data.push_back(static_cast<char>(i % 256));
- file_stream_->set_expected_written_data(test_data);
- return test_data;
- }
-
- // The "CreateTemporaryFileStream" method invoked by the
- // RedirectToFileResourceHandler. Just sets a callback that will be invoked
- // directly.
- void SetCreateTemporaryFileStreamCallback(
- const CreateTemporaryFileStreamCallback& create_file_stream_callback) {
- create_file_stream_callback_ = create_file_stream_callback;
- }
-
- void PerformOnWillStart() {
- MockResourceLoader::Status expected_status;
- if (GetParam() == CompletionMode::ASYNC) {
- expected_status = MockResourceLoader::Status::CALLBACK_PENDING;
- } else {
- expected_status = MockResourceLoader::Status::IDLE;
- }
- EXPECT_EQ(expected_status, mock_loader_->OnWillStart(url_request_->url()));
- }
-
- // Sets up the file stream or error, and performs the file callback.
- void PerformCreateFile(base::File::Error file_error) {
- DCHECK(file_stream_);
-
- file_stream_->set_expect_closed(file_error == base::File::FILE_OK);
- if (file_error != base::File::FILE_OK)
- file_stream_ = nullptr;
-
- base::ResetAndReturn(&create_file_stream_callback_)
- .Run(file_error, std::move(file_stream_),
- // Not really used by the test, but the ResourceHandler expects it
- // to be non-null.
- storage::ShareableFileReference::GetOrCreate(
- temp_file_path_,
- storage::ShareableFileReference::DELETE_ON_FINAL_RELEASE,
- base::ThreadTaskRunnerHandle::Get().get())
- .get());
- }
-
- // Simulates starting the request, the response starting, and stream creation
- // completing with the specified error code. Has |test_handler_| resume the
- // request, if needed. Returns final status of |mock_loader_|.
- MockResourceLoader::Status StartAndCreateStream(base::File::Error file_error)
- WARN_UNUSED_RESULT {
- PerformOnWillStart();
-
- // Create the file right away.
- PerformCreateFile(file_error);
-
- // If this is an async test, |test_handler_| will defer the OnWillStart
- // event on success (On error, its OnWillStart method is not called).
- if (file_error == base::File::FILE_OK &&
- GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- test_handler_->Resume();
- mock_loader_->WaitUntilIdleOrCanceled();
- }
- EXPECT_NE(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- return mock_loader_->status();
- }
-
- // Convenience wrapper for MockLoader methods that will Resume |test_handler_|
- // and wait for it to resume the request if running an async test.
- MockResourceLoader::Status OnResponseStartedAndWaitForResult()
- WARN_UNUSED_RESULT {
- mock_loader_->OnResponseStarted(
- base::MakeRefCounted<network::ResourceResponse>());
- if (GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- test_handler_->Resume();
- mock_loader_->WaitUntilIdleOrCanceled();
- }
- EXPECT_NE(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- return mock_loader_->status();
- }
-
- // Utility method that simulates a final 0-byte read and response completed
- // events, and checks that completion is handled correctly. Expects all data
- // to already have been written to the file.
- void CompleteRequestSuccessfully(int expected_total_bytes_downloaded) {
- // The loader should be idle and all the data should have already been
- // processed.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
- EXPECT_EQ(expected_total_bytes_downloaded,
- test_handler_->total_bytes_downloaded());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(""));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::OK)));
- EXPECT_EQ(expected_total_bytes_downloaded,
- test_handler_->total_bytes_downloaded());
- EXPECT_EQ(net::URLRequestStatus::SUCCESS,
- test_handler_->final_status().status());
- }
-
- protected:
- TestBrowserThreadBundle thread_bundle_;
- base::FilePath temp_file_path_;
- net::TestURLRequestContext url_request_context_;
- net::TestDelegate url_request_delegate_;
- base::WeakPtr<TestResourceHandler> test_handler_;
- std::unique_ptr<net::URLRequest> url_request_;
- std::unique_ptr<MockResourceLoader> mock_loader_;
- std::unique_ptr<RedirectToFileResourceHandler> redirect_to_file_handler_;
- std::unique_ptr<MockFileStream> file_stream_;
-
- CreateTemporaryFileStreamCallback create_file_stream_callback_;
-};
-
-TEST_P(RedirectToFileResourceHandlerTest, EmptyBody) {
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- CompleteRequestSuccessfully(0);
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, SingleBodyRead) {
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
- // Wait for the write to complete, in the async case.
- base::RunLoop().RunUntilIdle();
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, SingleBodyReadDelayedFileOnResponse) {
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- PerformOnWillStart();
- if (GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- test_handler_->Resume();
- mock_loader_->WaitUntilIdleOrCanceled();
- }
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
- mock_loader_->OnResponseStarted(
- base::MakeRefCounted<network::ResourceResponse>());
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
-
- PerformCreateFile(base::File::FILE_OK);
-
- if (GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- test_handler_->Resume();
- mock_loader_->WaitUntilIdleOrCanceled();
- }
- EXPECT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
- // Wait for the write to complete, in the async case.
- base::RunLoop().RunUntilIdle();
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, SingleBodyReadDelayedFileError) {
- std::string test_data = CreateTestData(0);
-
- PerformOnWillStart();
- if (GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
- test_handler_->Resume();
- mock_loader_->WaitUntilIdleOrCanceled();
- }
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
- mock_loader_->OnResponseStarted(
- base::MakeRefCounted<network::ResourceResponse>());
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->status());
-
- PerformCreateFile(base::File::FILE_ERROR_FAILED);
-
- EXPECT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status());
- EXPECT_EQ(0, test_handler_->on_response_completed_called());
- EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, ManySequentialBodyReads) {
- const size_t kBytesPerRead = 128;
- std::string test_data =
- CreateTestData(RedirectToFileResourceHandler::kInitialReadBufSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- for (size_t offset = 0; offset < test_data.length();
- offset += kBytesPerRead) {
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- size_t length = std::min(kBytesPerRead, test_data.length() - offset);
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(
- base::StringPiece(test_data.data() + offset, length)));
- // Spin the message loop, to allow async writes to complete.
- base::RunLoop().RunUntilIdle();
- }
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, PartialWrites) {
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- RedirectToFileResourceHandler::kInitialReadBufSize / 50, GetParam()));
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
- // Wait for the writes to complete, in the async case.
- base::RunLoop().RunUntilIdle();
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-// Same as above, but read enough data to defer reading the body.
-TEST_P(RedirectToFileResourceHandlerTest, PartialWrites2) {
- std::string test_data =
- CreateTestData(RedirectToFileResourceHandler::kInitialReadBufSize);
- // Async reads, as otherwise reading won't be defered.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- RedirectToFileResourceHandler::kInitialReadBufSize / 50,
- CompletionMode::ASYNC));
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnReadCompleted(test_data));
- // Wait for the writes to complete.
- base::RunLoop().RunUntilIdle();
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, ReceiveDataWhileWritingBody) {
- const int kFirstWriteSize = 100;
-
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- // Will use multiple writes, with a combined size such that they don't
- // saturate the buffer.
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(
- MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(0, kFirstWriteSize)));
- // Next read completes before first write succeeds.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(
- kFirstWriteSize, sizeof(test_data) - kFirstWriteSize)));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // Wait for both writes to succeed.
- base::RunLoop().RunUntilIdle();
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, ReceiveDataAndDeferWhileWritingBody) {
- const int kFirstWriteSize = 100;
-
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- // Will use multiple writes, with a combined size such that they saturate the
- // buffer.
- std::string test_data =
- CreateTestData(RedirectToFileResourceHandler::kInitialReadBufSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(
- MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(0, kFirstWriteSize)));
- // Next read completes before first write succeeds.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnReadCompleted(test_data.substr(
- kFirstWriteSize, sizeof(test_data) - kFirstWriteSize)));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // Wait for both writes to succeed.
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest,
- ExpandBufferCapacityManySequentialBodyReads) {
- // The buffer is only resized when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- const int kInitialReadSize =
- RedirectToFileResourceHandler::kInitialReadBufSize;
- const int kMaxReadSize = RedirectToFileResourceHandler::kMaxReadBufSize;
- int next_read_size = kInitialReadSize;
- int total_read_bytes = 0;
- // Populate |read_sizes| with expected buffer sizes if each previous read
- // filled the entire buffer.
- std::vector<size_t> read_sizes;
- while (true) {
- total_read_bytes += next_read_size;
- read_sizes.push_back(next_read_size);
- if (next_read_size == kMaxReadSize)
- break;
- next_read_size = std::min(2 * next_read_size, kMaxReadSize);
- }
- // Once the max is reached, do another round to make sure it isn't increased.
- total_read_bytes += kMaxReadSize;
- read_sizes.push_back(kMaxReadSize);
-
- std::string test_data = CreateTestData(total_read_bytes);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- int offset = 0;
- for (int read_size : read_sizes) {
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnReadCompleted(
- base::StringPiece(test_data.data() + offset, read_size)));
- offset += read_size;
-
- EXPECT_EQ(read_size, redirect_to_file_handler_->GetBufferSizeForTesting());
-
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
- }
-
- CompleteRequestSuccessfully(test_data.size());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, CompletedWhileWritingBody) {
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // While data is being written to the disk, the request completes.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(""));
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::OK)));
-
- // Wait for the write to complete and the final status sent to the
- // TestHandler.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(test_data.size()),
- test_handler_->total_bytes_downloaded());
- EXPECT_EQ(net::URLRequestStatus::SUCCESS,
- test_handler_->final_status().status());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest,
- CompletedWhileWritingBodyAndWritePending) {
- const int kFirstWriteSize = 100;
-
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- // Will use multiple writes, with a combined size such that they don't
- // saturate the buffer.
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(
- MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(0, kFirstWriteSize)));
- // Next read completes before first write succeeds.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(
- kFirstWriteSize, sizeof(test_data) - kFirstWriteSize)));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // While the first write is still going on, the request completes.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(""));
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::OK)));
-
- // Wait for both writes to complete and the final status to be sent to the
- // TestHandler.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(test_data.size()),
- test_handler_->total_bytes_downloaded());
- EXPECT_EQ(net::URLRequestStatus::SUCCESS,
- test_handler_->final_status().status());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, SingleBodyReadAndFail) {
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
-
- // Wait for the write to complete.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(test_data.size()),
- test_handler_->total_bytes_downloaded());
-
- // Next read fails and request is torn down synchronously.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
-
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, FailedWhileWritingBody) {
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // While data is being written to the disk, the request fails.
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
-
- // Wait for the write to complete and the final status sent to the
- // TestHandler.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(test_data.size()),
- test_handler_->total_bytes_downloaded());
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest,
- FailededWhileWritingBodyAndWritePending) {
- const int kFirstWriteSize = 100;
-
- // This test only makes sense when reads are async.
- file_stream_->set_all_write_results(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), CompletionMode::ASYNC));
-
- // Will use multiple writes, with a combined size such that they don't
- // saturate the buffer.
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(
- MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(0, kFirstWriteSize)));
- // Next read completes before first write succeeds.
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(test_data.substr(
- kFirstWriteSize, sizeof(test_data) - kFirstWriteSize)));
-
- // While the first write is still going on, the request fails.
- ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
-
- // Wait for both writes to complete and the final status to be sent to the
- // TestHandler.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(test_data.size()),
- test_handler_->total_bytes_downloaded());
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, CreateFileFails) {
- ASSERT_EQ(MockResourceLoader::Status::CANCELED,
- StartAndCreateStream(base::File::FILE_ERROR_FAILED));
-
- EXPECT_EQ(0, test_handler_->on_response_completed_called());
- EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
- if (GetParam() == CompletionMode::ASYNC) {
- EXPECT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompletedFromExternalOutOfBandCancel(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- } else {
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- }
-
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, FirstWriteFails) {
- std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
- file_stream_->set_expected_written_data("");
- file_stream_->set_next_write_result(
- MockFileStream::OperationResult(net::ERR_FAILED, GetParam()));
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- mock_loader_->OnReadCompleted(test_data);
- // Wait for the write to complete, in the async case.
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status());
-
- EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
- EXPECT_EQ(0, test_handler_->on_response_completed_called());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-TEST_P(RedirectToFileResourceHandlerTest, SecondWriteFails) {
- const int kFirstWriteSize = kMaxInitialSyncReadSize;
- std::string test_data =
- CreateTestData(RedirectToFileResourceHandler::kInitialReadBufSize);
- file_stream_->set_expected_written_data(test_data.substr(0, kFirstWriteSize));
- file_stream_->set_all_write_results(
- MockFileStream::OperationResult(net::ERR_FAILED, GetParam()));
- file_stream_->set_next_write_result(MockFileStream::OperationResult(
- std::numeric_limits<int>::max(), GetParam()));
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- StartAndCreateStream(base::File::FILE_OK));
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- OnResponseStartedAndWaitForResult());
-
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnReadCompleted(
- base::StringPiece(test_data.data(), kFirstWriteSize)));
- ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
- mock_loader_->OnReadCompleted(base::StringPiece(
- test_data.data() + kFirstWriteSize, test_data.size() - kFirstWriteSize));
- // Wait for the write to complete, in the async case.
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status());
-
- EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
- EXPECT_EQ(0, test_handler_->on_response_completed_called());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
- EXPECT_EQ(kFirstWriteSize, test_handler_->total_bytes_downloaded());
- EXPECT_FALSE(test_handler_->final_status().is_success());
- EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
-}
-
-INSTANTIATE_TEST_CASE_P(/* No prefix needed */,
- RedirectToFileResourceHandlerTest,
- testing::Values(CompletionMode::SYNC,
- CompletionMode::ASYNC));
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/browser/loader/resource_buffer.cc b/chromium/content/browser/loader/resource_buffer.cc
deleted file mode 100644
index 5e34dd24f15..00000000000
--- a/chromium/content/browser/loader/resource_buffer.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/resource_buffer.h"
-
-#include <math.h>
-
-#include "base/logging.h"
-
-namespace content {
-
-// A circular buffer allocator.
-//
-// We keep track of the starting offset (alloc_start_) and the ending offset
-// (alloc_end_). There are two layouts to keep in mind:
-//
-// #1:
-// ------------[XXXXXXXXXXXXXXXXXXXXXXX]----
-// ^ ^
-// start end
-//
-// #2:
-// XXXXXXXXXX]---------------------[XXXXXXXX
-// ^ ^
-// end start
-//
-// If end <= start, then we have the buffer wraparound case (depicted second).
-// If the buffer is empty, then start and end will be set to -1.
-//
-// Allocations are always contiguous.
-
-ResourceBuffer::ResourceBuffer()
- : buf_size_(0),
- min_alloc_size_(0),
- max_alloc_size_(0),
- alloc_start_(-1),
- alloc_end_(-1) {
-}
-
-ResourceBuffer::~ResourceBuffer() {
-}
-
-bool ResourceBuffer::Initialize(int buffer_size,
- int min_allocation_size,
- int max_allocation_size) {
- CHECK(!IsInitialized());
-
- // It would be wasteful if these are not multiples of min_allocation_size.
- CHECK_EQ(0, buffer_size % min_allocation_size);
- CHECK_EQ(0, max_allocation_size % min_allocation_size);
-
- buf_size_ = buffer_size;
- min_alloc_size_ = min_allocation_size;
- max_alloc_size_ = max_allocation_size;
-
- return shared_mem_.CreateAndMapAnonymous(buf_size_);
-}
-
-bool ResourceBuffer::IsInitialized() const {
- return shared_mem_.memory() != nullptr;
-}
-
-base::SharedMemory& ResourceBuffer::GetSharedMemory() {
- CHECK(IsInitialized());
- return shared_mem_;
-}
-
-bool ResourceBuffer::CanAllocate() const {
- CHECK(IsInitialized());
-
- if (alloc_start_ == -1)
- return true;
-
- int diff = alloc_end_ - alloc_start_;
- if (diff > 0)
- return (buf_size_ - diff) >= min_alloc_size_;
-
- return -diff >= min_alloc_size_;
-}
-
-char* ResourceBuffer::Allocate(int* size) {
- CHECK(CanAllocate());
-
- int alloc_offset = 0;
- int alloc_size;
-
- if (alloc_start_ == -1) {
- // This is the first allocation.
- alloc_start_ = 0;
- alloc_end_ = buf_size_;
- alloc_size = buf_size_;
- } else if (alloc_start_ < alloc_end_) {
- // Append the next allocation if it fits. Otherwise, wraparound.
- //
- // NOTE: We could look to see if a larger allocation is possible by
- // wrapping around sooner, but instead we just look to fill the space at
- // the end of the buffer provided that meets the min_alloc_size_
- // requirement.
- //
- if ((buf_size_ - alloc_end_) >= min_alloc_size_) {
- alloc_offset = alloc_end_;
- alloc_size = buf_size_ - alloc_end_;
- alloc_end_ = buf_size_;
- } else {
- // It must be possible to allocate a least min_alloc_size_.
- CHECK(alloc_start_ >= min_alloc_size_);
- alloc_size = alloc_start_;
- alloc_end_ = alloc_start_;
- }
- } else {
- // This is the wraparound case.
- CHECK(alloc_end_ < alloc_start_);
- alloc_offset = alloc_end_;
- alloc_size = alloc_start_ - alloc_end_;
- alloc_end_ = alloc_start_;
- }
-
- // Make sure alloc_size does not exceed max_alloc_size_. We store the
- // current value of alloc_size, so that we can use ShrinkLastAllocation to
- // trim it back. This allows us to reuse the alloc_end_ adjustment logic.
-
- alloc_sizes_.push(alloc_size);
-
- if (alloc_size > max_alloc_size_) {
- alloc_size = max_alloc_size_;
- ShrinkLastAllocation(alloc_size);
- }
-
- *size = alloc_size;
- return static_cast<char*>(shared_mem_.memory()) + alloc_offset;
-}
-
-int ResourceBuffer::GetLastAllocationOffset() const {
- CHECK(!alloc_sizes_.empty());
- CHECK(alloc_end_ >= alloc_sizes_.back());
- return alloc_end_ - alloc_sizes_.back();
-}
-
-void ResourceBuffer::ShrinkLastAllocation(int new_size) {
- CHECK(!alloc_sizes_.empty());
-
- int aligned_size = (new_size / min_alloc_size_) * min_alloc_size_;
- if (aligned_size < new_size)
- aligned_size += min_alloc_size_;
-
- CHECK_LE(new_size, aligned_size);
- CHECK_GE(alloc_sizes_.back(), aligned_size);
-
- int* last_allocation_size = &alloc_sizes_.back();
- alloc_end_ -= (*last_allocation_size - aligned_size);
- *last_allocation_size = aligned_size;
-}
-
-void ResourceBuffer::RecycleLeastRecentlyAllocated() {
- CHECK(!alloc_sizes_.empty());
- int allocation_size = alloc_sizes_.front();
- alloc_sizes_.pop();
-
- alloc_start_ += allocation_size;
- CHECK(alloc_start_ <= buf_size_);
-
- if (alloc_start_ == alloc_end_) {
- CHECK(alloc_sizes_.empty());
- alloc_start_ = -1;
- alloc_end_ = -1;
- } else if (alloc_start_ == buf_size_) {
- CHECK(!alloc_sizes_.empty());
- alloc_start_ = 0;
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/resource_buffer.h b/chromium/content/browser/loader/resource_buffer.h
deleted file mode 100644
index 85354c4a1c7..00000000000
--- a/chromium/content/browser/loader/resource_buffer.h
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_RESOURCE_BUFFER_H_
-#define CONTENT_BROWSER_LOADER_RESOURCE_BUFFER_H_
-
-#include "base/containers/queue.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/shared_memory.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// ResourceBuffer implements a simple "circular buffer" allocation strategy.
-// Allocations are recycled in FIFO order.
-//
-// You can think of the ResourceBuffer as a FIFO. The Allocate method reserves
-// space in the buffer. Allocate may be called multiple times until the buffer
-// is fully reserved (at which point CanAllocate returns false). Allocations
-// are freed in FIFO order via a call to RecycleLeastRecentlyAllocated.
-//
-// ResourceBuffer is reference-counted for the benefit of consumers, who need
-// to ensure that ResourceBuffer stays alive while they are using its memory.
-//
-// EXAMPLE USAGE:
-//
-// // Writes data into the ResourceBuffer, and returns the location (byte
-// // offset and count) of the bytes written into the ResourceBuffer's shared
-// // memory buffer.
-// void WriteToBuffer(ResourceBuffer* buf, int* offset, int* count) {
-// DCHECK(buf->CanAllocate());
-//
-// *offset = -1;
-// *count = 0;
-//
-// int size;
-// char* ptr = buf->Allocate(&size);
-// if (!ptr) { /* handle error */ }
-//
-// int bytes_read = static_cast<int>(fread(ptr, 1, size, file_pointer_));
-// if (!bytes_read) { /* handle error */ }
-//
-// if (bytes_read < size)
-// buf->ShrinkLastAllocation(bytes_read);
-//
-// *offset = buf->GetLastAllocationOffset();
-// *count = bytes_read;
-// }
-//
-// NOTE: As the above example illustrates, the ResourceBuffer keeps track of
-// the last allocation made. Calling ShrinkLastAllocation is optional, as it
-// just helps the ResourceBuffer optimize storage and be more aggressive about
-// returning larger allocations from the Allocate method.
-//
-class CONTENT_EXPORT ResourceBuffer
- : public base::RefCountedThreadSafe<ResourceBuffer> {
- public:
- ResourceBuffer();
-
- // Initialize the shared memory buffer. It will be buffer_size bytes in
- // length. The min/max_allocation_size parameters control the behavior of
- // the Allocate method. It will prefer to return segments that are
- // max_allocation_size in length, but will return segments less than that if
- // space is limited. It will not return allocations smaller than
- // min_allocation_size.
- bool Initialize(int buffer_size,
- int min_allocation_size,
- int max_allocation_size);
- bool IsInitialized() const;
-
- // Returns a reference to the underlying shared memory.
- base::SharedMemory& GetSharedMemory();
-
- // Returns true if Allocate will succeed.
- bool CanAllocate() const;
-
- // Returns a pointer into the shared memory buffer or NULL if the buffer is
- // already fully allocated. The returned size will be max_allocation_size
- // unless the buffer is close to being full.
- char* Allocate(int* size);
-
- // Returns the offset into the shared memory buffer where the last allocation
- // returned by Allocate can be found.
- int GetLastAllocationOffset() const;
-
- // Called to reduce the size of the last allocation returned by Allocate. It
- // is OK for new_size to match the current size of the last allocation.
- void ShrinkLastAllocation(int new_size);
-
- // Called to allow reuse of memory that was previously allocated. See notes
- // above the class for more details about this method.
- void RecycleLeastRecentlyAllocated();
-
- private:
- friend class base::RefCountedThreadSafe<ResourceBuffer>;
- ~ResourceBuffer();
-
- base::SharedMemory shared_mem_;
-
- int buf_size_;
- int min_alloc_size_;
- int max_alloc_size_;
-
- // These point to the range of the shared memory that is currently allocated.
- // If alloc_start_ is -1, then the range is empty and nothing is allocated.
- // Otherwise, alloc_start_ points to the start of the allocated range, and
- // alloc_end_ points just beyond the end of the previous allocation. In the
- // wraparound case, alloc_end_ <= alloc_start_. See resource_buffer.cc for
- // more details about these members.
- int alloc_start_;
- int alloc_end_;
-
- base::queue<int> alloc_sizes_;
-
- DISALLOW_COPY_AND_ASSIGN(ResourceBuffer);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_RESOURCE_BUFFER_H_
diff --git a/chromium/content/browser/loader/resource_buffer_unittest.cc b/chromium/content/browser/loader/resource_buffer_unittest.cc
deleted file mode 100644
index a9e90431544..00000000000
--- a/chromium/content/browser/loader/resource_buffer_unittest.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/resource_buffer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-TEST(ResourceBufferTest, BasicAllocations) {
- scoped_refptr<ResourceBuffer> buf = new ResourceBuffer();
- EXPECT_TRUE(buf->Initialize(100, 5, 10));
- EXPECT_TRUE(buf->CanAllocate());
-
- // First allocation
- {
- int size;
- char* ptr = buf->Allocate(&size);
- EXPECT_TRUE(ptr);
- EXPECT_EQ(10, size);
- EXPECT_TRUE(buf->CanAllocate());
-
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
-
- buf->ShrinkLastAllocation(2); // Less than our min allocation size.
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
- EXPECT_TRUE(buf->CanAllocate());
- }
-
- // Second allocation
- {
- int size;
- char* ptr = buf->Allocate(&size);
- EXPECT_TRUE(ptr);
- EXPECT_EQ(10, size);
- EXPECT_TRUE(buf->CanAllocate());
-
- EXPECT_EQ(5, buf->GetLastAllocationOffset());
-
- buf->ShrinkLastAllocation(4);
- EXPECT_EQ(5, buf->GetLastAllocationOffset());
-
- EXPECT_TRUE(buf->CanAllocate());
- }
-}
-
-TEST(ResourceBufferTest, AllocateAndRecycle) {
- scoped_refptr<ResourceBuffer> buf = new ResourceBuffer();
- EXPECT_TRUE(buf->Initialize(100, 5, 10));
-
- int size;
-
- buf->Allocate(&size);
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
-
- buf->RecycleLeastRecentlyAllocated();
-
- // Offset should again be 0.
- buf->Allocate(&size);
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
-}
-
-TEST(ResourceBufferTest, WrapAround) {
- scoped_refptr<ResourceBuffer> buf = new ResourceBuffer();
- EXPECT_TRUE(buf->Initialize(20, 10, 10));
-
- int size;
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- // Create hole at the beginnning. Next allocation should go there.
- buf->RecycleLeastRecentlyAllocated();
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
-}
-
-TEST(ResourceBufferTest, WrapAround2) {
- scoped_refptr<ResourceBuffer> buf = new ResourceBuffer();
- EXPECT_TRUE(buf->Initialize(30, 10, 10));
-
- int size;
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- EXPECT_FALSE(buf->CanAllocate());
-
- // Create holes at first and second slots.
- buf->RecycleLeastRecentlyAllocated();
- buf->RecycleLeastRecentlyAllocated();
-
- EXPECT_TRUE(buf->CanAllocate());
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
- EXPECT_EQ(0, buf->GetLastAllocationOffset());
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
- EXPECT_EQ(10, buf->GetLastAllocationOffset());
-
- EXPECT_FALSE(buf->CanAllocate());
-}
-
-TEST(ResourceBufferTest, Full) {
- scoped_refptr<ResourceBuffer> buf = new ResourceBuffer();
- EXPECT_TRUE(buf->Initialize(20, 10, 10));
-
- int size;
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- buf->Allocate(&size);
- EXPECT_EQ(10, size);
-
- // Full.
- EXPECT_FALSE(buf->CanAllocate());
-
- // Still full, even if there is a small hole at the end.
- buf->ShrinkLastAllocation(5);
- EXPECT_FALSE(buf->CanAllocate());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/resource_controller.h b/chromium/content/browser/loader/resource_controller.h
index 82785346fef..55ecd8c28a5 100644
--- a/chromium/content/browser/loader/resource_controller.h
+++ b/chromium/content/browser/loader/resource_controller.h
@@ -5,8 +5,13 @@
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_CONTROLLER_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_CONTROLLER_H_
+#include "base/optional.h"
#include "content/common/content_export.h"
+namespace net {
+class HttpRequestHeaders;
+};
+
namespace content {
// Used to either resume a deferred resource load or cancel a resource load at
@@ -25,6 +30,12 @@ class CONTENT_EXPORT ResourceController {
// deferred. Guaranteed not to call back into the ResourceHandler, or destroy
// it, synchronously.
virtual void Resume() = 0;
+
+ // Similar to |Resume()| but can only be called if the request was previously
+ // redirected. |modified_request_headers| are changes applied to the request
+ // headers after updating them for the redirect.
+ virtual void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) = 0;
};
} // namespace content
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index 1c1fb59e02c..061ad189c46 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -47,7 +47,6 @@
#include "content/browser/loader/mime_sniffing_resource_handler.h"
#include "content/browser/loader/mojo_async_resource_handler.h"
#include "content/browser/loader/null_resource_controller.h"
-#include "content/browser/loader/redirect_to_file_resource_handler.h"
#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -55,7 +54,6 @@
#include "content/browser/loader/stream_resource_handler.h"
#include "content/browser/loader/throttling_resource_handler.h"
#include "content/browser/loader/upload_data_stream_builder.h"
-#include "content/browser/loader/wake_lock_resource_throttle.h"
#include "content/browser/resource_context_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
@@ -112,11 +110,11 @@
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "services/network/resource_scheduler.h"
+#include "services/network/throttling/scoped_throttling_token.h"
#include "services/network/url_loader_factory.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/blob_url_request_job_factory.h"
-#include "storage/browser/blob/shareable_file_reference.h"
#include "storage/browser/fileapi/file_permission_policy.h"
#include "storage/browser/fileapi/file_system_context.h"
#include "url/third_party/mozilla/url_parse.h"
@@ -171,12 +169,6 @@ void AbortRequestBeforeItStarts(
url_loader_client->OnComplete(status);
}
-void RemoveDownloadFileFromChildSecurityPolicy(int child_id,
- const base::FilePath& path) {
- ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile(
- child_id, path);
-}
-
bool IsValidatedSCT(
const net::SignedCertificateTimestampAndStatus& sct_status) {
return sct_status.status == net::ct::SCT_STATUS_OK;
@@ -193,6 +185,7 @@ PreviewsState DetermineEnabledPreviews(PreviewsState previews_to_allow,
net::URLRequest* request,
ResourceContext* resource_context,
bool is_main_frame) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
// If previews have already been turned off, or we are inheriting values on a
// sub-frame, don't check any further.
if (previews_to_allow & PREVIEWS_OFF ||
@@ -324,8 +317,6 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl(
max_num_in_flight_requests_ * kMaxRequestsPerProcessRatio)),
max_outstanding_requests_cost_per_process_(
kMaxOutstandingRequestsCostPerProcess),
- largest_outstanding_request_count_seen_(0),
- largest_outstanding_request_per_process_count_seen_(0),
delegate_(nullptr),
loader_delegate_(nullptr),
allow_cross_origin_auth_prompt_(false),
@@ -557,7 +548,8 @@ scoped_refptr<LoginDelegate> ResourceDispatcherHostImpl::CreateLoginDelegate(
scoped_refptr<LoginDelegate> login_delegate =
GetContentClient()->browser()->CreateLoginDelegate(
auth_info, resource_request_info->GetWebContentsGetterForRequest(),
- is_request_for_main_frame, url,
+ request_id, is_request_for_main_frame, url,
+ request->response_headers(),
resource_request_info->first_auth_attempt(),
base::BindOnce(&ResourceDispatcherHostImpl::RunAuthRequiredCallback,
base::Unretained(this), request_id));
@@ -606,13 +598,6 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(
network::ResourceResponse* response) {
ResourceRequestInfoImpl* info = loader->GetRequestInfo();
net::URLRequest* request = loader->request();
- if (request->was_fetched_via_proxy() &&
- request->was_fetched_via_spdy() &&
- request->url().SchemeIs(url::kHttpScheme)) {
- scheduler_->OnReceivedSpdyProxiedHttpResponse(
- info->GetChildID(), info->GetRouteID());
- }
-
if (delegate_)
delegate_->OnResponseStarted(request, info->GetContext(), response);
}
@@ -620,39 +605,9 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(
void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
ResourceRequestInfoImpl* info = loader->GetRequestInfo();
- base::TimeDelta request_loading_time(base::TimeTicks::Now() -
- loader->request()->creation_time());
-
// Record final result of all resource loads.
if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME) {
- // This enumeration has "3" appended to its name to distinguish it from
- // older versions.
- base::UmaHistogramSparse("Net.ErrorCodesForMainFrame3",
- -loader->request()->status().error());
- if (loader->request()->status().error() == net::OK) {
- UMA_HISTOGRAM_LONG_TIMES("Net.RequestTime2Success.MainFrame",
- request_loading_time);
- }
- if (loader->request()->status().error() == net::ERR_ABORTED) {
- UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ErrAborted.SentBytes",
- loader->request()->GetTotalSentBytes(), 1,
- 50000000, 50);
- UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ErrAborted.ReceivedBytes",
- loader->request()->GetTotalReceivedBytes(), 1,
- 50000000, 50);
- }
-
if (loader->request()->url().SchemeIsCryptographic()) {
- if (loader->request()->url().host_piece() == "www.google.com") {
- base::UmaHistogramSparse("Net.ErrorCodesForHTTPSGoogleMainFrame2",
- -loader->request()->status().error());
- }
-
- if (net::IsTLS13ExperimentHost(loader->request()->url().host_piece())) {
- base::UmaHistogramSparse("Net.ErrorCodesForTLS13ExperimentMainFrame",
- -loader->request()->status().error());
- }
-
int num_valid_scts = std::count_if(
loader->request()->ssl_info().signed_certificate_timestamps.begin(),
loader->request()->ssl_info().signed_certificate_timestamps.end(),
@@ -660,18 +615,6 @@ void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
UMA_HISTOGRAM_COUNTS_100(
"Net.CertificateTransparency.MainFrameValidSCTCount", num_valid_scts);
}
- } else {
- if (loader->request()->status().error() == net::OK) {
- UMA_HISTOGRAM_LONG_TIMES("Net.RequestTime2Success.Subresource",
- request_loading_time);
- }
- if (info->GetResourceType() == RESOURCE_TYPE_IMAGE) {
- base::UmaHistogramSparse("Net.ErrorCodesForImages",
- -loader->request()->status().error());
- }
- // This enumeration has "2" appended to distinguish it from older versions.
- base::UmaHistogramSparse("Net.ErrorCodesForSubresources2",
- -loader->request()->status().error());
}
if (delegate_)
@@ -725,6 +668,7 @@ void ResourceDispatcherHostImpl::OnRequestResourceInternal(
int request_id,
bool is_sync_load,
const network::ResourceRequest& request_data,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
@@ -732,7 +676,7 @@ void ResourceDispatcherHostImpl::OnRequestResourceInternal(
requester_info->IsNavigationPreload() ||
requester_info->IsCertificateFetcherForSignedExchange());
BeginRequest(requester_info, request_id, request_data, is_sync_load,
- routing_id, std::move(mojo_request),
+ routing_id, url_loader_options, std::move(mojo_request),
std::move(url_loader_client), traffic_annotation);
}
@@ -756,6 +700,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
const network::ResourceRequest& request_data,
bool is_sync_load,
int route_id,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
@@ -862,7 +807,8 @@ void ResourceDispatcherHostImpl::BeginRequest(
&ResourceDispatcherHostImpl::ContinuePendingBeginRequest,
base::Unretained(this), base::WrapRefCounted(requester_info),
request_id, request_data, is_sync_load, route_id,
- request_data.headers, base::Passed(std::move(mojo_request)),
+ request_data.headers, url_loader_options,
+ base::Passed(std::move(mojo_request)),
base::Passed(std::move(url_loader_client)),
base::Passed(std::move(blob_handles)), traffic_annotation));
return;
@@ -871,7 +817,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
}
ContinuePendingBeginRequest(
requester_info, request_id, request_data, is_sync_load, route_id,
- request_data.headers, std::move(mojo_request),
+ request_data.headers, url_loader_options, std::move(mojo_request),
std::move(url_loader_client), std::move(blob_handles), traffic_annotation,
HeaderInterceptorResult::CONTINUE);
}
@@ -883,6 +829,7 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
bool is_sync_load,
int route_id,
const net::HttpRequestHeaders& headers,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
BlobHandles blob_handles,
@@ -948,6 +895,7 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
new_request->set_site_for_cookies(request_data.site_for_cookies);
new_request->set_attach_same_site_cookies(
request_data.attach_same_site_cookies);
+ new_request->set_upgrade_if_insecure(request_data.upgrade_if_insecure);
// The initiator should normally be present, unless this is a navigation.
// Browser-initiated navigations don't have an initiator document, the
@@ -967,6 +915,11 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
new_request->SetExtraRequestHeaders(headers);
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token =
+ network::ScopedThrottlingToken::MaybeCreate(
+ new_request->net_log().source().id,
+ request_data.throttling_profile_id);
+
blob_context = GetBlobStorageContext(requester_info->blob_storage_context());
// Resolve elements from request_body and prepare upload data.
if (request_data.request_body.get()) {
@@ -1096,7 +1049,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
std::unique_ptr<ResourceHandler> handler = CreateResourceHandler(
requester_info.get(), new_request.get(), request_data, route_id, child_id,
- resource_context, std::move(mojo_request), std::move(url_loader_client));
+ resource_context, url_loader_options, std::move(mojo_request),
+ std::move(url_loader_client));
if (handler) {
RecordFetchRequestMode(request_data.url, request_data.method,
@@ -1104,7 +1058,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
const bool is_initiated_by_fetch_api =
request_data.fetch_request_context_type == REQUEST_CONTEXT_TYPE_FETCH;
BeginRequestInternal(std::move(new_request), std::move(handler),
- is_initiated_by_fetch_api);
+ is_initiated_by_fetch_api,
+ std::move(throttling_token));
}
}
@@ -1116,6 +1071,7 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
int route_id,
int child_id,
ResourceContext* resource_context,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client) {
DCHECK(requester_info->IsRenderer() ||
@@ -1124,15 +1080,10 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
// Construct the IPC resource handler.
std::unique_ptr<ResourceHandler> handler;
handler = CreateBaseResourceHandler(
- request, std::move(mojo_request), std::move(url_loader_client),
+ request, url_loader_options, std::move(mojo_request),
+ std::move(url_loader_client),
static_cast<ResourceType>(request_data.resource_type));
- // The RedirectToFileResourceHandler depends on being next in the chain.
- if (request_data.download_to_file) {
- handler.reset(
- new RedirectToFileResourceHandler(std::move(handler), request));
- }
-
// Prefetches outlive their child process.
if (request_data.resource_type == RESOURCE_TYPE_PREFETCH) {
auto detachable_handler = std::make_unique<DetachableResourceHandler>(
@@ -1153,13 +1104,14 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
std::unique_ptr<ResourceHandler>
ResourceDispatcherHostImpl::CreateBaseResourceHandler(
net::URLRequest* request,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
ResourceType resource_type) {
std::unique_ptr<ResourceHandler> handler;
handler.reset(new MojoAsyncResourceHandler(
request, this, std::move(mojo_request), std::move(url_loader_client),
- resource_type, network::mojom::kURLLoadOptionNone));
+ resource_type, url_loader_options));
return handler;
}
@@ -1191,12 +1143,6 @@ ResourceDispatcherHostImpl::AddStandardHandlers(
&throttles);
}
- if (request->has_upload()) {
- // Request wake lock while uploading data.
- throttles.push_back(
- std::make_unique<WakeLockResourceThrottle>(request->url().host()));
- }
-
// The Clear-Site-Data throttle.
std::unique_ptr<ResourceThrottle> clear_site_data_throttle =
ClearSiteDataThrottle::MaybeCreateThrottleForRequest(request);
@@ -1255,41 +1201,6 @@ ResourceDispatcherHostImpl::AddStandardHandlers(
return handler;
}
-void ResourceDispatcherHostImpl::RegisterDownloadedTempFile(
- int child_id, int request_id, const base::FilePath& file_path) {
- scoped_refptr<ShareableFileReference> reference =
- ShareableFileReference::Get(file_path);
- DCHECK(reference.get());
-
- registered_temp_files_[child_id][request_id] = reference;
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
- child_id, reference->path());
-
- // When the temp file is deleted, revoke permissions that the renderer has
- // to that file. This covers an edge case where the file is deleted and then
- // the same name is re-used for some other purpose, we don't want the old
- // renderer to still have access to it.
- //
- // We do this when the file is deleted because the renderer can take a blob
- // reference to the temp file that outlives the url loaded that it was
- // loaded with to keep the file (and permissions) alive.
- reference->AddFinalReleaseCallback(
- base::BindOnce(&RemoveDownloadFileFromChildSecurityPolicy, child_id));
-}
-
-void ResourceDispatcherHostImpl::UnregisterDownloadedTempFile(
- int child_id, int request_id) {
- DeletableFilesMap& map = registered_temp_files_[child_id];
- DeletableFilesMap::iterator found = map.find(request_id);
- if (found == map.end())
- return;
-
- map.erase(found);
-
- // Note that we don't remove the security bits here. This will be done
- // when all file refs are deleted (see RegisterDownloadedTempFile).
-}
-
ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
int child_id,
int render_view_route_id,
@@ -1353,7 +1264,6 @@ void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) {
const auto& map = keepalive_statistics_recorder_.per_process_records();
if (map.find(child_id) != map.end())
keepalive_statistics_recorder_.Unregister(child_id);
- registered_temp_files_.erase(child_id);
}
void ResourceDispatcherHostImpl::CancelRequestsForRoute(
@@ -1523,21 +1433,6 @@ ResourceDispatcherHostImpl::IncrementOutstandingRequestsCount(
DCHECK_GE(stats.num_requests, 0);
UpdateOutstandingRequestsStats(*info, stats);
- if (num_in_flight_requests_ > largest_outstanding_request_count_seen_) {
- largest_outstanding_request_count_seen_ = num_in_flight_requests_;
- UMA_HISTOGRAM_COUNTS_1M(
- "Net.ResourceDispatcherHost.OutstandingRequests.Total",
- largest_outstanding_request_count_seen_);
- }
-
- if (stats.num_requests >
- largest_outstanding_request_per_process_count_seen_) {
- largest_outstanding_request_per_process_count_seen_ = stats.num_requests;
- UMA_HISTOGRAM_COUNTS_1M(
- "Net.ResourceDispatcherHost.OutstandingRequests.PerProcess",
- largest_outstanding_request_per_process_count_seen_);
- }
-
return stats;
}
@@ -1571,11 +1466,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
ServiceWorkerNavigationHandleCore* service_worker_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
uint32_t url_loader_options,
- GlobalRequestID* global_request_id) {
- // PlzNavigate: BeginNavigationRequest currently should only be used for the
- // browser-side navigations project.
- CHECK(IsBrowserSideNavigationEnabled());
-
+ const GlobalRequestID& global_request_id) {
DCHECK(url_loader_client.is_bound());
DCHECK(url_loader_request.is_pending());
@@ -1623,11 +1514,16 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
new_request->set_method(info.common_params.method);
new_request->set_site_for_cookies(info.site_for_cookies);
new_request->set_initiator(info.begin_params->initiator_origin);
+ new_request->set_upgrade_if_insecure(info.upgrade_if_insecure);
if (info.is_main_frame) {
new_request->set_first_party_url_policy(
net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT);
}
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token =
+ network::ScopedThrottlingToken::MaybeCreate(
+ new_request->net_log().source().id, info.devtools_frame_token);
+
Referrer::SetReferrerForRequest(new_request.get(),
info.common_params.referrer);
@@ -1684,7 +1580,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
-1, // route_id
info.frame_tree_node_id,
ChildProcessHost::kInvalidUniqueID, // plugin_child_id
- MakeRequestID(),
+ global_request_id.request_id,
-1, // request_data.render_frame_id,
info.is_main_frame, resource_type, info.common_params.transition,
false, // is download
@@ -1713,8 +1609,6 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
// Request takes ownership.
extra_info->AssociateWithRequest(new_request.get());
- *global_request_id = extra_info->GetGlobalRequestID();
-
if (new_request->url().SchemeIs(url::kBlobScheme)) {
// Hang on to a reference to ensure the blob is not released prior
// to the job being started.
@@ -1760,7 +1654,8 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
RecordFetchRequestMode(new_request->url(), new_request->method(),
network::mojom::FetchRequestMode::kNavigate);
BeginRequestInternal(std::move(new_request), std::move(handler),
- false /* is_initiated_by_fetch_api */);
+ false /* is_initiated_by_fetch_api */,
+ std::move(throttling_token));
}
void ResourceDispatcherHostImpl::SetLoaderDelegate(
@@ -1782,8 +1677,6 @@ void ResourceDispatcherHostImpl::OnRequestResourceWithMojo(
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
- DCHECK_EQ(network::mojom::kURLLoadOptionNone,
- options & ~network::mojom::kURLLoadOptionSynchronous);
if (!url_loader_client) {
VLOG(1) << "Killed renderer for null client";
bad_message::ReceivedBadMessage(requester_info->filter(),
@@ -1792,7 +1685,8 @@ void ResourceDispatcherHostImpl::OnRequestResourceWithMojo(
}
bool is_sync_load = options & network::mojom::kURLLoadOptionSynchronous;
OnRequestResourceInternal(requester_info, routing_id, request_id,
- is_sync_load, request, std::move(mojo_request),
+ is_sync_load, request, options,
+ std::move(mojo_request),
std::move(url_loader_client), traffic_annotation);
}
@@ -1819,7 +1713,8 @@ int ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(
void ResourceDispatcherHostImpl::BeginRequestInternal(
std::unique_ptr<net::URLRequest> request,
std::unique_ptr<ResourceHandler> handler,
- bool is_initiated_by_fetch_api) {
+ bool is_initiated_by_fetch_api,
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token) {
DCHECK(!request->is_pending());
ResourceRequestInfoImpl* info =
ResourceRequestInfoImpl::ForRequest(request.get());
@@ -1895,8 +1790,9 @@ void ResourceDispatcherHostImpl::BeginRequestInternal(
}
ResourceContext* resource_context = info->GetContext();
- std::unique_ptr<ResourceLoader> loader(new ResourceLoader(
- std::move(request), std::move(handler), this, resource_context));
+ std::unique_ptr<ResourceLoader> loader(
+ new ResourceLoader(std::move(request), std::move(handler), this,
+ resource_context, std::move(throttling_token)));
GlobalFrameRoutingId id(info->GetChildID(), info->GetRenderFrameID());
BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.find(id);
@@ -1966,7 +1862,8 @@ void ResourceDispatcherHostImpl::BeginURLRequest(
true /* force_download */, true /* is_new_request */);
}
BeginRequestInternal(std::move(request), std::move(handler),
- false /* is_initiated_by_fetch_api */);
+ false /* is_initiated_by_fetch_api */,
+ nullptr /* throttling_token */);
}
int ResourceDispatcherHostImpl::MakeRequestID() {
@@ -1974,6 +1871,10 @@ int ResourceDispatcherHostImpl::MakeRequestID() {
return --request_id_;
}
+GlobalRequestID ResourceDispatcherHostImpl::MakeGlobalRequestID() {
+ return GlobalRequestID(ChildProcessHost::kInvalidUniqueID, MakeRequestID());
+}
+
void ResourceDispatcherHostImpl::CancelRequestFromRenderer(
GlobalRequestID request_id) {
ResourceLoader* loader = GetLoader(request_id);
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index 388f7f84a00..b8a81809fff 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -47,7 +47,6 @@
#include "url/gurl.h"
namespace base {
-class FilePath;
class OneShotTimer;
}
@@ -59,11 +58,11 @@ class URLRequestContextGetter;
namespace network {
class ResourceScheduler;
+class ScopedThrottlingToken;
} // namespace network
namespace storage {
class FileSystemContext;
-class ShareableFileReference;
}
namespace content {
@@ -182,15 +181,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
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
- // child process and to defer deletion of the file until it's
- // no longer needed.
- void RegisterDownloadedTempFile(
- int child_id, int request_id,
- const base::FilePath& file_path);
- void UnregisterDownloadedTempFile(int child_id, int request_id);
-
// Indicates whether third-party sub-content can pop-up HTTP basic auth
// dialog boxes.
bool allow_cross_origin_auth_prompt();
@@ -240,9 +230,8 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void FinishedWithResourcesForRequest(net::URLRequest* request);
// PlzNavigate: Begins a request for NavigationURLLoader. |loader| is the
- // loader to attach to the leaf resource handler.
- // After calling this function, |global_request_id| will contains the
- // request's global id.
+ // loader to attach to the leaf resource handler. |global_request_id| needs to
+ // be created by MakeGlobalRequestID() before calling this method.
void BeginNavigationRequest(
ResourceContext* resource_context,
net::URLRequestContext* request_context,
@@ -254,7 +243,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
ServiceWorkerNavigationHandleCore* service_worker_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
uint32_t url_loader_options,
- GlobalRequestID* global_request_id);
+ const GlobalRequestID& global_request_id);
int num_in_flight_requests_for_testing() const {
return num_in_flight_requests_;
@@ -311,6 +300,11 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// of |request_id_| for the details. Must be called on the IO thread.
int MakeRequestID();
+ // Creates a new global request ID for browser initiated requests. The ID
+ // is consistent with the request id created by MakeRequestID(). Must be
+ // called on the IO thread.
+ GlobalRequestID MakeGlobalRequestID();
+
// Cancels a request as requested by a renderer. This function is called when
// a mojo connection is lost.
// Note that this cancel is subtly different from the other CancelRequest
@@ -420,9 +414,11 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void OnShutdown();
// Helper function for URL requests.
- void BeginRequestInternal(std::unique_ptr<net::URLRequest> request,
- std::unique_ptr<ResourceHandler> handler,
- bool is_initiated_by_fetch_api);
+ void BeginRequestInternal(
+ std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceHandler> handler,
+ bool is_initiated_by_fetch_api,
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token);
void StartLoading(ResourceRequestInfoImpl* info,
std::unique_ptr<ResourceLoader> loader);
@@ -539,6 +535,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int request_id,
bool is_sync_load,
const network::ResourceRequest& request_data,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
@@ -550,6 +547,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
const network::ResourceRequest& request_data,
bool is_sync_load,
int route_id,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
@@ -569,6 +567,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
bool is_sync_load,
int route_id,
const net::HttpRequestHeaders& headers,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
BlobHandles blob_handles,
@@ -584,12 +583,14 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int route_id,
int child_id,
ResourceContext* resource_context,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client);
// Creates either MojoAsyncResourceHandler or AsyncResourceHandler.
std::unique_ptr<ResourceHandler> CreateBaseResourceHandler(
net::URLRequest* request,
+ uint32_t url_loader_options,
network::mojom::URLLoaderRequest mojo_request,
network::mojom::URLLoaderClientPtr url_loader_client,
ResourceType resource_type);
@@ -667,15 +668,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
LoaderMap pending_loaders_;
- // Collection of temp files downloaded for child processes via
- // the download_to_file mechanism. We avoid deleting them until
- // the client no longer needs them.
- typedef std::map<int, scoped_refptr<storage::ShareableFileReference> >
- DeletableFilesMap; // key is request id
- typedef std::map<int, DeletableFilesMap>
- RegisteredTempFiles; // key is child process id
- RegisteredTempFiles registered_temp_files_;
-
// A timer that periodically calls UpdateLoadInfo while |pending_loaders_| is
// not empty, at least one RenderViewHost is loading, and not waiting on an
// ACK from the UI thread for the last sent LoadInfoList.
@@ -733,12 +725,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// kAvgBytesPerOutstandingRequest)
int max_outstanding_requests_cost_per_process_;
- // Largest number of outstanding requests seen so far across all processes.
- int largest_outstanding_request_count_seen_;
-
- // Largest number of outstanding requests seen so far in any single process.
- int largest_outstanding_request_per_process_count_seen_;
-
// Time of the last user gesture. Stored so that we can add a load
// flag to requests occurring soon after a gesture to indicate they
// may be because of explicit user action.
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index e576ad75157..d8d744e64ff 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -27,7 +27,6 @@
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/detachable_resource_handler.h"
-#include "content/browser/loader/downloaded_temp_file_impl.h"
#include "content/browser/loader/navigation_url_loader.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_loader.h"
@@ -78,6 +77,8 @@
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/public/cpp/resource_request.h"
+#include "services/network/resource_scheduler.h"
+#include "services/network/resource_scheduler_params_manager.h"
#include "services/network/test/test_url_loader_client.h"
#include "storage/browser/blob/shareable_file_reference.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -104,7 +105,6 @@ static network::ResourceRequest CreateResourceRequest(const char* method,
request.plugin_child_id = -1;
request.resource_type = type;
request.appcache_host_id = kAppCacheNoHostId;
- request.download_to_file = false;
request.should_reset_appcache = false;
request.is_main_frame = true;
request.transition_type = ui::PAGE_TRANSITION_LINK;
@@ -818,7 +818,9 @@ class ResourceDispatcherHostTest : public testing::Test {
std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo(common_params, std::move(begin_params), url,
true, false, false, -1, false, false, false,
- nullptr, base::UnguessableToken::Create()));
+ false, nullptr,
+ base::UnguessableToken::Create(),
+ base::UnguessableToken::Create()));
std::unique_ptr<NavigationURLLoader> test_loader =
NavigationURLLoader::Create(
browser_context_->GetResourceContext(),
@@ -838,6 +840,18 @@ class ResourceDispatcherHostTest : public testing::Test {
request_info->detachable_handler()->is_detached();
}
+ void SetMaxDelayableRequests(size_t max_delayable_requests) {
+ network::ResourceSchedulerParamsManager::ParamsForNetworkQualityContainer c;
+ for (int i = 0; i != net::EFFECTIVE_CONNECTION_TYPE_LAST; ++i) {
+ auto type = static_cast<net::EffectiveConnectionType>(i);
+ c[type] =
+ network::ResourceSchedulerParamsManager::ParamsForNetworkQuality(
+ max_delayable_requests, 0.0, false);
+ }
+ host_.scheduler()->SetResourceSchedulerParamsManagerForTests(
+ network::ResourceSchedulerParamsManager(c));
+ }
+
content::TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<TestBrowserContext> browser_context_;
std::unique_ptr<TestURLRequestJobFactory> job_factory_;
@@ -1467,6 +1481,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsOnRenderFrameDeleted) {
host_.SetDelegate(&delegate);
host_.OnRenderViewHostCreated(filter_->child_id(), 0,
request_context_getter_.get());
+ SetMaxDelayableRequests(1);
// One RenderView issues a high priority request and a low priority one. Both
// should be started.
@@ -2208,138 +2223,6 @@ TEST_F(ResourceDispatcherHostTest, DataSentBeforeDetach) {
EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
}
-// Tests the dispatcher host's temporary file management in the mojo-enabled
-// loading.
-TEST_F(ResourceDispatcherHostTest, RegisterDownloadedTempFileWithMojo) {
- const int kRequestID = 1;
-
- // Create a temporary file.
- base::FilePath file_path;
- ASSERT_TRUE(base::CreateTemporaryFile(&file_path));
- EXPECT_TRUE(base::PathExists(file_path));
- scoped_refptr<ShareableFileReference> deletable_file =
- ShareableFileReference::GetOrCreate(
- file_path, ShareableFileReference::DELETE_ON_FINAL_RELEASE,
- base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()})
- .get());
-
- // Not readable.
- EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
-
- // Register it for a resource request.
- auto downloaded_file =
- DownloadedTempFileImpl::Create(filter_->child_id(), kRequestID);
- network::mojom::DownloadedTempFilePtr downloaded_file_ptr =
- DownloadedTempFileImpl::Create(filter_->child_id(), kRequestID);
- host_.RegisterDownloadedTempFile(filter_->child_id(), kRequestID, file_path);
-
- // Should be readable now.
- EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
-
- // The child releases from the request.
- downloaded_file_ptr = nullptr;
- content::RunAllTasksUntilIdle();
-
- // Still readable because there is another reference to the file. (The child
- // may take additional blob references.)
- EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
-
- // Release extra references and wait for the file to be deleted. (This relies
- // on the delete happening on the FILE thread which is mapped to main thread
- // in this test.)
- deletable_file = nullptr;
- content::RunAllTasksUntilIdle();
-
- // The file is no longer readable to the child and has been deleted.
- EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
- EXPECT_FALSE(base::PathExists(file_path));
-}
-
-// Tests that temporary files held on behalf of child processes are released
-// when the child process dies.
-TEST_F(ResourceDispatcherHostTest, ReleaseTemporiesOnProcessExit) {
- const int kRequestID = 1;
-
- // Create a temporary file.
- base::FilePath file_path;
- ASSERT_TRUE(base::CreateTemporaryFile(&file_path));
- scoped_refptr<ShareableFileReference> deletable_file =
- ShareableFileReference::GetOrCreate(
- file_path, ShareableFileReference::DELETE_ON_FINAL_RELEASE,
- base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()})
- .get());
-
- // Register it for a resource request.
- host_.RegisterDownloadedTempFile(filter_->child_id(), kRequestID, file_path);
- deletable_file = nullptr;
-
- // Should be readable now.
- EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
-
- // Let the process die.
- filter_->OnChannelClosing();
- content::RunAllTasksUntilIdle();
-
- // The file is no longer readable to the child and has been deleted.
- EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), file_path));
- EXPECT_FALSE(base::PathExists(file_path));
-}
-
-TEST_F(ResourceDispatcherHostTest, DownloadToFile) {
- // Make a request which downloads to file.
- network::mojom::URLLoaderPtr loader;
- network::TestURLLoaderClient client;
- network::ResourceRequest request = CreateResourceRequest(
- "GET", RESOURCE_TYPE_SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
- request.download_to_file = true;
- filter_->CreateLoaderAndStart(
- mojo::MakeRequest(&loader), 0, 1, network::mojom::kURLLoadOptionNone,
- request, client.CreateInterfacePtr(),
- net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
- content::RunAllTasksUntilIdle();
-
- // The request should contain the following messages:
- // ReceivedResponse (indicates headers received and filename)
- // DataDownloaded* (bytes downloaded and total length)
- // RequestComplete (request is done)
- client.RunUntilComplete();
- EXPECT_FALSE(client.response_head().download_file_path.empty());
- EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(),
- static_cast<size_t>(client.download_data_length()));
- EXPECT_EQ(net::OK, client.completion_status().error_code);
-
- // Verify that the data ended up in the temporary file.
- std::string contents;
- ASSERT_TRUE(base::ReadFileToString(client.response_head().download_file_path,
- &contents));
- EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents);
-
- // The file should be readable by the child.
- EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), client.response_head().download_file_path));
-
- // When the renderer releases the file, it should be deleted.
- // RunUntilIdle doesn't work because base::WorkerPool is involved.
- ShareableFileReleaseWaiter waiter(client.response_head().download_file_path);
- client.TakeDownloadedTempFile();
- content::RunAllTasksUntilIdle();
- waiter.Wait();
- // The release callback runs before the delete is scheduled, so pump the
- // message loop for the delete itself. (This relies on the delete happening on
- // the FILE thread which is mapped to main thread in this test.)
- content::RunAllTasksUntilIdle();
-
- EXPECT_FALSE(base::PathExists(client.response_head().download_file_path));
- EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
- filter_->child_id(), client.response_head().download_file_path));
-}
-
WebContents* WebContentsBinder(WebContents* rv) { return rv; }
// Tests GetLoadInfoForAllRoutes when there are 3 requests from the same
diff --git a/chromium/content/browser/loader/resource_handler.cc b/chromium/content/browser/loader/resource_handler.cc
index a507567e950..c58d7641e4d 100644
--- a/chromium/content/browser/loader/resource_handler.cc
+++ b/chromium/content/browser/loader/resource_handler.cc
@@ -44,6 +44,11 @@ void ResourceHandler::Resume() {
ReleaseController()->Resume();
}
+void ResourceHandler::ResumeForRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
+ ReleaseController()->ResumeForRedirect(modified_request_headers);
+}
+
void ResourceHandler::Cancel() {
ReleaseController()->Cancel();
}
diff --git a/chromium/content/browser/loader/resource_handler.h b/chromium/content/browser/loader/resource_handler.h
index b9b6ebf554d..bb60dbe0d97 100644
--- a/chromium/content/browser/loader/resource_handler.h
+++ b/chromium/content/browser/loader/resource_handler.h
@@ -138,12 +138,6 @@ class CONTENT_EXPORT ResourceHandler {
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) = 0;
- // This notification is synthesized by the RedirectToFileResourceHandler
- // to indicate progress of 'download_to_file' requests. OnReadCompleted
- // calls are consumed by the RedirectToFileResourceHandler and replaced
- // with OnDataDownloaded calls.
- virtual void OnDataDownloaded(int bytes_downloaded) = 0;
-
protected:
explicit ResourceHandler(net::URLRequest* request);
@@ -165,6 +159,8 @@ class CONTENT_EXPORT ResourceHandler {
// These call the corresponding methods on the ResourceController previously
// passed to HoldController and then destroy it.
void Resume();
+ void ResumeForRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers);
void Cancel();
void CancelWithError(int error_code);
diff --git a/chromium/content/browser/loader/resource_hints_impl.cc b/chromium/content/browser/loader/resource_hints_impl.cc
index 6365bc19995..3ebe0570196 100644
--- a/chromium/content/browser/loader/resource_hints_impl.cc
+++ b/chromium/content/browser/loader/resource_hints_impl.cc
@@ -6,11 +6,10 @@
#include "base/memory/ref_counted.h"
#include "base/trace_event/trace_event.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_hints.h"
#include "net/base/address_list.h"
#include "net/base/load_flags.h"
-#include "net/dns/host_resolver.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_info.h"
#include "net/http/http_stream_factory.h"
@@ -24,18 +23,7 @@ namespace content {
namespace {
-class RequestHolder {
- public:
- std::unique_ptr<net::HostResolver::Request>* GetRequest() {
- return &request_;
- }
-
- private:
- std::unique_ptr<net::HostResolver::Request> request_;
-};
-
-void OnResolveComplete(std::unique_ptr<RequestHolder> request_holder,
- std::unique_ptr<net::AddressList> addresses,
+void OnResolveComplete(std::unique_ptr<net::AddressList> addresses,
const net::CompletionCallback& callback,
int result) {
// Plumb the resolution result into the callback if future consumers want
@@ -50,9 +38,7 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
const GURL& site_for_cookies,
int count,
bool allow_credentials) {
- DCHECK(ResourceDispatcherHostImpl::Get()
- ->io_thread_task_runner()
- ->BelongsToCurrentThread());
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(getter);
TRACE_EVENT2("net", "PreconnectUrl", "url", url.spec(), "count", count);
@@ -74,6 +60,9 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
user_agent);
net::NetworkDelegate* delegate = request_context->network_delegate();
+ // NetworkDelegate is not set in tests.
+ if (!delegate)
+ return;
if (delegate->CanEnablePrivacyMode(url, site_for_cookies))
request_info.privacy_mode = net::PRIVACY_MODE_ENABLED;
@@ -93,10 +82,9 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
int PreresolveUrl(net::URLRequestContextGetter* getter,
const GURL& url,
- const net::CompletionCallback& callback) {
- DCHECK(ResourceDispatcherHostImpl::Get()
- ->io_thread_task_runner()
- ->BelongsToCurrentThread());
+ const net::CompletionCallback& callback,
+ std::unique_ptr<net::HostResolver::Request>* out_request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(getter);
TRACE_EVENT1("net", "PreresolveUrl", "url", url.spec());
@@ -104,21 +92,17 @@ int PreresolveUrl(net::URLRequestContextGetter* getter,
if (!request_context)
return net::ERR_CONTEXT_SHUT_DOWN;
- auto request_holder = std::make_unique<RequestHolder>();
auto addresses = std::make_unique<net::AddressList>();
- // Save raw pointers before the unique_ptr is invalidated by base::Passed.
+ // Save raw pointers before the unique_ptr is invalidated by base::Passed().
net::AddressList* raw_addresses = addresses.get();
- std::unique_ptr<net::HostResolver::Request>* out_request =
- request_holder->GetRequest();
net::HostResolver* resolver = request_context->host_resolver();
net::HostResolver::RequestInfo resolve_info(net::HostPortPair::FromURL(url));
resolve_info.set_is_speculative(true);
return resolver->Resolve(
resolve_info, net::IDLE, raw_addresses,
- base::Bind(&OnResolveComplete, base::Passed(&request_holder),
- base::Passed(&addresses), callback),
+ base::Bind(&OnResolveComplete, base::Passed(&addresses), callback),
out_request, net::NetLogWithSource());
}
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index c06232582ab..2435233851b 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -43,6 +43,7 @@
#include "net/url_request/url_request_status.h"
#include "services/network/loader_util.h"
#include "services/network/public/cpp/resource_response.h"
+#include "services/network/throttling/scoped_throttling_token.h"
#include "url/url_constants.h"
using base::TimeDelta;
@@ -84,6 +85,8 @@ void PopulateResourceResponse(
response->head.socket_address = response_info.socket_address;
response->head.was_fetched_via_proxy = request->was_fetched_via_proxy();
response->head.network_accessed = response_info.network_accessed;
+ response->head.async_revalidation_requested =
+ response_info.async_revalidation_requested;
const content::ResourceRequestInfo* request_info =
content::ResourceRequestInfo::ForRequest(request);
if (request_info) {
@@ -152,7 +155,15 @@ class ResourceLoader::Controller : public ResourceController {
// ResourceController implementation:
void Resume() override {
MarkAsUsed();
- resource_loader_->Resume(true /* called_from_resource_controller */);
+ resource_loader_->Resume(true /* called_from_resource_controller */,
+ base::nullopt);
+ }
+
+ void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ MarkAsUsed();
+ resource_loader_->Resume(true /* called_from_resource_controller */,
+ modified_request_headers);
}
void Cancel() override {
@@ -209,7 +220,8 @@ class ResourceLoader::ScopedDeferral {
// If Resume() was called, it just advanced the state without doing
// anything. Go ahead and resume the request now.
if (old_deferred_stage == DEFERRED_NONE)
- resource_loader_->Resume(false /* called_from_resource_controller */);
+ resource_loader_->Resume(false /* called_from_resource_controller */,
+ base::nullopt);
}
private:
@@ -219,10 +231,12 @@ class ResourceLoader::ScopedDeferral {
DISALLOW_COPY_AND_ASSIGN(ScopedDeferral);
};
-ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request,
- std::unique_ptr<ResourceHandler> handler,
- ResourceLoaderDelegate* delegate,
- ResourceContext* resource_context)
+ResourceLoader::ResourceLoader(
+ std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceHandler> handler,
+ ResourceLoaderDelegate* delegate,
+ ResourceContext* resource_context,
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token)
: deferred_stage_(DEFERRED_NONE),
request_(std::move(request)),
handler_(std::move(handler)),
@@ -231,6 +245,7 @@ ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request,
started_request_(false),
times_cancelled_after_request_start_(0),
resource_context_(resource_context),
+ throttling_token_(std::move(throttling_token)),
weak_ptr_factory_(this) {
request_->set_delegate(this);
handler_->SetDelegate(this);
@@ -515,9 +530,13 @@ void ResourceLoader::CancelCertificateSelection() {
request_->CancelWithError(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
}
-void ResourceLoader::Resume(bool called_from_resource_controller) {
+void ResourceLoader::Resume(
+ bool called_from_resource_controller,
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DeferredStage stage = deferred_stage_;
deferred_stage_ = DEFERRED_NONE;
+ DCHECK(!modified_request_headers.has_value() || stage == DEFERRED_REDIRECT)
+ << "modified_request_headers can only be used with redirects";
switch (stage) {
case DEFERRED_NONE:
NOTREACHED();
@@ -536,7 +555,7 @@ void ResourceLoader::Resume(bool called_from_resource_controller) {
// URLRequest::Start completes asynchronously, so starting the request now
// won't result in synchronously calling into a ResourceHandler, if this
// was called from Resume().
- FollowDeferredRedirectInternal();
+ FollowDeferredRedirectInternal(modified_request_headers);
break;
case DEFERRED_ON_WILL_READ:
// Always post a task, as synchronous resumes don't go through this
@@ -611,8 +630,6 @@ void ResourceLoader::StartRequestInternal() {
request_->SetResponseHeadersCallback(base::Bind(
&ResourceLoader::SetRawResponseHeaders, base::Unretained(this)));
}
- UMA_HISTOGRAM_TIMES("Net.ResourceLoader.TimeToURLRequestStart",
- base::TimeTicks::Now() - request_->creation_time());
request_->Start();
delegate_->DidStartRequest(this);
@@ -664,14 +681,18 @@ void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
}
}
-void ResourceLoader::FollowDeferredRedirectInternal() {
+void ResourceLoader::FollowDeferredRedirectInternal(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DCHECK(!deferred_redirect_url_.is_empty());
GURL redirect_url = deferred_redirect_url_;
deferred_redirect_url_ = GURL();
if (delegate_->HandleExternalProtocol(this, redirect_url)) {
+ DCHECK(!modified_request_headers.has_value())
+ << "ResourceLoaderDelegate::HandleExternalProtocol() with modified "
+ "headers was not supported yet. crbug.com/845683";
Cancel();
} else {
- request_->FollowDeferredRedirect();
+ request_->FollowDeferredRedirect(modified_request_headers);
}
}
@@ -797,7 +818,6 @@ void ResourceLoader::ResponseCompleted() {
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
DVLOG(1) << "ResponseCompleted: " << request_->url().spec();
- RecordHistograms();
ScopedDeferral scoped_deferral(this, DEFERRED_FINISH);
handler_->OnResponseCompleted(request_->status(),
@@ -810,71 +830,6 @@ void ResourceLoader::CallDidFinishLoading() {
delegate_->DidFinishLoading(this);
}
-void ResourceLoader::RecordHistograms() {
- ResourceRequestInfoImpl* info = GetRequestInfo();
- if (request_->response_info().network_accessed) {
- if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME) {
- UMA_HISTOGRAM_ENUMERATION("Net.HttpResponseInfo.ConnectionInfo.MainFrame",
- request_->response_info().connection_info,
- net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS);
- } else {
- UMA_HISTOGRAM_ENUMERATION(
- "Net.HttpResponseInfo.ConnectionInfo.SubResource",
- request_->response_info().connection_info,
- net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS);
- }
- }
-
- if (request_->load_flags() & net::LOAD_PREFETCH) {
- // Note that RESOURCE_TYPE_PREFETCH requests are a subset of
- // net::LOAD_PREFETCH requests. In the histograms below, "Prefetch" means
- // RESOURCE_TYPE_PREFETCH and "LoadPrefetch" means net::LOAD_PREFETCH.
- bool is_resource_type_prefetch =
- info->GetResourceType() == RESOURCE_TYPE_PREFETCH;
- PrefetchStatus prefetch_status = STATUS_UNDEFINED;
- TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
-
- switch (request_->status().status()) {
- case net::URLRequestStatus::SUCCESS:
- if (request_->was_cached()) {
- prefetch_status = request_->response_info().unused_since_prefetch
- ? STATUS_SUCCESS_ALREADY_PREFETCHED
- : STATUS_SUCCESS_FROM_CACHE;
- if (is_resource_type_prefetch) {
- UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromCache",
- total_time);
- }
- } else {
- prefetch_status = STATUS_SUCCESS_FROM_NETWORK;
- if (is_resource_type_prefetch) {
- UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromNetwork",
- total_time);
- }
- }
- break;
- case net::URLRequestStatus::CANCELED:
- prefetch_status = STATUS_CANCELED;
- if (is_resource_type_prefetch)
- UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeBeforeCancel", total_time);
- break;
- case net::URLRequestStatus::IO_PENDING:
- case net::URLRequestStatus::FAILED:
- prefetch_status = STATUS_UNDEFINED;
- break;
- }
-
- UMA_HISTOGRAM_ENUMERATION("Net.LoadPrefetch.Pattern", prefetch_status,
- STATUS_MAX);
- if (is_resource_type_prefetch) {
- UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", prefetch_status,
- STATUS_MAX);
- }
- } else if (request_->response_info().unused_since_prefetch) {
- TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
- UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentOnPrefetchHit", total_time);
- }
-}
-
void ResourceLoader::SetRawResponseHeaders(
scoped_refptr<const net::HttpResponseHeaders> headers) {
raw_response_headers_ = headers;
diff --git a/chromium/content/browser/loader/resource_loader.h b/chromium/content/browser/loader/resource_loader.h
index 93ea0021af1..bbd241e28ed 100644
--- a/chromium/content/browser/loader/resource_loader.h
+++ b/chromium/content/browser/loader/resource_loader.h
@@ -25,6 +25,10 @@ class HttpResponseHeaders;
class X509Certificate;
}
+namespace network {
+class ScopedThrottlingToken;
+}
+
namespace content {
class LoginDelegate;
class ResourceHandler;
@@ -39,10 +43,12 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
public SSLClientAuthHandler::Delegate,
public ResourceHandler::Delegate {
public:
- ResourceLoader(std::unique_ptr<net::URLRequest> request,
- std::unique_ptr<ResourceHandler> handler,
- ResourceLoaderDelegate* delegate,
- ResourceContext* resource_context);
+ ResourceLoader(
+ std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceHandler> handler,
+ ResourceLoaderDelegate* delegate,
+ ResourceContext* resource_context,
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token);
~ResourceLoader() override;
void StartRequest();
@@ -92,14 +98,17 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
// |called_from_resource_controller| is true if called directly from a
// ResourceController, in which case |resource_handler_| must not be invoked
// or destroyed synchronously to avoid re-entrancy issues, and false
- // otherwise.
- void Resume(bool called_from_resource_controller);
+ // otherwise. |modified_request_headers| is used for redirects only.
+ void Resume(
+ bool called_from_resource_controller,
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers);
void Cancel();
void CancelWithError(int error_code);
void StartRequestInternal();
void CancelRequestInternal(int error, bool from_renderer);
- void FollowDeferredRedirectInternal();
+ void FollowDeferredRedirectInternal(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers);
void CompleteResponseStarted();
// If |handle_result_async| is true, the result of the following read will be
// handled asynchronously if it completes synchronously, unless it's EOF or an
@@ -112,7 +121,6 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
void CompleteRead(int bytes_read);
void ResponseCompleted();
void CallDidFinishLoading();
- void RecordHistograms();
void SetRawResponseHeaders(
scoped_refptr<const net::HttpResponseHeaders> headers);
@@ -177,6 +185,8 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
ResourceContext* resource_context_;
+ std::unique_ptr<network::ScopedThrottlingToken> throttling_token_;
+
bool should_pause_reading_body_ = false;
// The request is not deferred (i.e., DEFERRED_NONE) and is ready to read more
// response body data. However, reading is paused because of
diff --git a/chromium/content/browser/loader/resource_loader_unittest.cc b/chromium/content/browser/loader/resource_loader_unittest.cc
index 469e35d26be..aeae17a85e5 100644
--- a/chromium/content/browser/loader/resource_loader_unittest.cc
+++ b/chromium/content/browser/loader/resource_loader_unittest.cc
@@ -59,6 +59,7 @@
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/public/cpp/resource_response.h"
+#include "services/network/throttling/scoped_throttling_token.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -453,7 +454,7 @@ class ResourceLoaderTest : public testing::Test,
loader_.reset(new ResourceLoader(
std::move(request),
WrapResourceHandler(std::move(resource_handler), raw_ptr_to_request_),
- this, &resource_context_));
+ this, &resource_context_, nullptr /* throttling_token */));
}
void SetUpResourceLoaderForUrl(const GURL& test_url) {
diff --git a/chromium/content/browser/loader/resource_message_filter.cc b/chromium/content/browser/loader/resource_message_filter.cc
index 4a82566e296..2f531f5ae08 100644
--- a/chromium/content/browser/loader/resource_message_filter.cc
+++ b/chromium/content/browser/loader/resource_message_filter.cc
@@ -4,7 +4,7 @@
#include "content/browser/loader/resource_message_filter.h"
-#include "base/feature_list.h"
+#include "base/command_line.h"
#include "base/logging.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
@@ -18,9 +18,8 @@
#include "content/common/resource_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
-#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
#include "services/network/cors/cors_url_loader_factory.h"
-#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "storage/browser/fileapi/file_system_context.h"
@@ -146,6 +145,10 @@ void ResourceMessageFilter::CreateLoaderAndStart(
void ResourceMessageFilter::Clone(
network::mojom::URLLoaderFactoryRequest request) {
+ if (!url_loader_factory_) {
+ queued_clone_requests_.emplace_back(std::move(request));
+ return;
+ }
url_loader_factory_->Clone(std::move(request));
}
@@ -175,15 +178,19 @@ void ResourceMessageFilter::InitializeOnIOThread() {
// The WeakPtr of the filter must be created on the IO thread. So sets the
// WeakPtr of |requester_info_| now.
requester_info_->set_filter(GetWeakPtr());
- url_loader_factory_ = std::make_unique<URLLoaderFactoryImpl>(requester_info_);
-
- if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS)) {
- url_loader_factory_ = std::make_unique<network::cors::CORSURLLoaderFactory>(
- std::move(url_loader_factory_),
- base::BindRepeating(&ResourceDispatcherHostImpl::CancelRequest,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- requester_info_->child_id()));
- }
+ url_loader_factory_ = std::make_unique<network::cors::CORSURLLoaderFactory>(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity),
+ std::make_unique<URLLoaderFactoryImpl>(requester_info_),
+ base::BindRepeating(&ResourceDispatcherHostImpl::CancelRequest,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ requester_info_->child_id()));
+
+ std::vector<network::mojom::URLLoaderFactoryRequest> requests =
+ std::move(queued_clone_requests_);
+ for (auto& request : requests)
+ Clone(std::move(request));
+ queued_clone_requests_.clear();
}
} // namespace content
diff --git a/chromium/content/browser/loader/resource_message_filter.h b/chromium/content/browser/loader/resource_message_filter.h
index c8f2748aa4c..a0a5a0dc3cb 100644
--- a/chromium/content/browser/loader/resource_message_filter.h
+++ b/chromium/content/browser/loader/resource_message_filter.h
@@ -81,6 +81,7 @@ class CONTENT_EXPORT ResourceMessageFilter
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override;
+ // |request| could be queued when the channel has not been connected yet.
void Clone(network::mojom::URLLoaderFactoryRequest request) override;
int child_id() const;
@@ -116,6 +117,7 @@ class CONTENT_EXPORT ResourceMessageFilter
scoped_refptr<ResourceRequesterInfo> requester_info_;
std::unique_ptr<network::mojom::URLLoaderFactory> url_loader_factory_;
+ std::vector<network::mojom::URLLoaderFactoryRequest> queued_clone_requests_;
scoped_refptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index 651bf20c2c3..3db8fd33813 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -36,6 +36,11 @@ const void* const kResourceRequestInfoImplKey = &kResourceRequestInfoImplKey;
// ResourceRequestInfo
// static
+ResourceRequestInfo* ResourceRequestInfo::ForRequest(net::URLRequest* request) {
+ return ResourceRequestInfoImpl::ForRequest(request);
+}
+
+// static
const ResourceRequestInfo* ResourceRequestInfo::ForRequest(
const net::URLRequest* request) {
return ResourceRequestInfoImpl::ForRequest(request);
@@ -184,7 +189,8 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
previews_state_(previews_state),
body_(body),
initiated_in_secure_context_(initiated_in_secure_context),
- blocked_cross_site_document_(false),
+ blocked_response_from_reaching_renderer_(false),
+ should_report_corb_blocking_(false),
first_auth_attempt_(true) {}
ResourceRequestInfoImpl::~ResourceRequestInfoImpl() {
@@ -308,14 +314,6 @@ PreviewsState ResourceRequestInfoImpl::GetPreviewsState() const {
return previews_state_;
}
-bool ResourceRequestInfoImpl::ShouldReportRawHeaders() const {
- return report_raw_headers_;
-}
-
-bool ResourceRequestInfoImpl::ShouldReportSecurityInfo() const {
- return report_security_info_;
-}
-
NavigationUIData* ResourceRequestInfoImpl::GetNavigationUIData() const {
return navigation_ui_data_.get();
}
@@ -325,6 +323,11 @@ ResourceRequestInfo::DevToolsStatus ResourceRequestInfoImpl::GetDevToolsStatus()
return devtools_status_;
}
+void ResourceRequestInfoImpl::SetResourceRequestBlockedReason(
+ blink::ResourceRequestBlockedReason reason) {
+ resource_request_blocked_reason_ = reason;
+}
+
base::Optional<blink::ResourceRequestBlockedReason>
ResourceRequestInfoImpl::GetResourceRequestBlockedReason() const {
return resource_request_blocked_reason_;
@@ -353,6 +356,14 @@ GlobalRoutingID ResourceRequestInfoImpl::GetGlobalRoutingID() const {
return GlobalRoutingID(GetChildID(), route_id_);
}
+bool ResourceRequestInfoImpl::ShouldReportRawHeaders() const {
+ return report_raw_headers_;
+}
+
+bool ResourceRequestInfoImpl::ShouldReportSecurityInfo() const {
+ return report_security_info_;
+}
+
void ResourceRequestInfoImpl::ResetBody() {
body_ = nullptr;
}
diff --git a/chromium/content/browser/loader/resource_request_info_impl.h b/chromium/content/browser/loader/resource_request_info_impl.h
index 0b65d8c115b..0bc8ea93804 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -96,14 +96,12 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool IsDownload() const override;
// Returns a bitmask of potentially several Previews optimizations.
PreviewsState GetPreviewsState() const override;
- bool ShouldReportRawHeaders() const;
- bool ShouldReportSecurityInfo() const;
NavigationUIData* GetNavigationUIData() const override;
DevToolsStatus GetDevToolsStatus() const override;
-
+ void SetResourceRequestBlockedReason(
+ blink::ResourceRequestBlockedReason reason) override;
base::Optional<blink::ResourceRequestBlockedReason>
GetResourceRequestBlockedReason() const override;
-
base::StringPiece GetCustomCancelReason() const override;
CONTENT_EXPORT void AssociateWithRequest(net::URLRequest* request);
@@ -111,6 +109,14 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
CONTENT_EXPORT int GetRequestID() const;
GlobalRoutingID GetGlobalRoutingID() const;
+ // Returns true if raw response headers (including sensitive data such as
+ // cookies) should be included with the response.
+ bool ShouldReportRawHeaders() const;
+
+ // Returns true if security details (SSL/TLS connection parameters and
+ // certificate chain) should be included with the response.
+ bool ShouldReportSecurityInfo() const;
+
// PlzNavigate
// The id of the FrameTreeNode that initiated this request (for a navigation
// request).
@@ -184,18 +190,19 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
devtools_status_ = devtools_status;
}
- void set_resource_request_blocked_reason(
- base::Optional<blink::ResourceRequestBlockedReason> reason) {
- resource_request_blocked_reason_ = reason;
- }
-
void SetBlobHandles(BlobHandles blob_handles);
- bool blocked_cross_site_document() const {
- return blocked_cross_site_document_;
+ bool blocked_response_from_reaching_renderer() const {
+ return blocked_response_from_reaching_renderer_;
+ }
+ void set_blocked_response_from_reaching_renderer(bool value) {
+ blocked_response_from_reaching_renderer_ = value;
}
- void set_blocked_cross_site_document(bool value) {
- blocked_cross_site_document_ = value;
+ bool should_report_corb_blocking() const {
+ return should_report_corb_blocking_;
+ }
+ void set_should_report_corb_blocking(bool value) {
+ should_report_corb_blocking_ = value;
}
void set_custom_cancel_reason(base::StringPiece reason) {
@@ -248,7 +255,13 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
scoped_refptr<network::ResourceRequestBody> body_;
bool initiated_in_secure_context_;
std::unique_ptr<NavigationUIData> navigation_ui_data_;
- bool blocked_cross_site_document_;
+
+ // Whether response details (response headers, timing information, metadata)
+ // have been blocked from reaching the renderer process (e.g. by Cross-Origin
+ // Read Blocking).
+ bool blocked_response_from_reaching_renderer_;
+
+ bool should_report_corb_blocking_;
bool first_auth_attempt_;
// Keeps upload body blobs alive for the duration of the request.
diff --git a/chromium/content/browser/loader/resource_scheduler_filter.cc b/chromium/content/browser/loader/resource_scheduler_filter.cc
index 3b3da1ed38c..0667df77d25 100644
--- a/chromium/content/browser/loader/resource_scheduler_filter.cc
+++ b/chromium/content/browser/loader/resource_scheduler_filter.cc
@@ -5,8 +5,6 @@
#include "content/browser/loader/resource_scheduler_filter.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/common/frame_messages.h"
-#include "ipc/ipc_message_macros.h"
#include "services/network/resource_scheduler.h"
namespace content {
@@ -18,18 +16,6 @@ network::ResourceScheduler* GetResourceSchedulerOrNullptr() {
return ResourceDispatcherHostImpl::Get()->scheduler();
}
-ResourceSchedulerFilter::ResourceSchedulerFilter(int child_id)
- : BrowserMessageFilter(FrameMsgStart), child_id_(child_id) {}
-
-ResourceSchedulerFilter::~ResourceSchedulerFilter() {}
-
-bool ResourceSchedulerFilter::OnMessageReceived(const IPC::Message& message) {
- IPC_BEGIN_MESSAGE_MAP(ResourceSchedulerFilter, message)
- IPC_MESSAGE_HANDLER(FrameHostMsg_WillInsertBody, OnWillInsertBody)
- IPC_END_MESSAGE_MAP()
- return false;
-}
-
// static
void ResourceSchedulerFilter::OnDidCommitMainframeNavigation(
int render_process_id,
@@ -39,10 +25,4 @@ void ResourceSchedulerFilter::OnDidCommitMainframeNavigation(
scheduler->DeprecatedOnNavigate(render_process_id, render_view_routing_id);
}
-void ResourceSchedulerFilter::OnWillInsertBody(int render_view_routing_id) {
- auto* scheduler = GetResourceSchedulerOrNullptr();
- if (scheduler)
- scheduler->DeprecatedOnWillInsertBody(child_id_, render_view_routing_id);
-}
-
} // namespace content
diff --git a/chromium/content/browser/loader/resource_scheduler_filter.h b/chromium/content/browser/loader/resource_scheduler_filter.h
index 71a7b009809..573d27acd09 100644
--- a/chromium/content/browser/loader/resource_scheduler_filter.h
+++ b/chromium/content/browser/loader/resource_scheduler_filter.h
@@ -6,33 +6,20 @@
#define CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_FILTER_H_
#include "base/macros.h"
-#include "content/public/browser/browser_message_filter.h"
namespace content {
-// This class listens for incoming ViewHostMsgs that are applicable to the
-// ResourceScheduler and invokes the appropriate notifications. It must be
-// inserted before the RenderMessageFilter, because the ResourceScheduler runs
-// on the IO thread and we want to see the messages before the view messages are
-// bounced to the UI thread.
-class ResourceSchedulerFilter : public BrowserMessageFilter {
+// This class is used to send a signal to ResourceScheduler. This class used
+// to be a ResourceMessageFilter, but is not any more.
+class ResourceSchedulerFilter {
public:
- explicit ResourceSchedulerFilter(int child_id);
-
// Informs the ResourceScheduler that a main-frame, non-same-document
// navigation has just committed.
static void OnDidCommitMainframeNavigation(int render_process_id,
int render_view_routing_id);
-
- // BrowserMessageFilter:
- bool OnMessageReceived(const IPC::Message& message) override;
-
private:
- ~ResourceSchedulerFilter() override;
-
- void OnWillInsertBody(int render_view_routing_id);
-
- int child_id_;
+ ResourceSchedulerFilter() = delete;
+ ~ResourceSchedulerFilter() = delete;
DISALLOW_COPY_AND_ASSIGN(ResourceSchedulerFilter);
};
diff --git a/chromium/content/browser/loader/stream_resource_handler.cc b/chromium/content/browser/loader/stream_resource_handler.cc
index b1337ca2e17..9a487904ac1 100644
--- a/chromium/content/browser/loader/stream_resource_handler.cc
+++ b/chromium/content/browser/loader/stream_resource_handler.cc
@@ -73,8 +73,4 @@ void StreamResourceHandler::OnResponseCompleted(
controller->Resume();
}
-void StreamResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- NOTREACHED();
-}
-
} // namespace content
diff --git a/chromium/content/browser/loader/stream_resource_handler.h b/chromium/content/browser/loader/stream_resource_handler.h
index cb8a2d58d6b..b6f51bba48c 100644
--- a/chromium/content/browser/loader/stream_resource_handler.h
+++ b/chromium/content/browser/loader/stream_resource_handler.h
@@ -59,8 +59,6 @@ class StreamResourceHandler : public ResourceHandler {
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- void OnDataDownloaded(int bytes_downloaded) override;
-
Stream* stream() { return writer_.stream(); }
private:
diff --git a/chromium/content/browser/loader/temporary_file_stream.cc b/chromium/content/browser/loader/temporary_file_stream.cc
deleted file mode 100644
index 2f1c784f5e0..00000000000
--- a/chromium/content/browser/loader/temporary_file_stream.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/browser/loader/temporary_file_stream.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/files/file_proxy.h"
-#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
-#include "base/task_scheduler/post_task.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/base/file_stream.h"
-#include "storage/browser/blob/shareable_file_reference.h"
-
-using storage::ShareableFileReference;
-
-namespace content {
-
-namespace {
-
-void DidCreateTemporaryFile(
- const CreateTemporaryFileStreamCallback& callback,
- std::unique_ptr<base::FileProxy> file_proxy,
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- base::File::Error error_code,
- const base::FilePath& file_path) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (!file_proxy->IsValid()) {
- callback.Run(error_code, std::unique_ptr<net::FileStream>(), NULL);
- return;
- }
-
- // Cancelled or not, create the deletable_file so the temporary is cleaned up.
- scoped_refptr<ShareableFileReference> deletable_file =
- ShareableFileReference::GetOrCreate(
- file_path,
- ShareableFileReference::DELETE_ON_FINAL_RELEASE,
- task_runner.get());
-
- 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());
-}
-
-} // namespace
-
-void CreateTemporaryFileStream(
- const CreateTemporaryFileStreamCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- scoped_refptr<base::SequencedTaskRunner> task_runner =
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
-
- std::unique_ptr<base::FileProxy> file_proxy(
- new base::FileProxy(task_runner.get()));
- base::FileProxy* proxy = file_proxy.get();
- proxy->CreateTemporary(
- base::File::FLAG_ASYNC,
- base::BindOnce(&DidCreateTemporaryFile, callback, std::move(file_proxy),
- std::move(task_runner)));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/temporary_file_stream.h b/chromium/content/browser/loader/temporary_file_stream.h
deleted file mode 100644
index 406fcc445ee..00000000000
--- a/chromium/content/browser/loader/temporary_file_stream.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_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 "content/common/content_export.h"
-
-namespace net {
-class FileStream;
-}
-
-namespace storage {
-class ShareableFileReference;
-}
-
-namespace content {
-
-typedef base::Callback<void(base::File::Error,
- std::unique_ptr<net::FileStream>,
- storage::ShareableFileReference*)>
- CreateTemporaryFileStreamCallback;
-
-// Creates a temporary file and asynchronously calls |callback| with a
-// net::FileStream and storage::ShareableFileReference. The file is deleted
-// when the storage::ShareableFileReference is deleted. Note it is the
-// consumer's responsibility to ensure the storage::ShareableFileReference
-// stays in scope until net::FileStream has finished closing the file. On error,
-// |callback| is called with an error in the first parameter.
-//
-// This function may only be called on the IO thread.
-//
-// TODO(davidben): Juggling the net::FileStream and
-// storage::ShareableFileReference lifetimes is a nuisance. The two should
-// be tied together so the consumer need not deal with it.
-CONTENT_EXPORT void CreateTemporaryFileStream(
- const CreateTemporaryFileStreamCallback& callback);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_TEMPORARY_FILE_STREAM_H_
diff --git a/chromium/content/browser/loader/temporary_file_stream_unittest.cc b/chromium/content/browser/loader/temporary_file_stream_unittest.cc
deleted file mode 100644
index e32ae5b2a6b..00000000000
--- a/chromium/content/browser/loader/temporary_file_stream_unittest.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/browser/loader/temporary_file_stream.h"
-
-#include <string.h>
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "content/public/test/test_utils.h"
-#include "net/base/file_stream.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
-#include "storage/browser/blob/shareable_file_reference.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using storage::ShareableFileReference;
-
-namespace content {
-
-namespace {
-
-const char kTestData[] = "0123456789";
-const int kTestDataSize = arraysize(kTestData) - 1;
-
-class WaitForFileStream {
- public:
- base::File::Error error() const { return error_; }
- net::FileStream* file_stream() const { return file_stream_.get(); }
- ShareableFileReference* deletable_file() const {
- return deletable_file_.get();
- }
-
- void OnFileStreamCreated(base::File::Error error,
- std::unique_ptr<net::FileStream> file_stream,
- ShareableFileReference* deletable_file) {
- error_ = error;
- file_stream_ = std::move(file_stream);
- deletable_file_ = deletable_file;
- loop_.Quit();
- }
-
- void Wait() {
- loop_.Run();
- }
-
- void Release() {
- file_stream_.reset(nullptr);
- deletable_file_ = nullptr;
- }
- private:
- base::RunLoop loop_;
- base::File::Error error_;
- std::unique_ptr<net::FileStream> file_stream_;
- scoped_refptr<ShareableFileReference> deletable_file_;
-};
-
-} // namespace
-
-TEST(TemporaryFileStreamTest, Basic) {
- TestBrowserThreadBundle thread_bundle(TestBrowserThreadBundle::IO_MAINLOOP);
-
- // Create a temporary.
- WaitForFileStream file_stream_waiter;
- CreateTemporaryFileStream(base::Bind(&WaitForFileStream::OnFileStreamCreated,
- base::Unretained(&file_stream_waiter)));
- file_stream_waiter.Wait();
-
- // The temporary should exist.
- EXPECT_EQ(base::File::FILE_OK, file_stream_waiter.error());
- base::FilePath file_path = file_stream_waiter.deletable_file()->path();
- EXPECT_TRUE(base::PathExists(file_path));
-
- // Write some data to the temporary.
- int bytes_written = 0;
- scoped_refptr<net::IOBufferWithSize> buf =
- new net::IOBufferWithSize(kTestDataSize);
- memcpy(buf->data(), kTestData, kTestDataSize);
- scoped_refptr<net::DrainableIOBuffer> drainable =
- new net::DrainableIOBuffer(buf.get(), buf->size());
- while (bytes_written != kTestDataSize) {
- net::TestCompletionCallback write_callback;
- int rv = file_stream_waiter.file_stream()->Write(
- drainable.get(), drainable->BytesRemaining(),
- write_callback.callback());
- if (rv == net::ERR_IO_PENDING)
- rv = write_callback.WaitForResult();
- ASSERT_LT(0, rv);
- drainable->DidConsume(rv);
- bytes_written += rv;
- }
-
- // Verify the data matches.
- std::string contents;
- ASSERT_TRUE(base::ReadFileToString(file_path, &contents));
- EXPECT_EQ(kTestData, contents);
-
- // Close the file.
- net::TestCompletionCallback close_callback;
- int rv = file_stream_waiter.file_stream()->Close(close_callback.callback());
- if (rv == net::ERR_IO_PENDING)
- rv = close_callback.WaitForResult();
- EXPECT_EQ(net::OK, rv);
-
- // Release everything. The file should be gone now.
- file_stream_waiter.Release();
- content::RunAllTasksUntilIdle();
-
- // The temporary should be gone now.
- EXPECT_FALSE(base::PathExists(file_path));
-}
-
-} // content
diff --git a/chromium/content/browser/loader/test_resource_handler.cc b/chromium/content/browser/loader/test_resource_handler.cc
index b4c9f869b52..0fbeb2706a9 100644
--- a/chromium/content/browser/loader/test_resource_handler.cc
+++ b/chromium/content/browser/loader/test_resource_handler.cc
@@ -147,7 +147,6 @@ void TestResourceHandler::OnWillRead(
int* buf_size,
std::unique_ptr<ResourceController> controller) {
EXPECT_FALSE(canceled_);
- EXPECT_FALSE(expect_on_data_downloaded_);
EXPECT_EQ(0, on_response_completed_called_);
// Only create a ScopedCallDepthTracker if not called re-entrantly, as
// OnWillRead may be called synchronously in response to a Resume(), but
@@ -182,7 +181,6 @@ void TestResourceHandler::OnReadCompleted(
int bytes_read,
std::unique_ptr<ResourceController> controller) {
EXPECT_FALSE(canceled_);
- EXPECT_FALSE(expect_on_data_downloaded_);
EXPECT_EQ(1, on_will_start_called_);
EXPECT_EQ(1, on_response_started_called_);
EXPECT_EQ(0, on_response_completed_called_);
@@ -225,7 +223,7 @@ void TestResourceHandler::OnResponseCompleted(
parent_read_buffer_size_ = nullptr;
EXPECT_EQ(0, on_response_completed_called_);
- if (status.is_success() && !expect_on_data_downloaded_ && expect_eof_read_)
+ if (status.is_success() && expect_eof_read_)
EXPECT_EQ(1, on_read_eof_called_);
++on_response_completed_called_;
@@ -248,15 +246,6 @@ void TestResourceHandler::OnResponseCompleted(
controller->Resume();
}
-void TestResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- EXPECT_TRUE(expect_on_data_downloaded_);
- EXPECT_EQ(1, on_will_start_called_);
- EXPECT_EQ(1, on_response_started_called_);
- EXPECT_EQ(0, on_response_completed_called_);
-
- total_bytes_downloaded_ += bytes_downloaded;
-}
-
void TestResourceHandler::Resume() {
ScopedCallDepthTracker call_depth_tracker(&call_depth_);
diff --git a/chromium/content/browser/loader/test_resource_handler.h b/chromium/content/browser/loader/test_resource_handler.h
index f109fce1a6d..d99196a1128 100644
--- a/chromium/content/browser/loader/test_resource_handler.h
+++ b/chromium/content/browser/loader/test_resource_handler.h
@@ -63,7 +63,6 @@ class TestResourceHandler : public ResourceHandler {
void OnResponseCompleted(
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- void OnDataDownloaded(int bytes_downloaded) override;
void Resume();
void CancelWithError(net::Error error_code);
@@ -122,12 +121,6 @@ class TestResourceHandler : public ResourceHandler {
defer_on_response_completed_ = defer_on_response_completed;
}
- // Set if OnDataDownloaded calls are expected instead of
- // OnWillRead/OnReadCompleted.
- void set_expect_on_data_downloaded(bool expect_on_data_downloaded) {
- expect_on_data_downloaded_ = expect_on_data_downloaded;
- }
-
// Sets whether to expect a final 0-byte read on success. Defaults to true.
void set_expect_eof_read(bool expect_eof_read) {
expect_eof_read_ = expect_eof_read;
@@ -154,8 +147,6 @@ class TestResourceHandler : public ResourceHandler {
return resource_response_.get();
};
- int total_bytes_downloaded() const { return total_bytes_downloaded_; }
-
const std::string& body() const { return body_; }
net::URLRequestStatus final_status() const { return final_status_; }
@@ -197,8 +188,6 @@ class TestResourceHandler : public ResourceHandler {
bool defer_on_read_eof_ = false;
bool defer_on_response_completed_ = false;
- bool expect_on_data_downloaded_ = false;
-
bool expect_eof_read_ = true;
int on_will_start_called_ = 0;
@@ -211,7 +200,6 @@ class TestResourceHandler : public ResourceHandler {
GURL start_url_;
scoped_refptr<network::ResourceResponse> resource_response_;
- int total_bytes_downloaded_ = 0;
std::string body_;
net::URLRequestStatus final_status_ =
net::URLRequestStatus::FromError(net::ERR_UNEXPECTED);
diff --git a/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc b/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
index e6ede61511d..9385955b5c5 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
+++ b/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
@@ -203,8 +203,8 @@ TEST_P(URLLoaderFactoryImplTest, GetResponse) {
client.completion_status().encoded_data_length);
EXPECT_EQ(static_cast<int64_t>(expected.size()),
client.completion_status().encoded_body_length);
- // OnTransferSizeUpdated is not dispatched as report_raw_headers is not set.
- EXPECT_EQ(0, client.body_transfer_size());
+ EXPECT_EQ(static_cast<int64_t>(expected.size()), client.body_transfer_size());
+ EXPECT_GT(client.body_transfer_size(), 0);
EXPECT_GT(client.response_head().encoded_data_length, 0);
EXPECT_GT(client.completion_status().encoded_data_length, 0);
}
@@ -322,133 +322,6 @@ TEST_P(URLLoaderFactoryImplTest, ShouldNotRequestURL) {
EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
}
-TEST_P(URLLoaderFactoryImplTest, DownloadToFile) {
- constexpr int32_t kRoutingId = 1;
- constexpr int32_t kRequestId = 2;
-
- network::mojom::URLLoaderPtr loader;
- base::FilePath root;
- base::PathService::Get(DIR_TEST_DATA, &root);
- net::URLRequestMockHTTPJob::AddUrlHandlers(root);
-
- network::ResourceRequest request;
- network::TestURLLoaderClient client;
- request.url = net::URLRequestMockHTTPJob::GetMockUrl("hello.html");
- request.method = "GET";
- request.resource_type = RESOURCE_TYPE_XHR;
- request.download_to_file = true;
- request.request_initiator = url::Origin::Create(request.url);
- factory_->CreateLoaderAndStart(
- mojo::MakeRequest(&loader), kRoutingId, kRequestId, 0, request,
- client.CreateInterfacePtr(),
- net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
- ASSERT_FALSE(client.has_received_response());
- ASSERT_FALSE(client.has_data_downloaded());
- ASSERT_FALSE(client.has_received_completion());
-
- client.RunUntilResponseReceived();
-
- net::URLRequest* url_request =
- rdh_.GetURLRequest(GlobalRequestID(kChildId, kRequestId));
- ASSERT_TRUE(url_request);
- ResourceRequestInfoImpl* request_info =
- ResourceRequestInfoImpl::ForRequest(url_request);
- ASSERT_TRUE(request_info);
- EXPECT_EQ(kChildId, request_info->GetChildID());
- EXPECT_EQ(kRoutingId, request_info->GetRouteID());
- EXPECT_EQ(kRequestId, request_info->GetRequestID());
-
- ASSERT_FALSE(client.has_received_completion());
-
- client.RunUntilComplete();
- ASSERT_TRUE(client.has_data_downloaded());
- ASSERT_TRUE(client.has_received_completion());
-
- EXPECT_EQ(200, client.response_head().headers->response_code());
- std::string content_type;
- client.response_head().headers->GetNormalizedHeader("content-type",
- &content_type);
- EXPECT_EQ("text/html", content_type);
- EXPECT_EQ(0, client.completion_status().error_code);
-
- std::string contents;
- base::ReadFileToString(client.response_head().download_file_path, &contents);
-
- EXPECT_EQ(static_cast<int64_t>(contents.size()),
- client.download_data_length());
- EXPECT_EQ(static_cast<int64_t>(contents.size()),
- client.encoded_download_data_length());
-
- std::string expected;
- base::ReadFileToString(
- root.Append(base::FilePath(FILE_PATH_LITERAL("hello.html"))), &expected);
- EXPECT_EQ(expected, contents);
- EXPECT_EQ(static_cast<int64_t>(expected.size()) +
- client.response_head().encoded_data_length,
- client.completion_status().encoded_data_length);
- EXPECT_EQ(static_cast<int64_t>(expected.size()),
- client.completion_status().encoded_body_length);
-}
-
-TEST_P(URLLoaderFactoryImplTest, DownloadToFileFailure) {
- constexpr int32_t kRoutingId = 1;
- constexpr int32_t kRequestId = 2;
-
- network::mojom::URLLoaderPtr loader;
- base::FilePath root;
- base::PathService::Get(DIR_TEST_DATA, &root);
- net::URLRequestSlowDownloadJob::AddUrlHandler();
-
- network::ResourceRequest request;
- network::TestURLLoaderClient client;
- request.url = GURL(net::URLRequestSlowDownloadJob::kKnownSizeUrl);
- request.method = "GET";
- request.resource_type = RESOURCE_TYPE_XHR;
- request.download_to_file = true;
- request.request_initiator = url::Origin::Create(request.url);
- factory_->CreateLoaderAndStart(
- mojo::MakeRequest(&loader), kRoutingId, kRequestId, 0, request,
- client.CreateInterfacePtr(),
- net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
- ASSERT_FALSE(client.has_received_response());
- ASSERT_FALSE(client.has_data_downloaded());
- ASSERT_FALSE(client.has_received_completion());
-
- client.RunUntilResponseReceived();
-
- net::URLRequest* url_request =
- rdh_.GetURLRequest(GlobalRequestID(kChildId, kRequestId));
- ASSERT_TRUE(url_request);
- ResourceRequestInfoImpl* request_info =
- ResourceRequestInfoImpl::ForRequest(url_request);
- ASSERT_TRUE(request_info);
- EXPECT_EQ(kChildId, request_info->GetChildID());
- EXPECT_EQ(kRoutingId, request_info->GetRouteID());
- EXPECT_EQ(kRequestId, request_info->GetRequestID());
-
- ASSERT_FALSE(client.has_received_completion());
-
- client.RunUntilDataDownloaded();
- ASSERT_TRUE(client.has_data_downloaded());
- ASSERT_FALSE(client.has_received_completion());
- EXPECT_LT(0, client.download_data_length());
- EXPECT_GE(
- static_cast<int64_t>(net::URLRequestSlowDownloadJob::kFirstDownloadSize),
- client.download_data_length());
- EXPECT_LT(0, client.encoded_download_data_length());
- EXPECT_GE(
- static_cast<int64_t>(net::URLRequestSlowDownloadJob::kFirstDownloadSize),
- client.encoded_download_data_length());
-
- url_request->Cancel();
- client.RunUntilComplete();
-
- ASSERT_TRUE(client.has_received_completion());
-
- EXPECT_EQ(200, client.response_head().headers->response_code());
- EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
-}
-
TEST_P(URLLoaderFactoryImplTest, OnTransferSizeUpdated) {
constexpr int32_t kRoutingId = 81;
constexpr int32_t kRequestId = 28;
diff --git a/chromium/content/browser/loader/wake_lock_resource_throttle.cc b/chromium/content/browser/loader/wake_lock_resource_throttle.cc
deleted file mode 100644
index 9ba1bd0da64..00000000000
--- a/chromium/content/browser/loader/wake_lock_resource_throttle.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/wake_lock_resource_throttle.h"
-
-#include "content/browser/service_manager/service_manager_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/device/public/mojom/constants.mojom.h"
-#include "services/device/public/mojom/wake_lock_provider.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-namespace content {
-
-namespace {
-
-const int kWakeLockDelaySeconds = 30;
-
-} // namespace
-
-WakeLockResourceThrottle::WakeLockResourceThrottle(const std::string& host)
- : host_(host) {}
-
-WakeLockResourceThrottle::~WakeLockResourceThrottle() {}
-
-void WakeLockResourceThrottle::WillStartRequest(bool* defer) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Delay wake lock request to dismiss small requests.
- timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kWakeLockDelaySeconds),
- this, &WakeLockResourceThrottle::RequestWakeLock);
-}
-
-void WakeLockResourceThrottle::WillProcessResponse(bool* defer) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Cancel wake lock after request finishes.
- if (wake_lock_)
- wake_lock_->CancelWakeLock();
-
- timer_.Stop();
-}
-
-const char* WakeLockResourceThrottle::GetNameForLogging() const {
- return "WakeLockResourceThrottle";
-}
-
-void WakeLockResourceThrottle::RequestWakeLock() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!wake_lock_);
-
- service_manager::Connector* connector =
- ServiceManagerContext::GetConnectorForIOThread();
- // |connector| might be nullptr in some testing contexts, in which the
- // service manager connection isn't initialized.
- if (connector) {
- device::mojom::WakeLockProviderPtr wake_lock_provider;
- connector->BindInterface(device::mojom::kServiceName,
- mojo::MakeRequest(&wake_lock_provider));
- wake_lock_provider->GetWakeLockWithoutContext(
- device::mojom::WakeLockType::kPreventAppSuspension,
- device::mojom::WakeLockReason::kOther, "Uploading data to " + host_,
- mojo::MakeRequest(&wake_lock_));
-
- wake_lock_->RequestWakeLock();
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/wake_lock_resource_throttle.h b/chromium/content/browser/loader/wake_lock_resource_throttle.h
deleted file mode 100644
index 986b566aa86..00000000000
--- a/chromium/content/browser/loader/wake_lock_resource_throttle.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_BROWSER_LOADER_WAKE_LOCK_RESOURCE_THROTTLE_H_
-#define CONTENT_BROWSER_LOADER_WAKE_LOCK_RESOURCE_THROTTLE_H_
-
-#include <memory>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/timer/timer.h"
-#include "content/public/browser/resource_throttle.h"
-#include "services/device/public/mojom/wake_lock.mojom.h"
-
-namespace content {
-
-// This ResourceThrottle holds wake lock until large upload request finishes.
-class WakeLockResourceThrottle : public ResourceThrottle {
- public:
- WakeLockResourceThrottle(const std::string& host);
- ~WakeLockResourceThrottle() override;
-
- // ResourceThrottle overrides:
- void WillStartRequest(bool* defer) override;
- void WillProcessResponse(bool* defer) override;
- const char* GetNameForLogging() const override;
-
- private:
- void RequestWakeLock();
-
- const std::string host_;
- base::OneShotTimer timer_;
-
- // Destruction of wake_lock_ will trigger
- // WakeLock::OnConnectionError on the service side, so there is no
- // need to call CancelWakeLock() in the destructor.
- device::mojom::WakeLockPtr wake_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(WakeLockResourceThrottle);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_WAKE_LOCK_RESOURCE_THROTTLE_H_
diff --git a/chromium/content/browser/manifest/manifest_icon_downloader.cc b/chromium/content/browser/manifest/manifest_icon_downloader.cc
index 903eca621bb..ac40d4cefb5 100644
--- a/chromium/content/browser/manifest/manifest_icon_downloader.cc
+++ b/chromium/content/browser/manifest/manifest_icon_downloader.cc
@@ -9,7 +9,6 @@
#include <limits>
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/manifest_icon_selector.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
diff --git a/chromium/content/browser/manifest/manifest_icon_selector.cc b/chromium/content/browser/manifest/manifest_icon_selector.cc
deleted file mode 100644
index 02afadb3709..00000000000
--- a/chromium/content/browser/manifest/manifest_icon_selector.cc
+++ /dev/null
@@ -1,86 +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/browser/manifest_icon_selector.h"
-
-#include <limits>
-
-#include "base/stl_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "third_party/blink/public/common/mime_util/mime_util.h"
-
-namespace content {
-
-// static
-GURL ManifestIconSelector::FindBestMatchingIcon(
- const std::vector<blink::Manifest::Icon>& icons,
- int ideal_icon_size_in_px,
- int minimum_icon_size_in_px,
- blink::Manifest::Icon::IconPurpose purpose) {
- DCHECK(minimum_icon_size_in_px <= ideal_icon_size_in_px);
-
- // Icon with exact matching size has priority over icon with size "any", which
- // has priority over icon with closest matching size.
- int latest_size_any_index = -1;
- int closest_size_match_index = -1;
- int best_delta_in_size = std::numeric_limits<int>::min();
-
- for (size_t i = 0; i < icons.size(); ++i) {
- const auto& icon = icons[i];
-
- // Check for supported image MIME types.
- if (!icon.type.empty() &&
- !blink::IsSupportedImageMimeType(base::UTF16ToUTF8(icon.type))) {
- continue;
- }
-
- // Check for icon purpose.
- if (!base::ContainsValue(icon.purpose, purpose))
- continue;
-
- // Check for size constraints.
- for (const gfx::Size& size : icon.sizes) {
- // Check for size "any". Return this icon if no better one is found.
- if (size.IsEmpty()) {
- latest_size_any_index = i;
- continue;
- }
-
- // Check for squareness.
- if (size.width() != size.height())
- continue;
-
- // Check for minimum size.
- if (size.width() < minimum_icon_size_in_px)
- continue;
-
- // Check for ideal size. Return this icon immediately.
- if (size.width() == ideal_icon_size_in_px)
- return icon.src;
-
- // Check for closest match.
- int delta = size.width() - ideal_icon_size_in_px;
-
- // Smallest icon larger than ideal size has priority over largest icon
- // smaller than ideal size.
- if (best_delta_in_size > 0 && delta < 0)
- continue;
-
- if ((best_delta_in_size > 0 && delta < best_delta_in_size) ||
- (best_delta_in_size < 0 && delta > best_delta_in_size)) {
- closest_size_match_index = i;
- best_delta_in_size = delta;
- }
- }
- }
-
- if (latest_size_any_index != -1)
- return icons[latest_size_any_index].src;
- else if (closest_size_match_index != -1)
- return icons[closest_size_match_index].src;
- else
- return GURL();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/manifest/manifest_icon_selector_unittest.cc b/chromium/content/browser/manifest/manifest_icon_selector_unittest.cc
deleted file mode 100644
index 467a91a0864..00000000000
--- a/chromium/content/browser/manifest/manifest_icon_selector_unittest.cc
+++ /dev/null
@@ -1,499 +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/browser/manifest_icon_selector.h"
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-using IconPurpose = blink::Manifest::Icon::IconPurpose;
-
-namespace {
-
-const int kIdealIconSize = 144;
-const int kMinimumIconSize = 0;
-
-static blink::Manifest::Icon CreateIcon(const std::string& url,
- const std::string& type,
- const std::vector<gfx::Size> sizes,
- IconPurpose purpose) {
- blink::Manifest::Icon icon;
- icon.src = GURL(url);
- icon.type = base::UTF8ToUTF16(type);
- icon.sizes = sizes;
- icon.purpose.push_back(purpose);
-
- return icon;
-}
-
-} // anonymous namespace
-
-TEST(ManifestIconSelector, NoIcons) {
- // No icons should return the empty URL.
- std::vector<blink::Manifest::Icon> icons;
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_TRUE(url.is_empty());
-}
-
-TEST(ManifestIconSelector, NoSizes) {
- // Icon with no sizes are ignored.
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(CreateIcon("http://foo.com/icon.png", "",
- std::vector<gfx::Size>(), IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_TRUE(url.is_empty());
-}
-
-TEST(ManifestIconSelector, MIMETypeFiltering) {
- // Icons with type specified to a MIME type that isn't a valid image MIME type
- // are ignored.
- std::vector<gfx::Size> sizes;
- sizes.push_back(gfx::Size(1024, 1024));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(CreateIcon("http://foo.com/icon.png", "image/foo_bar", sizes,
- IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "image/", sizes, IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "image/", sizes, IconPurpose::ANY));
- icons.push_back(CreateIcon("http://foo.com/icon.png", "video/mp4", sizes,
- IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_TRUE(url.is_empty());
-
- icons.clear();
- icons.push_back(CreateIcon("http://foo.com/icon.png", "image/png", sizes,
- IconPurpose::ANY));
- url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
-
- icons.clear();
- icons.push_back(CreateIcon("http://foo.com/icon.png", "image/gif", sizes,
- IconPurpose::ANY));
- url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
-
- icons.clear();
- icons.push_back(CreateIcon("http://foo.com/icon.png", "image/jpeg", sizes,
- IconPurpose::ANY));
- url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
-}
-
-TEST(ManifestIconSelector, PurposeFiltering) {
- // Icons with purpose specified to non-matching purpose are ignored.
- std::vector<gfx::Size> sizes_48;
- sizes_48.push_back(gfx::Size(48, 48));
-
- std::vector<gfx::Size> sizes_96;
- sizes_96.push_back(gfx::Size(96, 96));
-
- std::vector<gfx::Size> sizes_144;
- sizes_144.push_back(gfx::Size(144, 144));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(CreateIcon("http://foo.com/icon_48.png", "", sizes_48,
- IconPurpose::BADGE));
- icons.push_back(
- CreateIcon("http://foo.com/icon_96.png", "", sizes_96, IconPurpose::ANY));
- icons.push_back(CreateIcon("http://foo.com/icon_144.png", "", sizes_144,
- IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, 48, kMinimumIconSize, IconPurpose::BADGE);
- EXPECT_EQ("http://foo.com/icon_48.png", url.spec());
-
- url = ManifestIconSelector::FindBestMatchingIcon(icons, 48, kMinimumIconSize,
- IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_96.png", url.spec());
-
- url = ManifestIconSelector::FindBestMatchingIcon(icons, 96, kMinimumIconSize,
- IconPurpose::BADGE);
- EXPECT_EQ("http://foo.com/icon_48.png", url.spec());
-
- url = ManifestIconSelector::FindBestMatchingIcon(icons, 96, 96,
- IconPurpose::BADGE);
- EXPECT_TRUE(url.is_empty());
-
- url = ManifestIconSelector::FindBestMatchingIcon(icons, 144, kMinimumIconSize,
- IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_144.png", url.spec());
-}
-
-TEST(ManifestIconSelector, IdealSizeIsUsedFirst) {
- // Each icon is marked with sizes that match the ideal icon size.
- std::vector<gfx::Size> sizes_48;
- sizes_48.push_back(gfx::Size(48, 48));
-
- std::vector<gfx::Size> sizes_96;
- sizes_96.push_back(gfx::Size(96, 96));
-
- std::vector<gfx::Size> sizes_144;
- sizes_144.push_back(gfx::Size(144, 144));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(
- CreateIcon("http://foo.com/icon_48.png", "", sizes_48, IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon_96.png", "", sizes_96, IconPurpose::ANY));
- icons.push_back(CreateIcon("http://foo.com/icon_144.png", "", sizes_144,
- IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, 48, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_48.png", url.spec());
-
- url = ManifestIconSelector::FindBestMatchingIcon(icons, 96, kMinimumIconSize,
- IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_96.png", url.spec());
-
- url = ManifestIconSelector::FindBestMatchingIcon(icons, 144, kMinimumIconSize,
- IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_144.png", url.spec());
-}
-
-TEST(ManifestIconSelector, FirstIconWithIdealSizeIsUsedFirst) {
- // This test has three icons. The first icon is going to be used because it
- // contains the ideal size.
- std::vector<gfx::Size> sizes_1;
- sizes_1.push_back(gfx::Size(kIdealIconSize, kIdealIconSize));
- sizes_1.push_back(gfx::Size(kIdealIconSize * 2, kIdealIconSize * 2));
- sizes_1.push_back(gfx::Size(kIdealIconSize * 3, kIdealIconSize * 3));
-
- std::vector<gfx::Size> sizes_2;
- sizes_2.push_back(gfx::Size(1024, 1024));
-
- std::vector<gfx::Size> sizes_3;
- sizes_3.push_back(gfx::Size(1024, 1024));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(
- CreateIcon("http://foo.com/icon_x1.png", "", sizes_1, IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon_x2.png", "", sizes_2, IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon_x3.png", "", sizes_3, IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
-
- url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize * 2, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
-
- url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize * 3, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
-}
-
-TEST(ManifestIconSelector, FallbackToSmallestLargerIcon) {
- // If there is no perfect icon, the smallest larger icon will be chosen.
- std::vector<gfx::Size> sizes_1;
- sizes_1.push_back(gfx::Size(90, 90));
-
- std::vector<gfx::Size> sizes_2;
- sizes_2.push_back(gfx::Size(128, 128));
-
- std::vector<gfx::Size> sizes_3;
- sizes_3.push_back(gfx::Size(192, 192));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(
- CreateIcon("http://foo.com/icon_x1.png", "", sizes_1, IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon_x2.png", "", sizes_2, IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon_x3.png", "", sizes_3, IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, 48, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
-
- url = ManifestIconSelector::FindBestMatchingIcon(icons, 96, kMinimumIconSize,
- IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_x2.png", url.spec());
-
- url = ManifestIconSelector::FindBestMatchingIcon(icons, 144, kMinimumIconSize,
- IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_x3.png", url.spec());
-}
-
-TEST(ManifestIconSelector, FallbackToLargestIconLargerThanMinimum) {
- // When an icon of the correct size has not been found, we fall back to the
- // closest non-matching sizes. Make sure that the minimum passed is enforced.
- std::vector<gfx::Size> sizes_1_2;
- std::vector<gfx::Size> sizes_3;
-
- sizes_1_2.push_back(gfx::Size(47, 47));
- sizes_3.push_back(gfx::Size(95, 95));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(CreateIcon("http://foo.com/icon_x1.png", "", sizes_1_2,
- IconPurpose::ANY));
- icons.push_back(CreateIcon("http://foo.com/icon_x2.png", "", sizes_1_2,
- IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon_x3.png", "", sizes_3, IconPurpose::ANY));
-
- // Icon 3 should match.
- GURL url = ManifestIconSelector::FindBestMatchingIcon(icons, 1024, 48,
- IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_x3.png", url.spec());
-
- // Nothing matches here as the minimum is 96.
- url = ManifestIconSelector::FindBestMatchingIcon(icons, 1024, 96,
- IconPurpose::ANY);
- EXPECT_TRUE(url.is_empty());
-}
-
-TEST(ManifestIconSelector, IdealVeryCloseToMinimumMatches) {
- std::vector<gfx::Size> sizes;
- sizes.push_back(gfx::Size(2, 2));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(
- CreateIcon("http://foo.com/icon_x1.png", "", sizes, IconPurpose::ANY));
-
- GURL url =
- ManifestIconSelector::FindBestMatchingIcon(icons, 2, 1, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
-}
-
-TEST(ManifestIconSelector, SizeVeryCloseToMinimumMatches) {
- std::vector<gfx::Size> sizes;
- sizes.push_back(gfx::Size(2, 2));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(
- CreateIcon("http://foo.com/icon_x1.png", "", sizes, IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(icons, 200, 1,
- IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
-}
-
-TEST(ManifestIconSelector, NotSquareIconsAreIgnored) {
- std::vector<gfx::Size> sizes;
- sizes.push_back(gfx::Size(1024, 1023));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "", sizes, IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_TRUE(url.is_empty());
-}
-
-TEST(ManifestIconSelector, ClosestIconToIdeal) {
- // Ensure ManifestIconSelector::FindBestMatchingIcon selects the closest icon
- // to the ideal size when presented with a number of options.
- int very_small = kIdealIconSize / 4;
- int small_size = kIdealIconSize / 2;
- int bit_small = kIdealIconSize - 1;
- int bit_big = kIdealIconSize + 1;
- int big = kIdealIconSize * 2;
- int very_big = kIdealIconSize * 4;
-
- // (very_small, bit_small) => bit_small
- {
- std::vector<gfx::Size> sizes_1;
- sizes_1.push_back(gfx::Size(very_small, very_small));
-
- std::vector<gfx::Size> sizes_2;
- sizes_2.push_back(gfx::Size(bit_small, bit_small));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
- IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "", sizes_2, IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
- }
-
- // (very_small, bit_small, small_size) => bit_small
- {
- std::vector<gfx::Size> sizes_1;
- sizes_1.push_back(gfx::Size(very_small, very_small));
-
- std::vector<gfx::Size> sizes_2;
- sizes_2.push_back(gfx::Size(bit_small, bit_small));
-
- std::vector<gfx::Size> sizes_3;
- sizes_3.push_back(gfx::Size(small_size, small_size));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(CreateIcon("http://foo.com/icon_no_1.png", "", sizes_1,
- IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "", sizes_2, IconPurpose::ANY));
- icons.push_back(CreateIcon("http://foo.com/icon_no_2.png", "", sizes_3,
- IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
- }
-
- // (very_big, big) => big
- {
- std::vector<gfx::Size> sizes_1;
- sizes_1.push_back(gfx::Size(very_big, very_big));
-
- std::vector<gfx::Size> sizes_2;
- sizes_2.push_back(gfx::Size(big, big));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
- IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "", sizes_2, IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
- }
-
- // (very_big, big, bit_big) => bit_big
- {
- std::vector<gfx::Size> sizes_1;
- sizes_1.push_back(gfx::Size(very_big, very_big));
-
- std::vector<gfx::Size> sizes_2;
- sizes_2.push_back(gfx::Size(big, big));
-
- std::vector<gfx::Size> sizes_3;
- sizes_3.push_back(gfx::Size(bit_big, bit_big));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
- IconPurpose::ANY));
- icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_2,
- IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "", sizes_3, IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
- }
-
- // (bit_small, very_big) => very_big
- {
- std::vector<gfx::Size> sizes_1;
- sizes_1.push_back(gfx::Size(bit_small, bit_small));
-
- std::vector<gfx::Size> sizes_2;
- sizes_2.push_back(gfx::Size(very_big, very_big));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
- IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "", sizes_2, IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
- }
-
- // (bit_small, bit_big) => bit_big
- {
- std::vector<gfx::Size> sizes_1;
- sizes_1.push_back(gfx::Size(bit_small, bit_small));
-
- std::vector<gfx::Size> sizes_2;
- sizes_2.push_back(gfx::Size(bit_big, bit_big));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
- IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "", sizes_2, IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
- }
-}
-
-TEST(ManifestIconSelector, UseAnyIfNoIdealSize) {
- // 'any' (ie. gfx::Size(0,0)) should be used if there is no icon of a
- // ideal size.
-
- // Icon with 'any' and icon with ideal size => ideal size is chosen.
- {
- std::vector<gfx::Size> sizes_1;
- sizes_1.push_back(gfx::Size(kIdealIconSize, kIdealIconSize));
- std::vector<gfx::Size> sizes_2;
- sizes_2.push_back(gfx::Size(0, 0));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "", sizes_1, IconPurpose::ANY));
- icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_2,
- IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
- }
-
- // Icon with 'any' and icon larger than ideal size => any is chosen.
- {
- std::vector<gfx::Size> sizes_1;
- sizes_1.push_back(gfx::Size(kIdealIconSize + 1, kIdealIconSize + 1));
- std::vector<gfx::Size> sizes_2;
- sizes_2.push_back(gfx::Size(0, 0));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
- IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "", sizes_2, IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
- }
-
- // Multiple icons with 'any' => the last one is chosen.
- {
- std::vector<gfx::Size> sizes;
- sizes.push_back(gfx::Size(0, 0));
-
- std::vector<blink::Manifest::Icon> icons;
- icons.push_back(
- CreateIcon("http://foo.com/icon_no1.png", "", sizes, IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon_no2.png", "", sizes, IconPurpose::ANY));
- icons.push_back(
- CreateIcon("http://foo.com/icon.png", "", sizes, IconPurpose::ANY));
-
- GURL url = ManifestIconSelector::FindBestMatchingIcon(
- icons, kIdealIconSize * 3, kMinimumIconSize, IconPurpose::ANY);
- EXPECT_EQ("http://foo.com/icon.png", url.spec());
- }
-}
-
-} // namespace content
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 d916fcbcaad..75f94f6902d 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.cc
+++ b/chromium/content/browser/media/android/browser_media_player_manager.cc
@@ -30,7 +30,6 @@
#include "media/base/media_content_type.h"
#if !defined(USE_AURA)
-#include "content/browser/android/content_view_core.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#endif
@@ -43,7 +42,6 @@ namespace content {
// Threshold on the number of media players per renderer before we start
// attempting to release inactive media players.
const int kMediaPlayerThreshold = 1;
-const int kInvalidMediaPlayerId = -1;
static BrowserMediaPlayerManager::Factory
g_browser_media_player_manager_factory = NULL;
@@ -132,8 +130,6 @@ BrowserMediaPlayerManager::CreateMediaPlayer(
BrowserMediaPlayerManager::BrowserMediaPlayerManager(
RenderFrameHost* render_frame_host)
: render_frame_host_(render_frame_host),
- fullscreen_player_id_(kInvalidMediaPlayerId),
- fullscreen_player_is_released_(false),
web_contents_(WebContents::FromRenderFrameHost(render_frame_host)),
weak_ptr_factory_(this) {
}
@@ -151,29 +147,6 @@ BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {
players_.clear();
}
-void BrowserMediaPlayerManager::DidExitFullscreen(bool release_media_player) {
-#if defined(USE_AURA)
- // TODO(crbug.com/548024)
- NOTIMPLEMENTED();
-#else
- if (WebContentsDelegate* delegate = web_contents_->GetDelegate())
- delegate->ExitFullscreenModeForTab(web_contents_);
-
- Send(
- new MediaPlayerMsg_DidExitFullscreen(RoutingID(), fullscreen_player_id_));
- video_view_.reset();
- MediaPlayerAndroid* player = GetFullscreenPlayer();
- fullscreen_player_id_ = kInvalidMediaPlayerId;
- if (!player)
- return;
-
- if (release_media_player)
- ReleaseFullscreenPlayer(player);
- else
- player->SetVideoSurface(gl::ScopedJavaSurface());
-#endif // defined(USE_AURA)
-}
-
void BrowserMediaPlayerManager::OnTimeUpdate(
int player_id,
base::TimeDelta current_timestamp,
@@ -182,31 +155,11 @@ void BrowserMediaPlayerManager::OnTimeUpdate(
RoutingID(), player_id, current_timestamp, current_time_ticks));
}
-void BrowserMediaPlayerManager::SetVideoSurface(gl::ScopedJavaSurface surface) {
- MediaPlayerAndroid* player = GetFullscreenPlayer();
- if (!player)
- return;
-
- bool empty_surface = surface.IsEmpty();
- player->SetVideoSurface(std::move(surface));
- 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());
- }
-}
-
void BrowserMediaPlayerManager::OnMediaMetadataChanged(
int player_id, base::TimeDelta duration, int width, int height,
bool success) {
Send(new MediaPlayerMsg_MediaMetadataChanged(
RoutingID(), player_id, duration, width, height, success));
- if (fullscreen_player_id_ == player_id)
- video_view_->OnVideoSizeChanged(width, height);
}
void BrowserMediaPlayerManager::OnPlaybackComplete(int player_id) {
@@ -239,18 +192,12 @@ void BrowserMediaPlayerManager::OnSeekComplete(
void BrowserMediaPlayerManager::OnError(int player_id, int error) {
Send(new MediaPlayerMsg_MediaError(RoutingID(), player_id, error));
- if (fullscreen_player_id_ == player_id &&
- error != MediaPlayerAndroid::MEDIA_ERROR_INVALID_CODE) {
- video_view_->OnMediaPlayerError(error);
- }
}
void BrowserMediaPlayerManager::OnVideoSizeChanged(
int player_id, int width, int height) {
Send(new MediaPlayerMsg_MediaVideoSizeChanged(RoutingID(), player_id,
width, height));
- if (fullscreen_player_id_ == player_id)
- video_view_->OnVideoSizeChanged(width, height);
}
media::MediaResourceGetter*
@@ -277,10 +224,6 @@ BrowserMediaPlayerManager::GetMediaUrlInterceptor() {
return media_url_interceptor_;
}
-MediaPlayerAndroid* BrowserMediaPlayerManager::GetFullscreenPlayer() {
- return GetPlayer(fullscreen_player_id_);
-}
-
MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) {
for (const auto& player : players_) {
if (player->player_id() == player_id)
@@ -301,53 +244,6 @@ bool BrowserMediaPlayerManager::RequestPlay(int player_id,
media::DurationToMediaContentType(duration));
}
-void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) {
-#if defined(USE_AURA)
- // TODO(crbug.com/548024)
- NOTIMPLEMENTED();
-#else
- DCHECK_EQ(fullscreen_player_id_, kInvalidMediaPlayerId);
- if (video_view_) {
- fullscreen_player_id_ = player_id;
- video_view_->OpenVideo();
- return;
- }
-
- if (ContentVideoView::GetInstance()) {
- // In Android WebView, two ContentViewCores could both try to enter
- // fullscreen video, we just ignore the second one.
- Send(new MediaPlayerMsg_DidExitFullscreen(RoutingID(), player_id));
- return;
- }
-
- // There's no ContentVideoView instance so create one.
- // If we know the video frame size, use it.
- gfx::Size natural_video_size;
- MediaPlayerAndroid* player = GetFullscreenPlayer();
- if (player && player->IsPlayerReady()) {
- natural_video_size =
- gfx::Size(player->GetVideoWidth(), player->GetVideoHeight());
- }
-
- if (!web_contents()->GetDelegate())
- return;
-
- base::android::ScopedJavaLocalRef<jobject> embedder(
- web_contents()->GetDelegate()->GetContentVideoViewEmbedder());
- video_view_.reset(
- new ContentVideoView(this, web_contents(), embedder, natural_video_size));
-
- 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)
-}
-
void BrowserMediaPlayerManager::OnInitialize(
const MediaPlayerHostMsg_Initialize_Params& media_player_params) {
DestroyPlayer(media_player_params.player_id);
@@ -369,10 +265,6 @@ void BrowserMediaPlayerManager::OnStart(int player_id) {
RequestDecoderResources(player_id, false);
player->Start();
- if (fullscreen_player_id_ == player_id && fullscreen_player_is_released_) {
- video_view_->OpenVideo();
- fullscreen_player_is_released_ = false;
- }
}
void BrowserMediaPlayerManager::OnSeek(
@@ -407,8 +299,6 @@ void BrowserMediaPlayerManager::OnSuspendAndReleaseResources(int player_id) {
void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
DestroyPlayer(player_id);
- if (fullscreen_player_id_ == player_id)
- fullscreen_player_id_ = kInvalidMediaPlayerId;
}
void BrowserMediaPlayerManager::OnRequestRemotePlayback(int /* player_id */) {
@@ -453,8 +343,6 @@ void BrowserMediaPlayerManager::ReleaseResources(int player_id) {
MediaPlayerAndroid* player = GetPlayer(player_id);
if (player)
ReleasePlayer(player);
- if (player_id == fullscreen_player_id_)
- fullscreen_player_is_released_ = true;
}
std::unique_ptr<MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
@@ -497,8 +385,7 @@ bool BrowserMediaPlayerManager::RequestDecoderResources(
return true;
for (it = active_players_.begin(); it != active_players_.end(); ++it) {
- if (!it->second && !GetPlayer(it->first)->IsPlaying() &&
- fullscreen_player_id_ != it->first) {
+ if (!it->second && !GetPlayer(it->first)->IsPlaying()) {
ReleasePlayer(GetPlayer(it->first));
Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(),
(it->first)));
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 dd82592843d..aaaf4ccb74f 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.h
+++ b/chromium/content/browser/media/android/browser_media_player_manager.h
@@ -12,7 +12,6 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/time/time.h"
-#include "content/browser/android/content_video_view.h"
#include "content/common/content_export.h"
#include "ipc/ipc_message.h"
#include "media/base/android/media_player_android.h"
@@ -37,8 +36,7 @@ class WebContents;
// MediaPlayerAndroid objects are converted to IPCs and then sent to the render
// process.
class CONTENT_EXPORT BrowserMediaPlayerManager
- : public media::MediaPlayerManager,
- public ContentVideoView::Client {
+ : public media::MediaPlayerManager {
public:
// Permits embedders to provide an extended version of the class.
typedef BrowserMediaPlayerManager* (*Factory)(RenderFrameHost*);
@@ -58,10 +56,6 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
~BrowserMediaPlayerManager() override;
- // ContentVideoView::Client implementation.
- void DidExitFullscreen(bool release_media_player) override;
- void SetVideoSurface(gl::ScopedJavaSurface surface) override;
-
// Called when browser player wants the renderer media element to seek.
// Any actual seek started by renderer will be handled by browser in OnSeek().
void OnSeekRequest(int player_id, const base::TimeDelta& time_to_seek);
@@ -87,13 +81,11 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
media::MediaResourceGetter* GetMediaResourceGetter() override;
media::MediaUrlInterceptor* GetMediaUrlInterceptor() override;
- media::MediaPlayerAndroid* GetFullscreenPlayer() override;
media::MediaPlayerAndroid* GetPlayer(int player_id) override;
bool RequestPlay(int player_id, base::TimeDelta duration,
bool has_audio) override;
// Message handlers.
- virtual void OnEnterFullscreen(int player_id);
virtual void OnInitialize(
const MediaPlayerHostMsg_Initialize_Params& media_player_params);
virtual void OnStart(int player_id);
@@ -172,10 +164,6 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// will release its resources later.
ActivePlayerMap active_players_;
- // The fullscreen video view object or NULL if video is not played in
- // fullscreen.
- std::unique_ptr<ContentVideoView> video_view_;
-
// Player ID of the fullscreen media player.
int fullscreen_player_id_;
diff --git a/chromium/content/browser/media/android/browser_surface_view_manager.cc b/chromium/content/browser/media/android/browser_surface_view_manager.cc
deleted file mode 100644
index 54a75fe8150..00000000000
--- a/chromium/content/browser/media/android/browser_surface_view_manager.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/android/browser_surface_view_manager.h"
-
-#include "base/android/build_info.h"
-#include "base/trace_event/trace_event.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/media/surface_view_manager_messages_android.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/web_contents_delegate.h"
-#include "gpu/ipc/common/gpu_surface_tracker.h"
-#include "media/base/surface_manager.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace content {
-namespace {
-void SendDestroyingVideoSurfaceOnIO(int surface_id,
- const base::Closure& done_cb) {
- GpuProcessHost* host = GpuProcessHost::Get(
- GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */);
- if (host)
- host->SendDestroyingVideoSurface(surface_id, done_cb);
- else
- done_cb.Run();
-}
-} // namespace
-
-BrowserSurfaceViewManager::BrowserSurfaceViewManager(
- RenderFrameHost* render_frame_host)
- : render_frame_host_(render_frame_host),
- surface_id_(media::SurfaceManager::kNoSurfaceID) {}
-
-BrowserSurfaceViewManager::~BrowserSurfaceViewManager() {}
-
-void BrowserSurfaceViewManager::SetVideoSurface(gl::ScopedJavaSurface surface) {
- TRACE_EVENT0("media", "BrowserSurfaceViewManager::SetVideoSurface");
- if (surface.IsEmpty()) {
- DCHECK_NE(surface_id_, media::SurfaceManager::kNoSurfaceID);
- gpu::GpuSurfaceTracker::Get()->RemoveSurface(surface_id_);
- SendDestroyingVideoSurface(surface_id_);
- surface_id_ = media::SurfaceManager::kNoSurfaceID;
- } else {
- // We just use the surface tracker to allocate a surface id for us. The
- // lookup will go through the Android specific path and get the java
- // surface directly, so there's no need to add a valid native widget here.
- surface_id_ = gpu::GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget(
- gpu::GpuSurfaceTracker::SurfaceRecord(gfx::kNullAcceleratedWidget,
- surface.j_surface().obj()));
- SendSurfaceID(surface_id_);
- }
-}
-
-void BrowserSurfaceViewManager::DidExitFullscreen(bool release_media_player) {
- DVLOG(3) << __func__;
- content_video_view_.reset();
-}
-
-void BrowserSurfaceViewManager::OnCreateFullscreenSurface(
- const gfx::Size& video_natural_size) {
- // If we are in virtual reality, no surface view is needed so just return.
- // TODO(http://crbug.com/673886): Support overlay surfaces in VR using GVR
- // reprojection video surface.
- RenderWidgetHostViewBase * rwhvb =
- static_cast<RenderWidgetHostViewBase*>(render_frame_host_->GetView());
- if (rwhvb->IsInVR()) {
- SendSurfaceID(media::SurfaceManager::kNoSurfaceID);
- return;
- }
-
- // 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;
- }
-
- WebContents* web_contents =
- WebContents::FromRenderFrameHost(render_frame_host_);
- if (!web_contents->GetDelegate()) {
- SendSurfaceID(media::SurfaceManager::kNoSurfaceID);
- return;
- }
- content_video_view_.reset(new ContentVideoView(
- this, web_contents,
- web_contents->GetDelegate()->GetContentVideoViewEmbedder(),
- 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));
-}
-
-void BrowserSurfaceViewManager::SendDestroyingVideoSurface(int surface_id) {
- base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- // Unretained is okay because we're waiting on the callback.
- if (BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&SendDestroyingVideoSurfaceOnIO, surface_id,
- base::Bind(&base::WaitableEvent::Signal,
- base::Unretained(&waiter))))) {
- base::ThreadRestrictions::ScopedAllowWait allow_wait;
- waiter.Wait();
- }
-}
-
-} // 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
deleted file mode 100644
index 08039efa5e9..00000000000
--- a/chromium/content/browser/media/android/browser_surface_view_manager.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEDIA_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 final
- : public ContentVideoView::Client {
- public:
- explicit BrowserSurfaceViewManager(RenderFrameHost* render_frame_host);
- ~BrowserSurfaceViewManager();
-
- // ContentVideoView::Client overrides.
- void SetVideoSurface(gl::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);
-
- // Synchronously notify the decoder that the surface is being destroyed so it
- // can stop rendering to it. This sends a message to the GPU process. Without
- // this, the MediaCodec decoder will start throwing IllegalStateException, and
- // crash on some devices (http://crbug.com/598408, http://crbug.com/600454).
- void SendDestroyingVideoSurface(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_player_renderer.cc b/chromium/content/browser/media/android/media_player_renderer.cc
index 2c5926260df..05d7c6a039d 100644
--- a/chromium/content/browser/media/android/media_player_renderer.cc
+++ b/chromium/content/browser/media/android/media_player_renderer.cc
@@ -298,11 +298,6 @@ void MediaPlayerRenderer::OnVideoSizeChanged(int player_id,
}
}
-media::MediaPlayerAndroid* MediaPlayerRenderer::GetFullscreenPlayer() {
- NOTREACHED();
- return nullptr;
-}
-
media::MediaPlayerAndroid* MediaPlayerRenderer::GetPlayer(int player_id) {
NOTREACHED();
return nullptr;
diff --git a/chromium/content/browser/media/android/media_player_renderer.h b/chromium/content/browser/media/android/media_player_renderer.h
index 44ab9e046be..ed0bd5822df 100644
--- a/chromium/content/browser/media/android/media_player_renderer.h
+++ b/chromium/content/browser/media/android/media_player_renderer.h
@@ -86,7 +86,6 @@ class CONTENT_EXPORT MediaPlayerRenderer : public media::Renderer,
const base::TimeDelta& current_time) override;
void OnError(int player_id, int error) override;
void OnVideoSizeChanged(int player_id, int width, int height) override;
- media::MediaPlayerAndroid* GetFullscreenPlayer() override;
media::MediaPlayerAndroid* GetPlayer(int player_id) override;
bool RequestPlay(int player_id,
base::TimeDelta duration,
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 c6ac9e5e68a..25368e310fc 100644
--- a/chromium/content/browser/media/android/media_web_contents_observer_android.cc
+++ b/chromium/content/browser/media/android/media_web_contents_observer_android.cc
@@ -8,11 +8,9 @@
#include "base/memory/ptr_util.h"
#include "content/browser/media/android/browser_media_player_manager.h"
-#include "content/browser/media/android/browser_surface_view_manager.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/media/media_player_delegate_messages.h"
#include "content/common/media/media_player_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"
@@ -53,19 +51,6 @@ MediaWebContentsObserverAndroid::GetMediaPlayerManager(
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.get();
-
- BrowserSurfaceViewManager* manager =
- new BrowserSurfaceViewManager(render_frame_host);
- surface_view_managers_[render_frame_host] = base::WrapUnique(manager);
- return manager;
-}
-
void MediaWebContentsObserverAndroid::SuspendAllMediaPlayers() {
web_contents()->ForEachFrame(
base::BindRepeating(&SuspendAllMediaPlayersInRenderFrame));
@@ -94,7 +79,6 @@ void MediaWebContentsObserverAndroid::RenderFrameDeleted(
MediaWebContentsObserver::RenderFrameDeleted(render_frame_host);
media_player_managers_.erase(render_frame_host);
- surface_view_managers_.erase(render_frame_host);
}
bool MediaWebContentsObserverAndroid::OnMessageReceived(
@@ -106,9 +90,6 @@ bool MediaWebContentsObserverAndroid::OnMessageReceived(
if (OnMediaPlayerMessageReceived(msg, render_frame_host))
return true;
- if (OnSurfaceViewManagerMessageReceived(msg, render_frame_host))
- return true;
-
return false;
}
@@ -130,9 +111,6 @@ bool MediaWebContentsObserverAndroid::OnMediaPlayerMessageReceived(
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserverAndroid, msg)
- IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_EnterFullscreen,
- media_player_manager,
- BrowserMediaPlayerManager::OnEnterFullscreen)
IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Initialize, media_player_manager,
BrowserMediaPlayerManager::OnInitialize)
IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Start, media_player_manager,
@@ -165,20 +143,4 @@ bool MediaWebContentsObserverAndroid::OnMediaPlayerMessageReceived(
return handled;
}
-bool MediaWebContentsObserverAndroid::OnSurfaceViewManagerMessageReceived(
- const IPC::Message& msg,
- RenderFrameHost* render_frame_host) {
- bool handled = true;
- 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;
-}
-
} // namespace content
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 e330e45009e..13da22f5c16 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
@@ -21,7 +21,6 @@ enum class MediaContentType;
namespace content {
class BrowserMediaPlayerManager;
-class BrowserSurfaceViewManager;
// This class adds Android specific extensions to the MediaWebContentsObserver.
class CONTENT_EXPORT MediaWebContentsObserverAndroid
@@ -39,8 +38,6 @@ class CONTENT_EXPORT MediaWebContentsObserverAndroid
// returned pointer.
BrowserMediaPlayerManager* GetMediaPlayerManager(
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
@@ -72,20 +69,12 @@ class CONTENT_EXPORT MediaWebContentsObserverAndroid
bool OnMediaPlayerMessageReceived(const IPC::Message& message,
RenderFrameHost* render_frame_host);
- bool OnSurfaceViewManagerMessageReceived(const IPC::Message& message,
- RenderFrameHost* render_frame_host);
-
// Map from RenderFrameHost* to BrowserMediaPlayerManager.
using MediaPlayerManagerMap =
std::unordered_map<RenderFrameHost*,
std::unique_ptr<BrowserMediaPlayerManager>>;
MediaPlayerManagerMap media_player_managers_;
- using SurfaceViewManagerMap =
- std::unordered_map<RenderFrameHost*,
- std::unique_ptr<BrowserSurfaceViewManager>>;
- SurfaceViewManagerMap surface_view_managers_;
-
DISALLOW_COPY_AND_ASSIGN(MediaWebContentsObserverAndroid);
};
diff --git a/chromium/content/browser/media/audible_metrics_unittest.cc b/chromium/content/browser/media/audible_metrics_unittest.cc
index d122e3178c2..a9f1b47e483 100644
--- a/chromium/content/browser/media/audible_metrics_unittest.cc
+++ b/chromium/content/browser/media/audible_metrics_unittest.cc
@@ -5,9 +5,9 @@
#include "content/browser/media/audible_metrics.h"
#include "base/metrics/histogram_samples.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/metrics/user_action_tester.h"
#include "base/test/simple_test_tick_clock.h"
-#include "base/test/user_action_tester.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
diff --git a/chromium/content/browser/media/audio_input_stream_broker.cc b/chromium/content/browser/media/audio_input_stream_broker.cc
index e0a2f97fdda..b8cc22b65e5 100644
--- a/chromium/content/browser/media/audio_input_stream_broker.cc
+++ b/chromium/content/browser/media/audio_input_stream_broker.cc
@@ -52,8 +52,8 @@ AudioInputStreamBroker::AudioInputStreamBroker(
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("audio", "AudioInputStreamBroker", this);
// Unretained is safe because |this| owns |renderer_factory_client_|.
- renderer_factory_client_.set_connection_error_handler(
- base::BindOnce(&AudioInputStreamBroker::Cleanup, base::Unretained(this)));
+ renderer_factory_client_.set_connection_error_handler(base::BindOnce(
+ &AudioInputStreamBroker::ClientBindingLost, base::Unretained(this)));
// Notify RenderProcessHost about input stream so the renderer is not
// background.
@@ -170,7 +170,7 @@ void AudioInputStreamBroker::DidStartRecording() {
void AudioInputStreamBroker::StreamCreated(
media::mojom::AudioInputStreamPtr stream,
- media::mojom::AudioDataPipePtr data_pipe,
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
bool initially_muted,
const base::Optional<base::UnguessableToken>& stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -210,6 +210,12 @@ void AudioInputStreamBroker::ObserverBindingLost(
Cleanup();
}
+void AudioInputStreamBroker::ClientBindingLost() {
+ disconnect_reason_ = media::mojom::AudioInputStreamObserver::
+ DisconnectReason::kTerminatedByClient;
+ Cleanup();
+}
+
void AudioInputStreamBroker::Cleanup() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chromium/content/browser/media/audio_input_stream_broker.h b/chromium/content/browser/media/audio_input_stream_broker.h
index 524fb3408e3..910453c4977 100644
--- a/chromium/content/browser/media/audio_input_stream_broker.h
+++ b/chromium/content/browser/media/audio_input_stream_broker.h
@@ -49,12 +49,12 @@ class CONTENT_EXPORT AudioInputStreamBroker final
private:
void StreamCreated(media::mojom::AudioInputStreamPtr stream,
- media::mojom::AudioDataPipePtr data_pipe,
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
bool initially_muted,
const base::Optional<base::UnguessableToken>& stream_id);
void ObserverBindingLost(uint32_t reason, const std::string& description);
-
+ void ClientBindingLost();
void Cleanup();
const std::string device_id_;
diff --git a/chromium/content/browser/media/audio_input_stream_broker_unittest.cc b/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
index 809f63f1504..4adcdff9b3c 100644
--- a/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
+++ b/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
@@ -56,7 +56,7 @@ class MockRendererAudioInputStreamFactoryClient
void StreamCreated(
media::mojom::AudioInputStreamPtr input_stream,
media::mojom::AudioInputStreamClientRequest client_request,
- media::mojom::AudioDataPipePtr data_pipe,
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
bool initially_muted,
const base::Optional<base::UnguessableToken>& stream_id) override {
EXPECT_TRUE(stream_id.has_value());
@@ -188,7 +188,8 @@ TEST(AudioInputStreamBrokerTest, StreamCreationSuccess_Propagates) {
base::SyncSocket socket1, socket2;
base::SyncSocket::CreatePair(&socket1, &socket2);
std::move(stream_request_data.created_callback)
- .Run({base::in_place, mojo::SharedBufferHandle::Create(shmem_size),
+ .Run({base::in_place,
+ base::ReadOnlySharedMemoryRegion::Create(shmem_size).region,
mojo::WrapPlatformFile(socket1.Release())},
kInitiallyMuted, base::UnguessableToken::Create());
diff --git a/chromium/content/browser/media/audio_log_factory.cc b/chromium/content/browser/media/audio_log_factory.cc
new file mode 100644
index 00000000000..f7ec4fef3c1
--- /dev/null
+++ b/chromium/content/browser/media/audio_log_factory.cc
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights 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/audio_log_factory.h"
+
+#include <utility>
+
+#include "content/browser/media/media_internals.h"
+
+namespace content {
+
+AudioLogFactory::AudioLogFactory() = default;
+AudioLogFactory::~AudioLogFactory() = default;
+
+void AudioLogFactory::CreateAudioLog(
+ media::mojom::AudioLogComponent component,
+ int32_t component_id,
+ media::mojom::AudioLogRequest audio_log_request) {
+ MediaInternals::GetInstance()->CreateMojoAudioLog(
+ static_cast<media::AudioLogFactory::AudioComponent>(component),
+ component_id, std::move(audio_log_request));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/audio_log_factory.h b/chromium/content/browser/media/audio_log_factory.h
new file mode 100644
index 00000000000..513d5a48a89
--- /dev/null
+++ b/chromium/content/browser/media/audio_log_factory.h
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All 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_AUDIO_LOG_FACTORY_H_
+#define CONTENT_BROWSER_MEDIA_AUDIO_LOG_FACTORY_H_
+
+#include "media/mojo/interfaces/audio_logging.mojom.h"
+
+namespace content {
+
+class AudioLogFactory : public media::mojom::AudioLogFactory {
+ public:
+ AudioLogFactory();
+ ~AudioLogFactory() override;
+
+ // media::mojom::AudioLogFactory implementation.
+ void CreateAudioLog(media::mojom::AudioLogComponent component,
+ int32_t component_id,
+ media::mojom::AudioLogRequest audio_log_request) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AudioLogFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_AUDIO_LOG_FACTORY_H_
diff --git a/chromium/content/browser/media/audio_loopback_stream_broker.cc b/chromium/content/browser/media/audio_loopback_stream_broker.cc
index d7cba0187ea..884508c44f3 100644
--- a/chromium/content/browser/media/audio_loopback_stream_broker.cc
+++ b/chromium/content/browser/media/audio_loopback_stream_broker.cc
@@ -141,7 +141,7 @@ void AudioLoopbackStreamBroker::DidStartRecording() {
void AudioLoopbackStreamBroker::StreamCreated(
media::mojom::AudioInputStreamPtr stream,
- media::mojom::AudioDataPipePtr data_pipe) {
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!data_pipe) {
diff --git a/chromium/content/browser/media/audio_loopback_stream_broker.h b/chromium/content/browser/media/audio_loopback_stream_broker.h
index 71778564a65..9853b4c9768 100644
--- a/chromium/content/browser/media/audio_loopback_stream_broker.h
+++ b/chromium/content/browser/media/audio_loopback_stream_broker.h
@@ -47,7 +47,7 @@ class CONTENT_EXPORT AudioLoopbackStreamBroker final
private:
void StreamCreated(media::mojom::AudioInputStreamPtr stream,
- media::mojom::AudioDataPipePtr data_pipe);
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe);
void Cleanup();
const std::unique_ptr<AudioStreamBrokerFactory::LoopbackSource> source_;
diff --git a/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc b/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc
index cfe6cc7ccb3..14923ed61e4 100644
--- a/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc
+++ b/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc
@@ -71,7 +71,7 @@ class MockRendererAudioInputStreamFactoryClient
void StreamCreated(
media::mojom::AudioInputStreamPtr input_stream,
media::mojom::AudioInputStreamClientRequest client_request,
- media::mojom::AudioDataPipePtr data_pipe,
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
bool initially_muted,
const base::Optional<base::UnguessableToken>& stream_id) override {
// Loopback streams have no stream ids.
@@ -219,7 +219,8 @@ TEST(AudioLoopbackStreamBrokerTest, StreamCreationSuccess_Propagates) {
base::SyncSocket socket1, socket2;
base::SyncSocket::CreatePair(&socket1, &socket2);
std::move(stream_request_data.created_callback)
- .Run({base::in_place, mojo::SharedBufferHandle::Create(shmem_size),
+ .Run({base::in_place,
+ base::ReadOnlySharedMemoryRegion::Create(shmem_size).region,
mojo::WrapPlatformFile(socket1.Release())});
EXPECT_CALL(env.renderer_factory_client, OnStreamCreated());
@@ -248,7 +249,8 @@ TEST(AudioLoopbackStreamBrokerTest, MutedStreamCreation_Mutes) {
base::SyncSocket socket1, socket2;
base::SyncSocket::CreatePair(&socket1, &socket2);
std::move(stream_request_data.created_callback)
- .Run({base::in_place, mojo::SharedBufferHandle::Create(shmem_size),
+ .Run({base::in_place,
+ base::ReadOnlySharedMemoryRegion::Create(shmem_size).region,
mojo::WrapPlatformFile(socket1.Release())});
EXPECT_CALL(env.renderer_factory_client, OnStreamCreated());
@@ -277,7 +279,8 @@ TEST(AudioLoopbackStreamBrokerTest, SourceGone_CallsDeleter) {
base::SyncSocket socket1, socket2;
base::SyncSocket::CreatePair(&socket1, &socket2);
std::move(stream_request_data.created_callback)
- .Run({base::in_place, mojo::SharedBufferHandle::Create(shmem_size),
+ .Run({base::in_place,
+ base::ReadOnlySharedMemoryRegion::Create(shmem_size).region,
mojo::WrapPlatformFile(socket1.Release())});
EXPECT_CALL(env.renderer_factory_client, OnStreamCreated());
diff --git a/chromium/content/browser/media/audio_output_stream_broker.cc b/chromium/content/browser/media/audio_output_stream_broker.cc
index 21cf65ea694..0d2f3deafe2 100644
--- a/chromium/content/browser/media/audio_output_stream_broker.cc
+++ b/chromium/content/browser/media/audio_output_stream_broker.cc
@@ -48,7 +48,7 @@ AudioOutputStreamBroker::AudioOutputStreamBroker(
// Unretained is safe because |this| owns |client_|
client_.set_connection_error_handler(base::BindOnce(
- &AudioOutputStreamBroker::Cleanup, base::Unretained(this)));
+ &AudioOutputStreamBroker::ClientBindingLost, base::Unretained(this)));
}
AudioOutputStreamBroker::~AudioOutputStreamBroker() {
@@ -101,7 +101,7 @@ void AudioOutputStreamBroker::CreateStream(
void AudioOutputStreamBroker::StreamCreated(
media::mojom::AudioOutputStreamPtr stream,
- media::mojom::AudioDataPipePtr data_pipe) {
+ media::mojom::ReadWriteAudioDataPipePtr data_pipe) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "CreateStream", this, "success",
!!data_pipe);
@@ -149,6 +149,12 @@ void AudioOutputStreamBroker::ObserverBindingLost(
Cleanup();
}
+void AudioOutputStreamBroker::ClientBindingLost() {
+ disconnect_reason_ = media::mojom::AudioOutputStreamObserver::
+ DisconnectReason::kTerminatedByClient;
+ Cleanup();
+}
+
void AudioOutputStreamBroker::Cleanup() {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
std::move(deleter_).Run(this);
diff --git a/chromium/content/browser/media/audio_output_stream_broker.h b/chromium/content/browser/media/audio_output_stream_broker.h
index d997649ff6d..f2480aa0140 100644
--- a/chromium/content/browser/media/audio_output_stream_broker.h
+++ b/chromium/content/browser/media/audio_output_stream_broker.h
@@ -44,8 +44,9 @@ class CONTENT_EXPORT AudioOutputStreamBroker final : public AudioStreamBroker {
private:
void StreamCreated(media::mojom::AudioOutputStreamPtr stream,
- media::mojom::AudioDataPipePtr data_pipe);
+ media::mojom::ReadWriteAudioDataPipePtr data_pipe);
void ObserverBindingLost(uint32_t reason, const std::string& description);
+ void ClientBindingLost();
void Cleanup();
SEQUENCE_CHECKER(owning_sequence_);
diff --git a/chromium/content/browser/media/audio_output_stream_broker_unittest.cc b/chromium/content/browser/media/audio_output_stream_broker_unittest.cc
index 5427db631be..7a9d488e322 100644
--- a/chromium/content/browser/media/audio_output_stream_broker_unittest.cc
+++ b/chromium/content/browser/media/audio_output_stream_broker_unittest.cc
@@ -53,7 +53,7 @@ class MockAudioOutputStreamProviderClient
~MockAudioOutputStreamProviderClient() override {}
void Created(media::mojom::AudioOutputStreamPtr,
- media::mojom::AudioDataPipePtr) override {
+ media::mojom::ReadWriteAudioDataPipePtr) override {
OnCreated();
}
@@ -197,7 +197,7 @@ TEST(AudioOutputStreamBrokerTest, StreamCreationSuccess_Propagates) {
base::SyncSocket socket1, socket2;
base::SyncSocket::CreatePair(&socket1, &socket2);
std::move(stream_request_data.created_callback)
- .Run({base::in_place, mojo::SharedBufferHandle::Create(kShMemSize),
+ .Run({base::in_place, base::UnsafeSharedMemoryRegion::Create(kShMemSize),
mojo::WrapPlatformFile(socket1.Release())});
EXPECT_CALL(env.provider_client, OnCreated());
diff --git a/chromium/content/browser/media/audio_stream_monitor.cc b/chromium/content/browser/media/audio_stream_monitor.cc
index 67c0baebe0b..324f3105a21 100644
--- a/chromium/content/browser/media/audio_stream_monitor.cc
+++ b/chromium/content/browser/media/audio_stream_monitor.cc
@@ -192,7 +192,7 @@ void AudioStreamMonitor::UpdateStreams() {
if (is_audible_ != was_audible) {
MaybeToggle();
- web_contents_->OnAudioStateChanged(is_audible_);
+ web_contents_->OnAudioStateChanged();
}
}
diff --git a/chromium/content/browser/media/capture/aura_window_capture_machine.cc b/chromium/content/browser/media/capture/aura_window_capture_machine.cc
deleted file mode 100644
index 2f6caae4995..00000000000
--- a/chromium/content/browser/media/capture/aura_window_capture_machine.cc
+++ /dev/null
@@ -1,485 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/capture/aura_window_capture_machine.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "components/viz/common/frame_sinks/copy_output_request.h"
-#include "components/viz/common/frame_sinks/copy_output_result.h"
-#include "components/viz/common/gl_helper.h"
-#include "content/browser/compositor/image_transport_factory.h"
-#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
-#include "media/base/video_util.h"
-#include "media/capture/content/thread_safe_capture_oracle.h"
-#include "media/capture/content/video_capture_oracle.h"
-#include "media/capture/video_capture_types.h"
-#include "services/device/public/mojom/constants.mojom.h"
-#include "services/device/public/mojom/wake_lock_provider.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "skia/ext/image_operations.h"
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_observer.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/cursor/cursors_aura.h"
-#include "ui/compositor/compositor.h"
-#include "ui/compositor/dip_util.h"
-#include "ui/compositor/layer.h"
-
-namespace content {
-
-AuraWindowCaptureMachine::AuraWindowCaptureMachine()
- : desktop_window_(nullptr),
- screen_capture_(false),
- frame_capture_active_(true),
- weak_factory_(this) {}
-
-AuraWindowCaptureMachine::~AuraWindowCaptureMachine() {}
-
-void AuraWindowCaptureMachine::Start(
- const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
- const media::VideoCaptureParams& params,
- const base::Callback<void(bool)> callback) {
- // Starts the capture machine asynchronously.
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&AuraWindowCaptureMachine::InternalStart,
- base::Unretained(this),
- oracle_proxy,
- params),
- callback);
-}
-
-bool AuraWindowCaptureMachine::InternalStart(
- const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
- const media::VideoCaptureParams& params) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- // The window might be destroyed between SetWindow() and Start().
- if (!desktop_window_)
- return false;
-
- // If the associated layer is already destroyed then return failure.
- ui::Layer* layer = desktop_window_->layer();
- if (!layer)
- return false;
-
- DCHECK(oracle_proxy);
- oracle_proxy_ = oracle_proxy;
- capture_params_ = params;
-
- // Update capture size.
- UpdateCaptureSize();
-
- // Start observing compositor updates.
- aura::WindowTreeHost* const host = desktop_window_->GetHost();
- ui::Compositor* const compositor = host ? host->compositor() : nullptr;
- if (!compositor)
- return false;
- compositor->AddAnimationObserver(this);
-
- // Start observing for GL context losses.
- compositor->context_factory()->AddObserver(this);
-
- DCHECK(!wake_lock_);
- // Request Wake Lock. In some testing contexts, the service manager
- // connection isn't initialized.
- if (ServiceManagerConnection::GetForProcess()) {
- service_manager::Connector* connector =
- ServiceManagerConnection::GetForProcess()->GetConnector();
- DCHECK(connector);
- device::mojom::WakeLockProviderPtr wake_lock_provider;
- connector->BindInterface(device::mojom::kServiceName,
- mojo::MakeRequest(&wake_lock_provider));
- wake_lock_provider->GetWakeLockWithoutContext(
- device::mojom::WakeLockType::kPreventDisplaySleep,
- device::mojom::WakeLockReason::kOther, "Aura window or desktop capture",
- mojo::MakeRequest(&wake_lock_));
-
- wake_lock_->RequestWakeLock();
- }
-
- return true;
-}
-
-void AuraWindowCaptureMachine::Suspend() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&AuraWindowCaptureMachine::InternalSuspend,
- base::Unretained(this)));
-}
-
-void AuraWindowCaptureMachine::InternalSuspend() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DVLOG(1) << "Suspending frame capture and delivery.";
- frame_capture_active_ = false;
-}
-
-void AuraWindowCaptureMachine::Resume() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&AuraWindowCaptureMachine::InternalResume,
- base::Unretained(this)));
-}
-
-void AuraWindowCaptureMachine::InternalResume() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DVLOG(1) << "Resuming frame capture and delivery.";
- frame_capture_active_ = true;
- // Whenever capture resumes, capture a refresh frame immediately to make sure
- // no content updates are missing from the video stream.
- MaybeCaptureForRefresh();
-}
-
-void AuraWindowCaptureMachine::Stop(const base::Closure& callback) {
- // Stops the capture machine asynchronously.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&AuraWindowCaptureMachine::InternalStop,
- base::Unretained(this), callback));
-}
-
-void AuraWindowCaptureMachine::InternalStop(const base::Closure& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- // Cancel any and all outstanding callbacks owned by external modules.
- weak_factory_.InvalidateWeakPtrs();
-
- if (wake_lock_)
- wake_lock_->CancelWakeLock();
- // Stop observing compositor and window events.
- if (desktop_window_) {
- if (aura::WindowTreeHost* host = desktop_window_->GetHost()) {
- if (ui::Compositor* compositor = host->compositor()) {
- compositor->RemoveAnimationObserver(this);
- compositor->context_factory()->RemoveObserver(this);
- }
- }
- desktop_window_->RemoveObserver(this);
- desktop_window_ = nullptr;
- cursor_renderer_.reset();
- }
-
- OnLostResources();
-
- callback.Run();
-}
-
-void AuraWindowCaptureMachine::MaybeCaptureForRefresh() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(
- &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(CursorRenderer::CURSOR_DISPLAYED_ALWAYS));
- cursor_renderer_->SetTargetView(window);
-
- // Start observing window events.
- desktop_window_->AddObserver(this);
-
- // We must store this for the UMA reporting in DidCopyOutput() as
- // desktop_window_ might be destroyed at that point.
- screen_capture_ = window->IsRootWindow();
- IncrementDesktopCaptureCounter(screen_capture_ ? SCREEN_CAPTURER_CREATED
- : WINDOW_CAPTURER_CREATED);
-}
-
-void AuraWindowCaptureMachine::UpdateCaptureSize() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (oracle_proxy_ && desktop_window_) {
- ui::Layer* layer = desktop_window_->layer();
- oracle_proxy_->UpdateCaptureSize(ui::ConvertSizeToPixel(
- layer, layer->bounds().size()));
- }
-}
-
-void AuraWindowCaptureMachine::Capture(base::TimeTicks event_time) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- // Do not capture if the desktop window is already destroyed.
- if (!desktop_window_)
- return;
-
- scoped_refptr<media::VideoFrame> frame;
- media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
-
- // TODO(miu): Need to fix this so the compositor is providing the presentation
- // timestamps and damage regions, to leverage the frame timestamp rewriting
- // logic. http://crbug.com/492839
- const base::TimeTicks start_time = base::TimeTicks::Now();
- media::VideoCaptureOracle::Event event;
- if (event_time.is_null()) {
- event = media::VideoCaptureOracle::kRefreshRequest;
- event_time = start_time;
- } else {
- event = media::VideoCaptureOracle::kCompositorUpdate;
- }
- if (oracle_proxy_->ObserveEventAndDecideCapture(
- event, gfx::Rect(), event_time, &frame, &capture_frame_cb)) {
- std::unique_ptr<viz::CopyOutputRequest> request =
- std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
- base::BindOnce(&AuraWindowCaptureMachine::DidCopyOutput,
- weak_factory_.GetWeakPtr(), std::move(frame),
- event_time, start_time, capture_frame_cb));
- gfx::Rect window_rect = gfx::Rect(desktop_window_->bounds().width(),
- desktop_window_->bounds().height());
- request->set_area(window_rect);
- desktop_window_->layer()->RequestCopyOfOutput(std::move(request));
- }
-}
-
-void AuraWindowCaptureMachine::DidCopyOutput(
- scoped_refptr<media::VideoFrame> video_frame,
- base::TimeTicks event_time,
- base::TimeTicks start_time,
- const CaptureFrameCallback& capture_frame_cb,
- std::unique_ptr<viz::CopyOutputResult> result) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- static bool first_call = true;
-
- const bool succeeded = ProcessCopyOutputResponse(
- video_frame, event_time, capture_frame_cb, std::move(result));
-
- 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.
- if (screen_capture_) {
- UMA_HISTOGRAM_TIMES(kUmaScreenCaptureTime, capture_time);
- } else {
- UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time);
- }
-
- if (first_call) {
- first_call = false;
- if (screen_capture_) {
- IncrementDesktopCaptureCounter(succeeded ? FIRST_SCREEN_CAPTURE_SUCCEEDED
- : FIRST_SCREEN_CAPTURE_FAILED);
- } else {
- IncrementDesktopCaptureCounter(succeeded
- ? FIRST_WINDOW_CAPTURE_SUCCEEDED
- : FIRST_WINDOW_CAPTURE_FAILED);
- }
- }
-
- // If ProcessCopyOutputResponse() failed, it will not run |capture_frame_cb|,
- // so do that now.
- if (!succeeded)
- capture_frame_cb.Run(std::move(video_frame), event_time, false);
-}
-
-bool AuraWindowCaptureMachine::ProcessCopyOutputResponse(
- scoped_refptr<media::VideoFrame> video_frame,
- base::TimeTicks event_time,
- const CaptureFrameCallback& capture_frame_cb,
- std::unique_ptr<viz::CopyOutputResult> result) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK_EQ(result->format(), viz::CopyOutputResult::Format::RGBA_TEXTURE);
-
- if (!desktop_window_) {
- VLOG(1) << "Ignoring CopyOutputResult: Capture target has gone away.";
- return false;
- }
- if (result->IsEmpty()) {
- VLOG(1) << "CopyOutputRequest failed: Empty result.";
- return false;
- }
- 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
- // (see CopyRGBToVideoFrame). They need to be even for the UV samples to
- // line up correctly.
- // The video frame's visible_rect() and the result's size() are both physical
- // 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);
- if (region_in_frame.IsEmpty()) {
- VLOG(1) << "Aborting capture: Computed empty letterboxed content region.";
- return false;
- }
-
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- viz::GLHelper* gl_helper = factory->GetGLHelper();
- if (!gl_helper) {
- VLOG(1) << "Aborting capture: No GLHelper available for YUV readback.";
- return false;
- }
-
- gpu::Mailbox mailbox = result->GetTextureResult()->mailbox;
- gpu::SyncToken sync_token = result->GetTextureResult()->sync_token;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback =
- result->TakeTextureOwnership();
-
- if (!yuv_readback_pipeline_)
- yuv_readback_pipeline_ = gl_helper->CreateReadbackPipelineYUV(true, true);
- viz::GLHelper::ScalerInterface* const scaler =
- yuv_readback_pipeline_->scaler();
- const gfx::Vector2d scale_from(result->size().width(),
- result->size().height());
- const gfx::Vector2d scale_to(region_in_frame.width(),
- region_in_frame.height());
- if (scale_from == scale_to) {
- if (scaler)
- yuv_readback_pipeline_->SetScaler(nullptr);
- } else if (!scaler || !scaler->IsSameScaleRatio(scale_from, scale_to)) {
- std::unique_ptr<viz::GLHelper::ScalerInterface> fast_scaler =
- gl_helper->CreateScaler(viz::GLHelper::SCALER_QUALITY_FAST, scale_from,
- scale_to, false, false, false);
- DCHECK(
- fast_scaler); // Arguments to CreateScaler() should never be invalid.
- yuv_readback_pipeline_->SetScaler(std::move(fast_scaler));
- }
-
- yuv_readback_pipeline_->ReadbackYUV(
- mailbox, sync_token, result->size(), gfx::Rect(region_in_frame.size()),
- video_frame->stride(media::VideoFrame::kYPlane),
- video_frame->data(media::VideoFrame::kYPlane),
- video_frame->stride(media::VideoFrame::kUPlane),
- video_frame->data(media::VideoFrame::kUPlane),
- video_frame->stride(media::VideoFrame::kVPlane),
- video_frame->data(media::VideoFrame::kVPlane), region_in_frame.origin(),
- base::Bind(&CopyOutputFinishedForVideo, weak_factory_.GetWeakPtr(),
- event_time, capture_frame_cb, video_frame, region_in_frame,
- base::Passed(&release_callback)));
- media::LetterboxVideoFrame(video_frame.get(), region_in_frame);
- return true;
-}
-
-using CaptureFrameCallback =
- media::ThreadSafeCaptureOracle::CaptureFrameCallback;
-
-void AuraWindowCaptureMachine::CopyOutputFinishedForVideo(
- base::WeakPtr<AuraWindowCaptureMachine> machine,
- base::TimeTicks event_time,
- const CaptureFrameCallback& capture_frame_cb,
- scoped_refptr<media::VideoFrame> target,
- const gfx::Rect& region_in_frame,
- std::unique_ptr<viz::SingleReleaseCallback> release_callback,
- bool result) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- release_callback->Run(gpu::SyncToken(), false);
-
- // Render the cursor and deliver the captured frame if the
- // AuraWindowCaptureMachine has not been stopped (i.e., the WeakPtr is
- // still valid).
- if (machine) {
- if (machine->cursor_renderer_ && result)
- machine->cursor_renderer_->RenderOnVideoFrame(target.get(),
- region_in_frame, nullptr);
- } else {
- VLOG(1) << "Aborting capture: AuraWindowCaptureMachine has gone away.";
- result = false;
- }
-
- capture_frame_cb.Run(std::move(target), event_time, result);
-}
-
-void AuraWindowCaptureMachine::OnWindowBoundsChanged(
- aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds,
- ui::PropertyChangeReason reason) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(desktop_window_ && window == desktop_window_);
-
- // Post a task to update capture size after first returning to the event loop.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&AuraWindowCaptureMachine::UpdateCaptureSize,
- weak_factory_.GetWeakPtr()));
-}
-
-void AuraWindowCaptureMachine::OnWindowDestroying(aura::Window* window) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- InternalStop(base::DoNothing());
-
- oracle_proxy_->ReportError(FROM_HERE, "OnWindowDestroying()");
-}
-
-void AuraWindowCaptureMachine::OnWindowAddedToRootWindow(
- aura::Window* window) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(window == desktop_window_);
-
- if (aura::WindowTreeHost* host = window->GetHost()) {
- if (ui::Compositor* compositor = host->compositor())
- compositor->AddAnimationObserver(this);
- }
-}
-
-void AuraWindowCaptureMachine::OnWindowRemovingFromRootWindow(
- aura::Window* window,
- aura::Window* new_root) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(window == desktop_window_);
-
- if (aura::WindowTreeHost* host = window->GetHost()) {
- if (ui::Compositor* compositor = host->compositor()) {
- compositor->RemoveAnimationObserver(this);
- compositor->context_factory()->RemoveObserver(this);
- }
- }
-}
-
-void AuraWindowCaptureMachine::OnAnimationStep(base::TimeTicks timestamp) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- 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
- if (frame_capture_active_)
- Capture(timestamp);
-}
-
-void AuraWindowCaptureMachine::OnCompositingShuttingDown(
- ui::Compositor* compositor) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- compositor->RemoveAnimationObserver(this);
- compositor->context_factory()->RemoveObserver(this);
-}
-
-void AuraWindowCaptureMachine::OnLostResources() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- yuv_readback_pipeline_.reset();
-}
-
-} // 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
deleted file mode 100644
index d6067419741..00000000000
--- a/chromium/content/browser/media/capture/aura_window_capture_machine.h
+++ /dev/null
@@ -1,150 +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_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/weak_ptr.h"
-#include "content/browser/media/capture/cursor_renderer_aura.h"
-#include "media/capture/content/screen_capture_device_core.h"
-#include "services/device/public/mojom/wake_lock.mojom.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 viz {
-class CopyOutputResult;
-class ReadbackYUVInterface;
-}
-
-namespace content {
-
-// AuraWindowCaptureMachine uses the compositor to capture Aura windows.
-//
-// It is used for browser window capture on platforms that use Aura (Windows,
-// Linux, and Chrome OS) and additionally for desktop capture on Chrome OS.
-class AuraWindowCaptureMachine : public media::VideoCaptureMachine,
- public aura::WindowObserver,
- public ui::ContextFactoryObserver,
- public ui::CompositorAnimationObserver {
- public:
- AuraWindowCaptureMachine();
- ~AuraWindowCaptureMachine() override;
-
- // VideoCaptureMachine overrides.
- void Start(const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
- const media::VideoCaptureParams& params,
- const base::Callback<void(bool)> callback) override;
- void Suspend() override;
- void Resume() override;
- void Stop(const base::Closure& callback) override;
- void MaybeCaptureForRefresh() override;
-
- // Implements aura::WindowObserver.
- void OnWindowBoundsChanged(aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds,
- ui::PropertyChangeReason reason) override;
- void OnWindowDestroying(aura::Window* window) override;
- void OnWindowAddedToRootWindow(aura::Window* window) override;
- void OnWindowRemovingFromRootWindow(aura::Window* window,
- aura::Window* new_root) 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);
-
- private:
- bool InternalStart(
- const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
- const media::VideoCaptureParams& params);
- void InternalSuspend();
- void InternalResume();
- void InternalStop(const base::Closure& callback);
-
- // 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();
-
- using CaptureFrameCallback =
- media::ThreadSafeCaptureOracle::CaptureFrameCallback;
-
- // Response callback for cc::Layer::RequestCopyOfOutput().
- void DidCopyOutput(scoped_refptr<media::VideoFrame> video_frame,
- base::TimeTicks event_time,
- base::TimeTicks start_time,
- const CaptureFrameCallback& capture_frame_cb,
- std::unique_ptr<viz::CopyOutputResult> result);
-
- // A helper which does the real work for DidCopyOutput. Returns true if
- // 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<viz::CopyOutputResult> result);
-
- // ui::ContextFactoryObserver implementation.
- void OnLostResources() override;
-
- // Renders the cursor if needed and then delivers the captured frame.
- static void CopyOutputFinishedForVideo(
- base::WeakPtr<AuraWindowCaptureMachine> machine,
- base::TimeTicks event_time,
- const CaptureFrameCallback& capture_frame_cb,
- scoped_refptr<media::VideoFrame> target,
- const gfx::Rect& region_in_frame,
- std::unique_ptr<viz::SingleReleaseCallback> release_callback,
- bool result);
-
- // The window associated with the desktop.
- aura::Window* desktop_window_;
-
- // Whether screen capturing or window capture.
- bool screen_capture_;
-
- // Makes all the decisions about which frames to copy, and how.
- scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_;
-
- // The capture parameters for this capture.
- media::VideoCaptureParams capture_params_;
-
- // YUV readback pipeline.
- std::unique_ptr<viz::ReadbackYUVInterface> yuv_readback_pipeline_;
-
- // Renders mouse cursor on frame.
- std::unique_ptr<content::CursorRendererAura> cursor_renderer_;
-
- // TODO(jiayl): Remove wake_lock_ when there is an API to keep the
- // screen from sleeping for the drive-by web.
- device::mojom::WakeLockPtr wake_lock_;
-
- // False while frame capture has been suspended. All other aspects of the
- // machine are maintained.
- bool frame_capture_active_;
-
- // WeakPtrs are used for the asynchronous capture callbacks passed to external
- // modules. They are only valid on the UI thread and become invalidated
- // immediately when InternalStop() is called to ensure that no more captured
- // frames will be delivered to the client.
- base::WeakPtrFactory<AuraWindowCaptureMachine> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(AuraWindowCaptureMachine);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_CAPTURE_AURA_WINDOW_CAPTURE_MACHINE_H_
diff --git a/chromium/content/browser/media/capture/content_capture_device_browsertest_base.cc b/chromium/content/browser/media/capture/content_capture_device_browsertest_base.cc
index 73ba0a4823f..a33ddda3ee8 100644
--- a/chromium/content/browser/media/capture/content_capture_device_browsertest_base.cc
+++ b/chromium/content/browser/media/capture/content_capture_device_browsertest_base.cc
@@ -143,8 +143,8 @@ void ContentCaptureDeviceBrowserTestBase::
void ContentCaptureDeviceBrowserTestBase::StopAndDeAllocate() {
device_->StopAndDeAllocate();
- RunUntilIdle();
device_.reset();
+ RunUntilIdle();
}
void ContentCaptureDeviceBrowserTestBase::RunUntilIdle() {
diff --git a/chromium/content/browser/media/capture/cursor_renderer.cc b/chromium/content/browser/media/capture/cursor_renderer.cc
index 66352cc8a80..6434a15a422 100644
--- a/chromium/content/browser/media/capture/cursor_renderer.cc
+++ b/chromium/content/browser/media/capture/cursor_renderer.cc
@@ -283,11 +283,11 @@ CursorRendererUndoer::CursorRendererUndoer() = default;
CursorRendererUndoer::~CursorRendererUndoer() = default;
-CursorRendererUndoer::CursorRendererUndoer(CursorRendererUndoer&& other) =
- default;
+CursorRendererUndoer::CursorRendererUndoer(
+ CursorRendererUndoer&& other) noexcept = default;
CursorRendererUndoer& CursorRendererUndoer::operator=(
- CursorRendererUndoer&& other) = default;
+ CursorRendererUndoer&& other) noexcept = default;
namespace {
diff --git a/chromium/content/browser/media/capture/cursor_renderer.h b/chromium/content/browser/media/capture/cursor_renderer.h
index b9d1acc4927..64409bd5b01 100644
--- a/chromium/content/browser/media/capture/cursor_renderer.h
+++ b/chromium/content/browser/media/capture/cursor_renderer.h
@@ -185,8 +185,8 @@ class CONTENT_EXPORT CursorRendererUndoer {
CursorRendererUndoer();
~CursorRendererUndoer();
- CursorRendererUndoer(CursorRendererUndoer&& other);
- CursorRendererUndoer& operator=(CursorRendererUndoer&& other);
+ CursorRendererUndoer(CursorRendererUndoer&& other) noexcept;
+ CursorRendererUndoer& operator=(CursorRendererUndoer&& other) noexcept;
void TakeSnapshot(const media::VideoFrame& frame, const gfx::Rect& rect);
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura.cc b/chromium/content/browser/media/capture/desktop_capture_device_aura.cc
deleted file mode 100644
index a80e01233d3..00000000000
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/capture/desktop_capture_device_aura.h"
-
-#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/browser/media/capture/desktop_capture_device_uma_types.h"
-#include "content/public/browser/browser_thread.h"
-#include "ui/aura/window.h"
-
-namespace content {
-
-namespace {
-
-void SetCaptureSource(AuraWindowCaptureMachine* machine,
- const DesktopMediaID& source) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- aura::Window* window = DesktopMediaID::GetAuraWindowById(source);
- if (window) {
- machine->SetWindow(window);
- if (source.type == DesktopMediaID::TYPE_SCREEN) {
- if (source.audio_share)
- IncrementDesktopCaptureCounter(SCREEN_CAPTURER_CREATED_WITH_AUDIO);
- else
- IncrementDesktopCaptureCounter(SCREEN_CAPTURER_CREATED_WITHOUT_AUDIO);
- }
- }
-}
-
-} // namespace
-
-DesktopCaptureDeviceAura::DesktopCaptureDeviceAura(
- const DesktopMediaID& source) {
- AuraWindowCaptureMachine* machine = new AuraWindowCaptureMachine();
- 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,
- base::BindOnce(&SetCaptureSource, machine, source));
-}
-
-DesktopCaptureDeviceAura::~DesktopCaptureDeviceAura() {
- DVLOG(2) << "DesktopCaptureDeviceAura@" << this << " destroying.";
-}
-
-// static
-std::unique_ptr<media::VideoCaptureDevice> DesktopCaptureDeviceAura::Create(
- const DesktopMediaID& source) {
- if (source.aura_id == DesktopMediaID::kNullId)
- return nullptr;
- return std::unique_ptr<media::VideoCaptureDevice>(
- new DesktopCaptureDeviceAura(source));
-}
-
-void DesktopCaptureDeviceAura::AllocateAndStart(
- const media::VideoCaptureParams& params,
- 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();
-}
-
-void DesktopCaptureDeviceAura::OnUtilizationReport(int frame_feedback_id,
- double utilization) {
- core_->OnConsumerReportingUtilization(frame_feedback_id, utilization);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura.h b/chromium/content/browser/media/capture/desktop_capture_device_aura.h
deleted file mode 100644
index 6eee43a0edb..00000000000
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_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 "content/common/content_export.h"
-#include "content/public/browser/desktop_media_id.h"
-#include "media/capture/content/screen_capture_device_core.h"
-#include "media/capture/video/video_capture_device.h"
-
-namespace content {
-
-// An implementation of VideoCaptureDevice that mirrors an Aura window.
-class CONTENT_EXPORT DesktopCaptureDeviceAura
- : public media::VideoCaptureDevice {
- public:
- // Creates a VideoCaptureDevice for the Aura desktop. If |source| does not
- // reference a registered aura window, returns nullptr instead.
- static std::unique_ptr<media::VideoCaptureDevice> Create(
- const DesktopMediaID& source);
-
- ~DesktopCaptureDeviceAura() override;
-
- // VideoCaptureDevice implementation.
- void AllocateAndStart(const media::VideoCaptureParams& params,
- std::unique_ptr<Client> client) override;
- void RequestRefreshFrame() override;
- void StopAndDeAllocate() override;
- void OnUtilizationReport(int frame_feedback_id, double utilization) override;
-
- private:
- explicit DesktopCaptureDeviceAura(const DesktopMediaID& source);
-
- std::unique_ptr<media::ScreenCaptureDeviceCore> core_;
-
- DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDeviceAura);
-};
-
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_CAPTURE_DEVICE_AURA_H_
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
deleted file mode 100644
index 7de25f82bfa..00000000000
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/capture/desktop_capture_device_aura.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <utility>
-
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "content/browser/compositor/test/test_image_transport_factory.h"
-#include "content/public/browser/desktop_media_id.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "media/capture/video_capture_types.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/aura/client/window_parenting_client.h"
-#include "ui/aura/test/aura_test_helper.h"
-#include "ui/aura/test/test_window_delegate.h"
-#include "ui/aura/window.h"
-#include "ui/wm/core/default_activation_client.h"
-
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::AtMost;
-using ::testing::DoAll;
-using ::testing::Expectation;
-using ::testing::InvokeWithoutArgs;
-using ::testing::SaveArg;
-
-namespace media {
-class VideoFrame;
-} // namespace media
-
-namespace content {
-namespace {
-
-const int kFrameRate = 30;
-
-class MockDeviceClient : public media::VideoCaptureDevice::Client {
- public:
- MOCK_METHOD7(OnIncomingCapturedData,
- void(const uint8_t* data,
- int length,
- const media::VideoCaptureFormat& frame_format,
- int rotation,
- base::TimeTicks reference_time,
- base::TimeDelta tiemstamp,
- int frame_feedback_id));
- MOCK_METHOD6(OnIncomingCapturedGfxBuffer,
- void(gfx::GpuMemoryBuffer* buffer,
- const media::VideoCaptureFormat& frame_format,
- int clockwise_rotation,
- base::TimeTicks reference_time,
- base::TimeDelta timestamp,
- int frame_feedback_id));
- 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 base::Location& from_here,
- const std::string& reason));
- MOCK_METHOD0(OnStarted, void(void));
-
- // Trampoline methods to workaround GMOCK problems with std::unique_ptr<>.
- Buffer ReserveOutputBuffer(const gfx::Size& dimensions,
- media::VideoPixelFormat format,
- int frame_feedback_id) override {
- EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
- DoReserveOutputBuffer();
- return Buffer();
- }
- void OnIncomingCapturedBuffer(Buffer buffer,
- const media::VideoCaptureFormat& frame_format,
- base::TimeTicks reference_time,
- base::TimeDelta timestamp) override {
- DoOnIncomingCapturedBuffer();
- }
- void OnIncomingCapturedBufferExt(
- Buffer buffer,
- const media::VideoCaptureFormat& format,
- base::TimeTicks reference_time,
- base::TimeDelta timestamp,
- gfx::Rect visible_rect,
- const media::VideoFrameMetadata& additional_metadata) override {
- DoOnIncomingCapturedVideoFrame();
- }
- Buffer ResurrectLastOutputBuffer(const gfx::Size& dimensions,
- media::VideoPixelFormat format,
- int frame_feedback_id) override {
- EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
- DoResurrectLastOutputBuffer();
- return Buffer();
- }
- double GetBufferPoolUtilization() const override { return 0.0; }
-};
-
-// Test harness that sets up a minimal environment with necessary stubs.
-class DesktopCaptureDeviceAuraTest : public testing::Test {
- public:
- DesktopCaptureDeviceAuraTest() = default;
- ~DesktopCaptureDeviceAuraTest() override = default;
-
- protected:
- void SetUp() override {
- // The ContextFactory must exist before any Compositors are created.
- ImageTransportFactory::SetFactory(
- std::make_unique<TestImageTransportFactory>());
- helper_.reset(new aura::test::AuraTestHelper());
- helper_->SetUp(
- ImageTransportFactory::GetInstance()->GetContextFactory(),
- ImageTransportFactory::GetInstance()->GetContextFactoryPrivate());
- new wm::DefaultActivationClient(helper_->root_window());
- // We need a window to cover desktop area so that DesktopCaptureDeviceAura
- // can use gfx::NativeWindow::GetWindowAtScreenPoint() to locate the
- // root window associated with the primary display.
- gfx::Rect desktop_bounds = root_window()->bounds();
- window_delegate_.reset(new aura::test::TestWindowDelegate());
- desktop_window_.reset(new aura::Window(window_delegate_.get()));
- desktop_window_->Init(ui::LAYER_TEXTURED);
- desktop_window_->SetBounds(desktop_bounds);
- aura::client::ParentWindowWithContext(
- desktop_window_.get(), root_window(), desktop_bounds);
- desktop_window_->Show();
- }
-
- void TearDown() override {
- helper_->RunAllPendingInMessageLoop();
- root_window()->RemoveChild(desktop_window_.get());
- desktop_window_.reset();
- window_delegate_.reset();
- helper_->TearDown();
- base::RunLoop().RunUntilIdle();
- ImageTransportFactory::Terminate();
- }
-
- aura::Window* root_window() { return helper_->root_window(); }
-
- private:
- TestBrowserThreadBundle thread_bundle_;
- std::unique_ptr<aura::test::AuraTestHelper> helper_;
- std::unique_ptr<aura::Window> desktop_window_;
- std::unique_ptr<aura::test::TestWindowDelegate> window_delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDeviceAuraTest);
-};
-
-TEST_F(DesktopCaptureDeviceAuraTest, StartAndStop) {
- std::unique_ptr<media::VideoCaptureDevice> capture_device =
- DesktopCaptureDeviceAura::Create(
- content::DesktopMediaID::RegisterAuraWindow(
- content::DesktopMediaID::TYPE_SCREEN, root_window()));
- ASSERT_TRUE(capture_device);
-
- std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
- EXPECT_CALL(*client, OnError(_, _)).Times(0);
- // |STARTED| is reported asynchronously, which may not be received if capture
- // is stopped immediately.
- EXPECT_CALL(*client, OnStarted()).Times(AtMost(1));
-
- media::VideoCaptureParams capture_params;
- capture_params.requested_format.frame_size.SetSize(640, 480);
- capture_params.requested_format.frame_rate = kFrameRate;
- capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_device->AllocateAndStart(capture_params, std::move(client));
- capture_device->StopAndDeAllocate();
-}
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/browser/media/capture/fake_webcontent_capture_machine.cc b/chromium/content/browser/media/capture/fake_webcontent_capture_machine.cc
deleted file mode 100644
index f18b8835d6e..00000000000
--- a/chromium/content/browser/media/capture/fake_webcontent_capture_machine.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights 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/fake_webcontent_capture_machine.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-FakeWebContentCaptureMachine::FakeWebContentCaptureMachine(
- bool enable_auto_throttling)
- : enable_auto_throttling_(enable_auto_throttling) {
- DVLOG(2) << "FakeWebContentCaptureMachine";
-}
-
-FakeWebContentCaptureMachine::~FakeWebContentCaptureMachine() {
- DVLOG(2) << "FakeWebContentCaptureMachine@" << this << " destroying.";
-}
-
-void FakeWebContentCaptureMachine::Start(
- const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
- const media::VideoCaptureParams& params,
- const base::Callback<void(bool)> callback) {
- callback.Run(true);
-}
-void FakeWebContentCaptureMachine::Suspend() {}
-void FakeWebContentCaptureMachine::Resume() {}
-void FakeWebContentCaptureMachine::Stop(const base::Closure& callback) {}
-bool FakeWebContentCaptureMachine::IsAutoThrottlingEnabled() const {
- return enable_auto_throttling_;
-}
-void FakeWebContentCaptureMachine::MaybeCaptureForRefresh() {}
-
-} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/media/capture/fake_webcontent_capture_machine.h b/chromium/content/browser/media/capture/fake_webcontent_capture_machine.h
deleted file mode 100644
index 92a5f84a3ec..00000000000
--- a/chromium/content/browser/media/capture/fake_webcontent_capture_machine.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2017 The Chromium Authors. All 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_FAKE_WEBCONTENT_CAPTURE_MACHINE_H_
-#define CONTENT_BROWSER_MEDIA_CAPTURE_FAKE_WEBCONTENT_CAPTURE_MACHINE_H_
-
-#include "base/callback_helpers.h"
-#include "content/common/content_export.h"
-#include "media/capture/content/screen_capture_device_core.h"
-#include "media/capture/content/thread_safe_capture_oracle.h"
-#include "media/capture/video_capture_types.h"
-
-namespace content {
-
-// An implementation of VideoCaptureDevice that fakes a desktop capturer.
-class CONTENT_EXPORT FakeWebContentCaptureMachine
- : public media::VideoCaptureMachine {
- public:
- FakeWebContentCaptureMachine(bool enable_auto_throttling);
- ~FakeWebContentCaptureMachine() override;
-
- // VideoCaptureMachine overrides.
- void Start(const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
- const media::VideoCaptureParams& params,
- const base::Callback<void(bool)> callback) override;
- void Suspend() override;
- void Resume() override;
- void Stop(const base::Closure& callback) override;
- bool IsAutoThrottlingEnabled() const override;
- void MaybeCaptureForRefresh() override;
-
- private:
- bool enable_auto_throttling_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeWebContentCaptureMachine);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_FAKE_CAPTURE_DEVICE_H_ \ No newline at end of file
diff --git a/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc b/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc
index 80ad28d503b..e096bf8cc5b 100644
--- a/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc
+++ b/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc
@@ -41,7 +41,7 @@ class ScopedFrameDoneHelper
: public base::ScopedClosureRunner,
public media::VideoCaptureDevice::Client::Buffer::ScopedAccessPermission {
public:
- ScopedFrameDoneHelper(base::OnceClosure done_callback)
+ explicit ScopedFrameDoneHelper(base::OnceClosure done_callback)
: base::ScopedClosureRunner(std::move(done_callback)) {}
~ScopedFrameDoneHelper() final = default;
};
@@ -258,12 +258,6 @@ void FrameSinkVideoCaptureDevice::OnFrameCaptured(
std::move(info));
}
-void FrameSinkVideoCaptureDevice::OnTargetLost(
- const viz::FrameSinkId& frame_sink_id) {
- // This is ignored because FrameSinkVideoCaptureDevice subclasses always call
- // OnTargetChanged() and OnTargetPermanentlyLost() to resolve lost targets.
-}
-
void FrameSinkVideoCaptureDevice::OnStopped() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -279,19 +273,19 @@ void FrameSinkVideoCaptureDevice::OnTargetChanged(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
target_ = frame_sink_id;
- // TODO(crbug.com/754872): When the frame sink is invalid, the capturer should
- // be told there is no target. This will require a mojo API change; and will
- // be addressed in a soon-upcoming CL.
- if (capturer_ && frame_sink_id.is_valid()) {
- capturer_->ChangeTarget(frame_sink_id);
+ if (capturer_) {
+ if (target_.is_valid()) {
+ capturer_->ChangeTarget(target_);
+ } else {
+ capturer_->ChangeTarget(base::nullopt);
+ }
}
}
void FrameSinkVideoCaptureDevice::OnTargetPermanentlyLost() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- target_ = viz::FrameSinkId();
-
+ OnTargetChanged(viz::FrameSinkId());
OnFatalError("Capture target has been permanently lost.");
}
@@ -376,9 +370,9 @@ void FrameSinkVideoCaptureDevice::OnFatalError(std::string message) {
FrameSinkVideoCaptureDevice::ConsumptionState::ConsumptionState() = default;
FrameSinkVideoCaptureDevice::ConsumptionState::~ConsumptionState() = default;
FrameSinkVideoCaptureDevice::ConsumptionState::ConsumptionState(
- FrameSinkVideoCaptureDevice::ConsumptionState&& other) = default;
+ FrameSinkVideoCaptureDevice::ConsumptionState&& other) noexcept = default;
FrameSinkVideoCaptureDevice::ConsumptionState&
FrameSinkVideoCaptureDevice::ConsumptionState::operator=(
- FrameSinkVideoCaptureDevice::ConsumptionState&& other) = default;
+ FrameSinkVideoCaptureDevice::ConsumptionState&& other) noexcept = default;
} // namespace content
diff --git a/chromium/content/browser/media/capture/frame_sink_video_capture_device.h b/chromium/content/browser/media/capture/frame_sink_video_capture_device.h
index fefe7b9d10c..341248435ea 100644
--- a/chromium/content/browser/media/capture/frame_sink_video_capture_device.h
+++ b/chromium/content/browser/media/capture/frame_sink_video_capture_device.h
@@ -6,6 +6,8 @@
#define CONTENT_BROWSER_MEDIA_CAPTURE_FRAME_SINK_VIDEO_CAPTURE_DEVICE_H_
#include <memory>
+#include <string>
+#include <utility>
#include <vector>
#include "base/macros.h"
@@ -76,7 +78,6 @@ class CONTENT_EXPORT FrameSinkVideoCaptureDevice
const gfx::Rect& update_rect,
const gfx::Rect& content_rect,
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) final;
- void OnTargetLost(const viz::FrameSinkId& frame_sink_id) final;
void OnStopped() final;
// These are called to notify when the capture target has changed or was
@@ -147,8 +148,8 @@ class CONTENT_EXPORT FrameSinkVideoCaptureDevice
ConsumptionState();
~ConsumptionState();
- ConsumptionState(ConsumptionState&& other);
- ConsumptionState& operator=(ConsumptionState&& other);
+ ConsumptionState(ConsumptionState&& other) noexcept;
+ ConsumptionState& operator=(ConsumptionState&& other) noexcept;
};
std::vector<ConsumptionState> slots_;
diff --git a/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc b/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
index b9cc7f8bad8..d8de88d4e46 100644
--- a/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
@@ -91,7 +91,12 @@ class MockFrameSinkVideoCapturer : public viz::mojom::FrameSinkVideoCapturer {
const gfx::Size& max_size,
bool use_fixed_aspect_ratio));
MOCK_METHOD1(SetAutoThrottlingEnabled, void(bool));
- MOCK_METHOD1(ChangeTarget, void(const viz::FrameSinkId& frame_sink_id));
+ void ChangeTarget(
+ const base::Optional<viz::FrameSinkId>& frame_sink_id) final {
+ DCHECK_NOT_ON_DEVICE_THREAD();
+ MockChangeTarget(frame_sink_id ? *frame_sink_id : viz::FrameSinkId());
+ }
+ MOCK_METHOD1(MockChangeTarget, void(const viz::FrameSinkId& frame_sink_id));
void Start(viz::mojom::FrameSinkVideoConsumerPtr consumer) final {
DCHECK_NOT_ON_DEVICE_THREAD();
consumer_ = std::move(consumer);
@@ -310,7 +315,7 @@ class FrameSinkVideoCaptureDeviceTest : public testing::Test {
EXPECT_CALL(capturer_,
SetResolutionConstraints(kResolution, kResolution, _));
constexpr viz::FrameSinkId frame_sink_id(1, 1);
- EXPECT_CALL(capturer_, ChangeTarget(frame_sink_id));
+ EXPECT_CALL(capturer_, MockChangeTarget(frame_sink_id));
EXPECT_CALL(capturer_, MockStart(NotNull()));
EXPECT_FALSE(capturer_.is_bound());
@@ -555,6 +560,7 @@ TEST_F(FrameSinkVideoCaptureDeviceTest, ShutsDownOnFatalError) {
// consumption, unbind the capturer, log an error with the VideoFrameReceiver,
// and destroy the VideoFrameReceiver.
{
+ EXPECT_CALL(capturer_, MockChangeTarget(viz::FrameSinkId()));
EXPECT_CALL(capturer_, MockStop());
POST_DEVICE_METHOD_CALL0(OnTargetPermanentlyLost);
WAIT_FOR_DEVICE_TASKS();
diff --git a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc
index 95e5e769f1a..1086b27f68f 100644
--- a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc
+++ b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc
@@ -4,6 +4,8 @@
#include "content/browser/media/capture/lame_window_capturer_chromeos.h"
+#include <algorithm>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
@@ -99,7 +101,7 @@ void LameWindowCapturerChromeOS::SetAutoThrottlingEnabled(bool enabled) {
}
void LameWindowCapturerChromeOS::ChangeTarget(
- const viz::FrameSinkId& frame_sink_id) {
+ const base::Optional<viz::FrameSinkId>& frame_sink_id) {
// The LameWindowCapturerChromeOS does not capture from compositor frame
// sinks.
}
diff --git a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h
index 6978f755f07..2a467ecc20b 100644
--- a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h
+++ b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_LAME_WINDOW_CAPTURER_CHROMEOS_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_LAME_WINDOW_CAPTURER_CHROMEOS_H_
+#include <memory>
#include <utility>
#include <vector>
@@ -60,7 +61,8 @@ class LameWindowCapturerChromeOS : public viz::mojom::FrameSinkVideoCapturer,
const gfx::Size& max_size,
bool use_fixed_aspect_ratio) final;
void SetAutoThrottlingEnabled(bool enabled) final;
- void ChangeTarget(const viz::FrameSinkId& frame_sink_id) final;
+ void ChangeTarget(
+ const base::Optional<viz::FrameSinkId>& frame_sink_id) final;
void Start(viz::mojom::FrameSinkVideoConsumerPtr consumer) final;
void Stop() final;
void RequestRefreshFrame() final;
diff --git a/chromium/content/browser/media/capture/screen_capture_device_android.cc b/chromium/content/browser/media/capture/screen_capture_device_android.cc
index 1e93e1c1ce3..9d5cf896498 100644
--- a/chromium/content/browser/media/capture/screen_capture_device_android.cc
+++ b/chromium/content/browser/media/capture/screen_capture_device_android.cc
@@ -4,36 +4,70 @@
#include "content/browser/media/capture/screen_capture_device_android.h"
+#include <utility>
+
#include "base/logging.h"
-#include "media/capture/content/android/screen_capture_machine_android.h"
+#include "media/capture/content/android/thread_safe_capture_oracle.h"
namespace content {
-ScreenCaptureDeviceAndroid::ScreenCaptureDeviceAndroid()
- : core_(std::make_unique<media::ScreenCaptureMachineAndroid>()) {}
+ScreenCaptureDeviceAndroid::ScreenCaptureDeviceAndroid() = default;
ScreenCaptureDeviceAndroid::~ScreenCaptureDeviceAndroid() {
- DVLOG(2) << "ScreenCaptureDeviceAndroid@" << this << " destroying.";
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!oracle_proxy_);
}
void ScreenCaptureDeviceAndroid::AllocateAndStart(
const media::VideoCaptureParams& params,
std::unique_ptr<Client> client) {
- DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString();
- core_.AllocateAndStart(params, std::move(client));
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (params.requested_format.pixel_format != media::PIXEL_FORMAT_I420) {
+ client->OnError(
+ FROM_HERE, "unsupported format: " + media::VideoCaptureFormat::ToString(
+ params.requested_format));
+ return;
+ }
+
+ DCHECK(!oracle_proxy_);
+ oracle_proxy_ = new media::ThreadSafeCaptureOracle(std::move(client), params);
+
+ if (!capture_machine_.Start(oracle_proxy_, params)) {
+ oracle_proxy_->ReportError(FROM_HERE, "Failed to start capture machine.");
+ StopAndDeAllocate();
+ } else {
+ // The |capture_machine_| will later report to the |oracle_proxy_| whether
+ // the device started successfully.
+ }
}
void ScreenCaptureDeviceAndroid::StopAndDeAllocate() {
- core_.StopAndDeAllocate();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (!oracle_proxy_) {
+ return; // Device is already stopped.
+ }
+
+ oracle_proxy_->Stop();
+ oracle_proxy_ = nullptr;
+ capture_machine_.Stop();
}
void ScreenCaptureDeviceAndroid::RequestRefreshFrame() {
- core_.RequestRefreshFrame();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (!oracle_proxy_) {
+ return; // Device is stopped.
+ }
+ capture_machine_.MaybeCaptureForRefresh();
}
void ScreenCaptureDeviceAndroid::OnUtilizationReport(int frame_feedback_id,
double utilization) {
- core_.OnConsumerReportingUtilization(frame_feedback_id, utilization);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(oracle_proxy_);
+ oracle_proxy_->OnConsumerReportingUtilization(frame_feedback_id, utilization);
}
} // namespace content
diff --git a/chromium/content/browser/media/capture/screen_capture_device_android.h b/chromium/content/browser/media/capture/screen_capture_device_android.h
index 7d2d5184435..14112269a5a 100644
--- a/chromium/content/browser/media/capture/screen_capture_device_android.h
+++ b/chromium/content/browser/media/capture/screen_capture_device_android.h
@@ -7,15 +7,17 @@
#include <memory>
+#include "base/macros.h"
+#include "base/sequence_checker.h"
#include "content/common/content_export.h"
-#include "media/capture/content/screen_capture_device_core.h"
+#include "media/capture/content/android/screen_capture_machine_android.h"
#include "media/capture/video/video_capture_device.h"
namespace content {
-// ScreenCaptureDeviceAndroid is a forwarder to media::ScreenCaptureDeviceCore
-// while keeping the Power Saving from kicking in between AllocateAndStart() and
-// StopAndDeAllocate().
+// ScreenCaptureDeviceAndroid is an adapter for using
+// media::ScreenCaptureMachineAndroid via the media::VideoCaptureDevice
+// interface.
class CONTENT_EXPORT ScreenCaptureDeviceAndroid
: public media::VideoCaptureDevice {
public:
@@ -30,7 +32,10 @@ class CONTENT_EXPORT ScreenCaptureDeviceAndroid
void OnUtilizationReport(int frame_feedback_id, double utilization) override;
private:
- media::ScreenCaptureDeviceCore core_;
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ media::ScreenCaptureMachineAndroid capture_machine_;
+ scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_;
DISALLOW_COPY_AND_ASSIGN(ScreenCaptureDeviceAndroid);
};
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 15115a22b8b..e1593cc807e 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
@@ -177,15 +177,20 @@ bool WebContentsAudioInputStream::Impl::Open() {
tracker_->Start(
initial_render_process_id_, initial_main_render_frame_id_,
base::Bind(&Impl::OnTargetChanged, this));
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Impl::IncrementCapturerCount, this));
+ IncrementCapturerCount();
return true;
}
void WebContentsAudioInputStream::Impl::IncrementCapturerCount() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&Impl::IncrementCapturerCount, this));
+ return;
+ }
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (WebContents* contents = tracker_->web_contents())
contents->IncrementCapturerCount(gfx::Size());
}
@@ -237,9 +242,7 @@ void WebContentsAudioInputStream::Impl::Close() {
if (state_ == OPENED) {
state_ = CONSTRUCTED;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Impl::DecrementCapturerCount, this));
+ DecrementCapturerCount();
tracker_->Stop();
mixer_stream_->Close();
}
@@ -249,8 +252,14 @@ void WebContentsAudioInputStream::Impl::Close() {
}
void WebContentsAudioInputStream::Impl::DecrementCapturerCount() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&Impl::DecrementCapturerCount, this));
+ return;
+ }
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (WebContents* contents = tracker_->web_contents())
contents->DecrementCapturerCount();
}
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 c440442ca3c..e4122a24cdf 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
@@ -53,10 +53,15 @@ class WebContentsVideoCaptureDevice::FrameTracker
AsWeakPtr(), render_process_id, main_render_frame_id));
}
- ~FrameTracker() final { DCHECK_CURRENTLY_ON(BrowserThread::UI); }
+ ~FrameTracker() final {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (is_capturing_)
+ DidStopCapturingWebContents();
+ }
void WillStartCapturingWebContents(const gfx::Size& capture_size) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!is_capturing_);
auto* contents = web_contents();
if (!contents) {
@@ -85,14 +90,18 @@ class WebContentsVideoCaptureDevice::FrameTracker
<< preferred_size.ToString() << " from a capture size of "
<< capture_size.ToString();
contents->IncrementCapturerCount(preferred_size);
+ is_capturing_ = true;
}
void DidStopCapturingWebContents() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (auto* contents = web_contents()) {
+ DCHECK(is_capturing_);
contents->DecrementCapturerCount();
+ is_capturing_ = false;
}
+ DCHECK(!is_capturing_);
}
private:
@@ -134,6 +143,7 @@ class WebContentsVideoCaptureDevice::FrameTracker
void DidDestroyFullscreenWidget() final { OnPossibleTargetChange(); }
void WebContentsDestroyed() final {
Observe(nullptr);
+ is_capturing_ = false;
OnPossibleTargetChange();
}
@@ -192,6 +202,9 @@ class WebContentsVideoCaptureDevice::FrameTracker
viz::FrameSinkId target_frame_sink_id_;
gfx::NativeView target_native_view_ = gfx::NativeView();
+ // Indicates whether the WebContents's capturer count needs to be decremented.
+ bool is_capturing_ = false;
+
DISALLOW_COPY_AND_ASSIGN(FrameTracker);
};
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc b/chromium/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc
index 643c570b0a0..ec35ff5a5b3 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc
@@ -195,6 +195,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
capture_stack()->ExpectHasLogMessages();
device->StopAndDeAllocate();
+ device.reset();
RunUntilIdle();
}
@@ -204,6 +205,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
ErrorsOutWhenWebContentsIsDestroyed) {
NavigateToInitialDocument();
AllocateAndStartAndWaitForFirstFrame();
+ EXPECT_TRUE(shell()->web_contents()->IsBeingCaptured());
// Initially, the device captures any content changes normally.
ChangePageContentColor(SK_ColorRED);
@@ -226,6 +228,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
SuspendsAndResumes) {
NavigateToInitialDocument();
AllocateAndStartAndWaitForFirstFrame();
+ EXPECT_TRUE(shell()->web_contents()->IsBeingCaptured());
// Initially, the device captures any content changes normally.
ChangePageContentColor(SK_ColorRED);
@@ -252,6 +255,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
WaitForFrameWithColor(SK_ColorGREEN);
StopAndDeAllocate();
+ EXPECT_FALSE(shell()->web_contents()->IsBeingCaptured());
}
// Tests that the device delivers refresh frames when asked, while the source
@@ -260,6 +264,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
DeliversRefreshFramesUponRequest) {
NavigateToInitialDocument();
AllocateAndStartAndWaitForFirstFrame();
+ EXPECT_TRUE(shell()->web_contents()->IsBeingCaptured());
// Set the page content to a known color.
ChangePageContentColor(SK_ColorRED);
@@ -274,6 +279,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
}
StopAndDeAllocate();
+ EXPECT_FALSE(shell()->web_contents()->IsBeingCaptured());
}
class WebContentsVideoCaptureDeviceBrowserTestP
@@ -331,6 +337,7 @@ IN_PROC_BROWSER_TEST_P(WebContentsVideoCaptureDeviceBrowserTestP,
NavigateToInitialDocument();
AllocateAndStartAndWaitForFirstFrame();
+ EXPECT_TRUE(shell()->web_contents()->IsBeingCaptured());
for (int visilibilty_case = 0; visilibilty_case < 3; ++visilibilty_case) {
switch (visilibilty_case) {
@@ -378,6 +385,7 @@ IN_PROC_BROWSER_TEST_P(WebContentsVideoCaptureDeviceBrowserTestP,
}
StopAndDeAllocate();
+ EXPECT_FALSE(shell()->web_contents()->IsBeingCaptured());
}
} // namespace
diff --git a/chromium/content/browser/media/cdm_registry_impl_unittest.cc b/chromium/content/browser/media/cdm_registry_impl_unittest.cc
index 96547c4fc7f..6f10e239e6c 100644
--- a/chromium/content/browser/media/cdm_registry_impl_unittest.cc
+++ b/chromium/content/browser/media/cdm_registry_impl_unittest.cc
@@ -21,6 +21,13 @@
namespace content {
+namespace {
+
+using VideoCodec = media::VideoCodec;
+using EncryptionMode = media::EncryptionMode;
+using CdmSessionType = media::CdmSessionType;
+using CdmProxy = media::CdmProxy;
+
const char kTestCdmName[] = "Test CDM";
const char kAlternateCdmName[] = "Alternate CDM";
const char kTestCdmGuid[] = "62FE9C4B-384E-48FD-B28A-9F6F248BC8CC";
@@ -30,6 +37,31 @@ const char kVersion2[] = "1.1.1.2";
const char kTestKeySystem[] = "com.example.somesystem";
const char kTestFileSystemId[] = "file_system_id";
+// Helper function to compare a STL container to an initializer_list.
+template <typename Container, typename T>
+bool StlEquals(const Container a, std::initializer_list<T> b) {
+ return a == Container(b);
+}
+
+#define EXPECT_STL_EQ(a, ...) \
+ do { \
+ EXPECT_TRUE(StlEquals(a, {__VA_ARGS__})); \
+ } while (false)
+
+#define EXPECT_VIDEO_CODECS(...) \
+ EXPECT_STL_EQ(cdm.capability.video_codecs, __VA_ARGS__)
+
+#define EXPECT_ENCRYPTION_SCHEMES(...) \
+ EXPECT_STL_EQ(cdm.capability.encryption_schemes, __VA_ARGS__)
+
+#define EXPECT_SESSION_TYPES(...) \
+ EXPECT_STL_EQ(cdm.capability.session_types, __VA_ARGS__)
+
+#define EXPECT_CDM_PROXY_PROTOCOLS(...) \
+ EXPECT_STL_EQ(cdm.capability.cdm_proxy_protocols, __VA_ARGS__)
+
+} // namespace
+
// For simplicity and to make failures easier to diagnose, this test uses
// std::string instead of base::FilePath and std::vector<std::string>.
class CdmRegistryImplTest : public testing::Test {
@@ -38,19 +70,19 @@ class CdmRegistryImplTest : public testing::Test {
~CdmRegistryImplTest() override {}
protected:
- void Register(const std::string& name,
- const std::string& version,
- const std::string& path,
- const std::vector<media::VideoCodec>& supported_video_codecs,
- bool supports_persistent_license,
- const base::flat_set<media::EncryptionMode>& supported_modes,
- std::string supported_key_system,
- bool supports_sub_key_systems = false) {
- cdm_registry_.RegisterCdm(CdmInfo(
- name, kTestCdmGuid, base::Version(version),
- base::FilePath::FromUTF8Unsafe(path), kTestFileSystemId,
- supported_video_codecs, supports_persistent_license, supported_modes,
- supported_key_system, supports_sub_key_systems));
+ CdmInfo GetTestCdmInfo() {
+ return CdmInfo(
+ kTestCdmName, kTestCdmGuid, base::Version(kVersion1),
+ base::FilePath::FromUTF8Unsafe(kTestPath), kTestFileSystemId,
+ CdmCapability(
+ {media::kCodecVP8, media::kCodecVP9}, {EncryptionMode::kCenc},
+ {CdmSessionType::kTemporary, CdmSessionType::kPersistentLicense},
+ {CdmProxy::Protocol::kIntel}),
+ kTestKeySystem, /*supports_sub_key_systems=*/true);
+ }
+
+ void Register(CdmInfo cdm_info) {
+ cdm_registry_.RegisterCdm(std::move(cdm_info));
}
bool IsRegistered(const std::string& name, const std::string& version) {
@@ -75,52 +107,51 @@ class CdmRegistryImplTest : public testing::Test {
};
TEST_F(CdmRegistryImplTest, Register) {
- Register(kTestCdmName, kVersion1, kTestPath,
- {media::kCodecVP8, media::kCodecVP9}, true,
- {media::EncryptionMode::kCenc}, kTestKeySystem, true);
- std::vector<CdmInfo> cdms = cdm_registry_.GetAllRegisteredCdms();
+ Register(GetTestCdmInfo());
+
+ auto cdms = cdm_registry_.GetAllRegisteredCdms();
ASSERT_EQ(1u, cdms.size());
CdmInfo cdm = cdms[0];
EXPECT_EQ(kTestCdmName, cdm.name);
EXPECT_EQ(kVersion1, cdm.version.GetString());
EXPECT_EQ(kTestPath, cdm.path.MaybeAsASCII());
EXPECT_EQ(kTestFileSystemId, cdm.file_system_id);
- EXPECT_EQ(2u, cdm.supported_video_codecs.size());
- EXPECT_EQ(media::kCodecVP8, cdm.supported_video_codecs[0]);
- EXPECT_EQ(media::kCodecVP9, cdm.supported_video_codecs[1]);
- EXPECT_TRUE(cdm.supports_persistent_license);
- EXPECT_EQ(1u, cdm.supported_encryption_schemes.size());
- EXPECT_EQ(
- 1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCenc));
+ EXPECT_VIDEO_CODECS(VideoCodec::kCodecVP8, VideoCodec::kCodecVP9);
+ EXPECT_ENCRYPTION_SCHEMES(EncryptionMode::kCenc);
+ EXPECT_SESSION_TYPES(CdmSessionType::kTemporary,
+ CdmSessionType::kPersistentLicense);
+ EXPECT_CDM_PROXY_PROTOCOLS(CdmProxy::Protocol::kIntel);
EXPECT_EQ(kTestKeySystem, cdm.supported_key_system);
EXPECT_TRUE(cdm.supports_sub_key_systems);
}
TEST_F(CdmRegistryImplTest, ReRegister) {
- Register(kTestCdmName, kVersion1, "/bb/cc", {}, false,
- {media::EncryptionMode::kCenc}, kTestKeySystem);
+ auto cdm_info = GetTestCdmInfo();
+ Register(cdm_info);
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
// Now register same key system with different values.
- Register(kTestCdmName, kVersion1, kTestPath, {}, false,
- {media::EncryptionMode::kCenc}, kTestKeySystem);
+ cdm_info.supports_sub_key_systems = false;
+ Register(cdm_info);
+
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
}
TEST_F(CdmRegistryImplTest, MultipleVersions) {
- Register(kTestCdmName, kVersion1, kTestPath, {}, false,
- {media::EncryptionMode::kCenc}, kTestKeySystem);
- Register(kTestCdmName, kVersion2, "/bb/cc", {}, false,
- {media::EncryptionMode::kCenc}, kTestKeySystem);
+ auto cdm_info = GetTestCdmInfo();
+ Register(cdm_info);
+ cdm_info.version = base::Version(kVersion2);
+ Register(cdm_info);
+
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion2));
}
TEST_F(CdmRegistryImplTest, NewVersionInsertedLast) {
- Register(kTestCdmName, kVersion1, kTestPath, {}, false,
- {media::EncryptionMode::kCenc}, kTestKeySystem);
- Register(kTestCdmName, kVersion2, "/bb/cc", {}, false,
- {media::EncryptionMode::kCenc}, kTestKeySystem);
+ auto cdm_info = GetTestCdmInfo();
+ Register(cdm_info);
+ cdm_info.version = base::Version(kVersion2);
+ Register(cdm_info);
const std::vector<std::string> versions = GetVersions(kTestCdmGuid);
EXPECT_EQ(2u, versions.size());
@@ -129,27 +160,25 @@ TEST_F(CdmRegistryImplTest, NewVersionInsertedLast) {
}
TEST_F(CdmRegistryImplTest, DifferentNames) {
- Register(kTestCdmName, kVersion1, kTestPath, {}, false,
- {media::EncryptionMode::kCenc}, kTestKeySystem);
- Register(kAlternateCdmName, kVersion1, kTestPath, {}, false,
- {media::EncryptionMode::kCbcs}, kTestKeySystem);
+ auto cdm_info = GetTestCdmInfo();
+ Register(cdm_info);
+ cdm_info.name = kAlternateCdmName;
+ Register(cdm_info);
+
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
EXPECT_TRUE(IsRegistered(kAlternateCdmName, kVersion1));
}
TEST_F(CdmRegistryImplTest, SupportedEncryptionSchemes) {
- Register(kTestCdmName, kVersion1, kTestPath, {}, false,
- {media::EncryptionMode::kCenc, media::EncryptionMode::kCbcs},
- kTestKeySystem);
+ auto cdm_info = GetTestCdmInfo();
+ cdm_info.capability.encryption_schemes = {EncryptionMode::kCenc,
+ EncryptionMode::kCbcs};
+ Register(cdm_info);
std::vector<CdmInfo> cdms = cdm_registry_.GetAllRegisteredCdms();
ASSERT_EQ(1u, cdms.size());
const CdmInfo& cdm = cdms[0];
- EXPECT_EQ(2u, cdm.supported_encryption_schemes.size());
- EXPECT_EQ(
- 1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCenc));
- EXPECT_EQ(
- 1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCbcs));
+ EXPECT_ENCRYPTION_SCHEMES(EncryptionMode::kCenc, EncryptionMode::kCbcs);
}
} // namespace content
diff --git a/chromium/content/browser/media/encrypted_media_browsertest.cc b/chromium/content/browser/media/encrypted_media_browsertest.cc
index 7096e1e1fe8..db7a34efd8d 100644
--- a/chromium/content/browser/media/encrypted_media_browsertest.cc
+++ b/chromium/content/browser/media/encrypted_media_browsertest.cc
@@ -56,6 +56,7 @@ const char kMp4Vp9VideoOnly[] =
"video/mp4; codecs=\"vp09.00.10.08.01.02.02.02.00\"";
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
const char kMp4Avc1VideoOnly[] = "video/mp4; codecs=\"avc1.64001E\"";
+const char kMp4AacAudioOnly[] = "audio/mp4; codecs=\"mp4a.40.2\"";
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
// EME-specific test results and errors.
@@ -63,6 +64,7 @@ const char kEmeKeyError[] = "KEYERROR";
const char kEmeNotSupportedError[] = "NOTSUPPORTEDERROR";
const char kDefaultEmePlayer[] = "eme_player.html";
+const char kDefaultMseOnlyEmePlayer[] = "mse_different_containers.html";
// The type of video src used to load media.
enum class SrcType { SRC, MSE };
@@ -92,15 +94,14 @@ class EncryptedMediaTest
void TestSimplePlayback(const std::string& encrypted_media,
const std::string& media_type) {
- RunSimpleEncryptedMediaTest(encrypted_media, media_type, CurrentKeySystem(),
- CurrentSourceType());
+ RunSimplePlaybackTest(encrypted_media, media_type, CurrentKeySystem(),
+ CurrentSourceType());
}
void TestFrameSizeChange() {
- RunEncryptedMediaTest("encrypted_frame_size_change.html",
- "frame_size_change-av_enc-v.webm",
- kWebMVorbisAudioVp8Video, CurrentKeySystem(),
- CurrentSourceType(), media::kEnded);
+ RunTest("encrypted_frame_size_change.html",
+ "frame_size_change-av_enc-v.webm", kWebMVorbisAudioVp8Video,
+ CurrentKeySystem(), CurrentSourceType(), media::kEnded);
}
void TestConfigChange(ConfigChangeType config_change_type) {
@@ -121,12 +122,12 @@ class EncryptedMediaTest
true);
}
- void RunEncryptedMediaTest(const std::string& html_page,
- const std::string& media_file,
- const std::string& media_type,
- const std::string& key_system,
- SrcType src_type,
- const std::string& expectation) {
+ void RunTest(const std::string& html_page,
+ const std::string& media_file,
+ const std::string& media_type,
+ const std::string& key_system,
+ SrcType src_type,
+ const std::string& expectation) {
base::StringPairs query_params;
query_params.emplace_back("mediaFile", media_file);
query_params.emplace_back("mediaType", media_type);
@@ -136,24 +137,40 @@ class EncryptedMediaTest
RunMediaTestPage(html_page, query_params, expectation, true);
}
- void RunSimpleEncryptedMediaTest(const std::string& media_file,
- const std::string& media_type,
- const std::string& key_system,
- SrcType src_type) {
- RunEncryptedMediaTest(kDefaultEmePlayer, media_file, media_type, key_system,
- src_type, media::kEnded);
+ void RunSimplePlaybackTest(const std::string& media_file,
+ const std::string& media_type,
+ const std::string& key_system,
+ SrcType src_type) {
+ RunTest(kDefaultEmePlayer, media_file, media_type, key_system, src_type,
+ media::kEnded);
}
- void TestMp4EncryptionPlayback(const std::string& media_file,
- const std::string& media_type,
- const std::string& expected_title) {
+ void RunMultipleFileTest(const std::string& video_file,
+ const std::string& video_type,
+ const std::string& audio_file,
+ const std::string& audio_type,
+ const std::string& expected_title) {
if (CurrentSourceType() != SrcType::MSE) {
DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
return;
}
- RunEncryptedMediaTest(kDefaultEmePlayer, media_file, media_type,
- CurrentKeySystem(), SrcType::MSE, expected_title);
+ base::StringPairs query_params;
+ query_params.emplace_back("keySystem", CurrentKeySystem());
+ query_params.emplace_back("runEncrypted", "1");
+ if (!video_file.empty()) {
+ DCHECK(!video_type.empty());
+ query_params.emplace_back("videoFile", video_file);
+ query_params.emplace_back("videoFormat", video_type);
+ }
+ if (!audio_file.empty()) {
+ DCHECK(!audio_type.empty());
+ query_params.emplace_back("audioFile", audio_file);
+ query_params.emplace_back("audioFormat", audio_type);
+ }
+
+ RunMediaTestPage(kDefaultMseOnlyEmePlayer, query_params, expected_title,
+ true);
}
protected:
@@ -258,8 +275,8 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM_Opus) {
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4_FLAC) {
- TestMp4EncryptionPlayback("bear-flac-cenc.mp4", kMp4FlacAudioOnly,
- media::kEnded);
+ RunMultipleFileTest(std::string(), std::string(), "bear-flac-cenc.mp4",
+ kMp4FlacAudioOnly, media::kEnded);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) {
@@ -302,32 +319,54 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, MAYBE_FrameSizeChangeVideo) {
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_Encryption_CENC) {
- TestMp4EncryptionPlayback("bear-640x360-v_frag-cenc.mp4", kMp4Avc1VideoOnly,
- media::kEnded);
+ RunMultipleFileTest("bear-640x360-v_frag-cenc.mp4", kMp4Avc1VideoOnly,
+ "bear-640x360-a_frag-cenc.mp4", kMp4AacAudioOnly,
+ media::kEnded);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_Encryption_CBC1) {
- TestMp4EncryptionPlayback("bear-640x360-v_frag-cbc1.mp4", kMp4Avc1VideoOnly,
- media::kError);
+ RunMultipleFileTest("bear-640x360-v_frag-cbc1.mp4", kMp4Avc1VideoOnly,
+ std::string(), std::string(), media::kError);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_Encryption_CENS) {
- TestMp4EncryptionPlayback("bear-640x360-v_frag-cens.mp4", kMp4Avc1VideoOnly,
- media::kError);
+ RunMultipleFileTest("bear-640x360-v_frag-cens.mp4", kMp4Avc1VideoOnly,
+ std::string(), std::string(), media::kError);
}
+#if !defined(OS_ANDROID)
+// TODO(crbug.com/813845): Enable CBCS support on Chrome for Android.
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_Encryption_CBCS) {
std::string expected_result =
BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) ? media::kEnded : media::kError;
- TestMp4EncryptionPlayback("bear-640x360-v_frag-cbcs.mp4", kMp4Avc1VideoOnly,
- expected_result);
+ RunMultipleFileTest("bear-640x360-v_frag-cbcs.mp4", kMp4Avc1VideoOnly,
+ "bear-640x360-a_frag-cbcs.mp4", kMp4AacAudioOnly,
+ expected_result);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
+ Playback_Encryption_CBCS_Video_CENC_Audio) {
+ std::string expected_result =
+ BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) ? media::kEnded : media::kError;
+ RunMultipleFileTest("bear-640x360-v_frag-cbcs.mp4", kMp4Avc1VideoOnly,
+ "bear-640x360-a_frag-cenc.mp4", kMp4AacAudioOnly,
+ expected_result);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
+ Playback_Encryption_CENC_Video_CBCS_Audio) {
+ std::string expected_result =
+ BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) ? media::kEnded : media::kError;
+ RunMultipleFileTest("bear-640x360-v_frag-cenc.mp4", kMp4Avc1VideoOnly,
+ "bear-640x360-a_frag-cbcs.mp4", kMp4AacAudioOnly,
+ expected_result);
}
+#endif // !defined(OS_ANDROID)
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, UnknownKeySystemThrowsException) {
- RunEncryptedMediaTest(kDefaultEmePlayer, "bear-a_enc-a.webm",
- kWebMVorbisAudioOnly, "com.example.foo", SrcType::MSE,
- kEmeNotSupportedError);
+ RunTest(kDefaultEmePlayer, "bear-a_enc-a.webm", kWebMVorbisAudioOnly,
+ "com.example.foo", SrcType::MSE, kEmeNotSupportedError);
}
} // namespace content
diff --git a/chromium/content/browser/media/flinging_renderer.cc b/chromium/content/browser/media/flinging_renderer.cc
index 8828939c4e5..b6119358422 100644
--- a/chromium/content/browser/media/flinging_renderer.cc
+++ b/chromium/content/browser/media/flinging_renderer.cc
@@ -14,7 +14,8 @@
namespace content {
-FlingingRenderer::FlingingRenderer(std::unique_ptr<MediaController> controller)
+FlingingRenderer::FlingingRenderer(
+ std::unique_ptr<media::MediaController> controller)
: controller_(std::move(controller)) {}
FlingingRenderer::~FlingingRenderer() = default;
diff --git a/chromium/content/browser/media/flinging_renderer.h b/chromium/content/browser/media/flinging_renderer.h
index 59a12b8bf07..38c411cd6d5 100644
--- a/chromium/content/browser/media/flinging_renderer.h
+++ b/chromium/content/browser/media/flinging_renderer.h
@@ -7,7 +7,7 @@
#include "base/callback.h"
#include "content/common/content_export.h"
-#include "content/public/browser/media_controller.h"
+#include "media/base/media_controller.h"
#include "media/base/media_resource.h"
#include "media/base/renderer.h"
#include "media/base/renderer_client.h"
@@ -50,9 +50,9 @@ class CONTENT_EXPORT FlingingRenderer : public media::Renderer {
private:
friend class FlingingRendererTest;
- explicit FlingingRenderer(std::unique_ptr<MediaController> controller);
+ explicit FlingingRenderer(std::unique_ptr<media::MediaController> controller);
- std::unique_ptr<MediaController> controller_;
+ std::unique_ptr<media::MediaController> controller_;
DISALLOW_COPY_AND_ASSIGN(FlingingRenderer);
};
diff --git a/chromium/content/browser/media/flinging_renderer_unittest.cc b/chromium/content/browser/media/flinging_renderer_unittest.cc
index 923415d94b8..680ac22101c 100644
--- a/chromium/content/browser/media/flinging_renderer_unittest.cc
+++ b/chromium/content/browser/media/flinging_renderer_unittest.cc
@@ -5,7 +5,7 @@
#include "content/browser/media/flinging_renderer.h"
#include "base/version.h"
-#include "content/public/browser/media_controller.h"
+#include "media/base/media_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -14,7 +14,7 @@ using ::testing::StrictMock;
namespace content {
-class MockMediaController : public MediaController {
+class MockMediaController : public media::MediaController {
public:
MOCK_METHOD0(Play, void());
MOCK_METHOD0(Pause, void());
@@ -27,7 +27,7 @@ class FlingingRendererTest : public testing::Test {
public:
FlingingRendererTest()
: media_controller_(new StrictMock<MockMediaController>()),
- renderer_(std::unique_ptr<MediaController>(media_controller_)) {}
+ renderer_(std::unique_ptr<media::MediaController>(media_controller_)) {}
protected:
StrictMock<MockMediaController>* media_controller_;
diff --git a/chromium/content/browser/media/key_system_support_impl.cc b/chromium/content/browser/media/key_system_support_impl.cc
index 414da641e76..624cca51aa8 100644
--- a/chromium/content/browser/media/key_system_support_impl.cc
+++ b/chromium/content/browser/media/key_system_support_impl.cc
@@ -6,13 +6,20 @@
#include <vector>
+#include "base/command_line.h"
#include "base/containers/flat_set.h"
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
+#include "base/strings/string_split.h"
#include "content/public/browser/cdm_registry.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/common/cdm_info.h"
+#include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
#include "media/base/key_system_names.h"
#include "media/base/key_systems.h"
+#include "media/base/media_switches.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
namespace content {
@@ -26,6 +33,104 @@ void SendCdmAvailableUMA(const std::string& key_system, bool available) {
available);
}
+template <typename T>
+std::vector<T> SetToVector(const base::flat_set<T>& s) {
+ return std::vector<T>(s.begin(), s.end());
+}
+
+// Returns whether hardware secure codecs are enabled from command line. If
+// true, |video_codecs| are filled with codecs specified on command line, which
+// could be empty if no codecs are specified. If false, |video_codecs| will not
+// be modified.
+bool IsHardwareSecureCodecsOverriddenFromCommandLine(
+ std::vector<media::VideoCodec>* video_codecs,
+ std::vector<media::EncryptionMode>* encryption_schemes) {
+ DCHECK(video_codecs->empty());
+ DCHECK(encryption_schemes->empty());
+
+ auto* command_line = base::CommandLine::ForCurrentProcess();
+ if (!command_line || !command_line->HasSwitch(
+ switches::kOverrideHardwareSecureCodecsForTesting)) {
+ return false;
+ }
+
+ auto codecs_string = command_line->GetSwitchValueASCII(
+ switches::kOverrideHardwareSecureCodecsForTesting);
+ const auto supported_codecs = base::SplitStringPiece(
+ codecs_string, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ for (const auto& codec : supported_codecs) {
+ if (codec == "vp8")
+ video_codecs->push_back(media::VideoCodec::kCodecVP8);
+ else if (codec == "vp9")
+ video_codecs->push_back(media::VideoCodec::kCodecVP9);
+ else if (codec == "avc1")
+ video_codecs->push_back(media::VideoCodec::kCodecH264);
+ else
+ DVLOG(1) << "Unsupported codec specified on command line: " << codec;
+ }
+
+ // Codecs enabled from command line assumes CENC support.
+ if (!video_codecs->empty())
+ encryption_schemes->push_back(media::EncryptionMode::kCenc);
+
+ return true;
+}
+
+void GetHardwareSecureDecryptionCaps(
+ const std::string& key_system,
+ const base::flat_set<media::CdmProxy::Protocol>& cdm_proxy_protocols,
+ std::vector<media::VideoCodec>* video_codecs,
+ std::vector<media::EncryptionMode>* encryption_schemes) {
+ DCHECK(video_codecs->empty());
+ DCHECK(encryption_schemes->empty());
+
+ if (!base::FeatureList::IsEnabled(media::kHardwareSecureDecryption)) {
+ DVLOG(1) << "Hardware secure decryption disabled";
+ return;
+ }
+
+ // Secure codecs override takes precedence over other checks.
+ if (IsHardwareSecureCodecsOverriddenFromCommandLine(video_codecs,
+ encryption_schemes)) {
+ DVLOG(1) << "Hardware secure codecs overridden from command line";
+ return;
+ }
+
+ if (cdm_proxy_protocols.empty()) {
+ DVLOG(1) << "CDM does not support any CdmProxy protocols";
+ return;
+ }
+
+ // Hardware secure video codecs need hardware video decoder support.
+ // TODO(xhwang): Make sure this check is as close as possible to the check
+ // in the render process. For example, also check check GPU features like
+ // GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE.
+ auto* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line &&
+ command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
+ DVLOG(1) << "Hardware secure codecs not supported because accelerated "
+ "video decode disabled";
+ return;
+ }
+
+ if (!base::FeatureList::IsEnabled(media::kMojoVideoDecoder)) {
+ DVLOG(1) << "Hardware secure codecs not supported because mojo video "
+ "decode disabled";
+ return;
+ }
+
+ base::flat_set<media::VideoCodec> video_codec_set;
+ base::flat_set<media::EncryptionMode> encryption_scheme_set;
+
+ GetContentClient()->browser()->GetHardwareSecureDecryptionCaps(
+ key_system, cdm_proxy_protocols, &video_codec_set,
+ &encryption_scheme_set);
+
+ *video_codecs = SetToVector(video_codec_set);
+ *encryption_schemes = SetToVector(encryption_scheme_set);
+}
+
} // namespace
// static
@@ -59,20 +164,31 @@ KeySystemSupportImpl::~KeySystemSupportImpl() = default;
void KeySystemSupportImpl::IsKeySystemSupported(
const std::string& key_system,
IsKeySystemSupportedCallback callback) {
- DVLOG(3) << __func__;
- std::unique_ptr<CdmInfo> cdm = GetCdmInfoForKeySystem(key_system);
- if (!cdm) {
+ DVLOG(3) << __func__ << ": key_system = " << key_system;
+
+ auto cdm_info = GetCdmInfoForKeySystem(key_system);
+ if (!cdm_info) {
SendCdmAvailableUMA(key_system, false);
- std::move(callback).Run(false, {}, false, {});
+ std::move(callback).Run(false, nullptr);
return;
}
- const base::flat_set<media::EncryptionMode>& schemes =
- cdm->supported_encryption_schemes;
SendCdmAvailableUMA(key_system, true);
- std::move(callback).Run(
- true, cdm->supported_video_codecs, cdm->supports_persistent_license,
- std::vector<media::EncryptionMode>(schemes.begin(), schemes.end()));
+
+ // Supported codecs and encryption schemes.
+ auto capability = media::mojom::KeySystemCapability::New();
+ capability->video_codecs = cdm_info->capability.video_codecs;
+ capability->encryption_schemes =
+ SetToVector(cdm_info->capability.encryption_schemes);
+
+ GetHardwareSecureDecryptionCaps(key_system,
+ cdm_info->capability.cdm_proxy_protocols,
+ &capability->hw_secure_video_codecs,
+ &capability->hw_secure_encryption_schemes);
+
+ capability->session_types = SetToVector(cdm_info->capability.session_types);
+
+ std::move(callback).Run(true, std::move(capability));
}
} // namespace content
diff --git a/chromium/content/browser/media/key_system_support_impl_unittest.cc b/chromium/content/browser/media/key_system_support_impl_unittest.cc
index aa3134ae60e..8ba04e3e867 100644
--- a/chromium/content/browser/media/key_system_support_impl_unittest.cc
+++ b/chromium/content/browser/media/key_system_support_impl_unittest.cc
@@ -22,11 +22,35 @@ namespace content {
namespace {
+using VideoCodec = media::VideoCodec;
+using EncryptionMode = media::EncryptionMode;
+using CdmSessionType = media::CdmSessionType;
+
const char kTestCdmGuid[] = "62FE9C4B-384E-48FD-B28A-9F6F248BC8CC";
const char kVersion[] = "1.1.1.1";
const char kTestPath[] = "/aa/bb";
const char kTestFileSystemId[] = "file_system_id";
+// Helper function to compare a STL container to an initializer_list.
+template <typename Container, typename T>
+bool StlEquals(const Container a, std::initializer_list<T> b) {
+ return a == Container(b);
+}
+
+#define EXPECT_STL_EQ(a, ...) \
+ do { \
+ EXPECT_TRUE(StlEquals(a, {__VA_ARGS__})); \
+ } while (false)
+
+#define EXPECT_VIDEO_CODECS(...) \
+ EXPECT_STL_EQ(capability_->video_codecs, __VA_ARGS__)
+
+#define EXPECT_ENCRYPTION_SCHEMES(...) \
+ EXPECT_STL_EQ(capability_->encryption_schemes, __VA_ARGS__)
+
+#define EXPECT_SESSION_TYPES(...) \
+ EXPECT_STL_EQ(capability_->session_types, __VA_ARGS__)
+
} // namespace
class KeySystemSupportTest : public testing::Test {
@@ -36,20 +60,24 @@ class KeySystemSupportTest : public testing::Test {
KeySystemSupportImpl::Create(mojo::MakeRequest(&key_system_support_));
}
- // Registers |key_system| with |supported_video_codecs| and
- // |supports_persistent_license|. All other values for CdmInfo have some
- // default value as they're not returned by IsKeySystemSupported().
- void Register(const std::string& key_system,
- const std::vector<media::VideoCodec>& supported_video_codecs,
- bool supports_persistent_license,
- const base::flat_set<media::EncryptionMode>& supported_modes) {
+ // TODO(xhwang): Add tests for hardware secure video codecs and encryption
+ // schemes.
+ CdmCapability GetTestCdmCapability() {
+ return CdmCapability(
+ {VideoCodec::kCodecVP8, VideoCodec::kCodecVP9},
+ {EncryptionMode::kCenc, EncryptionMode::kCbcs},
+ {CdmSessionType::kTemporary, CdmSessionType::kPersistentLicense}, {});
+ }
+
+ // Registers |key_system| with |capability|. All other values for CdmInfo have
+ // some default value as they're not returned by IsKeySystemSupported().
+ void Register(const std::string& key_system, CdmCapability capability) {
DVLOG(1) << __func__;
CdmRegistry::GetInstance()->RegisterCdm(
CdmInfo(key_system, kTestCdmGuid, base::Version(kVersion),
base::FilePath::FromUTF8Unsafe(kTestPath), kTestFileSystemId,
- supported_video_codecs, supports_persistent_license,
- supported_modes, key_system, false));
+ std::move(capability), key_system, false));
}
// Determines if |key_system| is registered. If it is, updates |codecs_|
@@ -58,8 +86,7 @@ class KeySystemSupportTest : public testing::Test {
DVLOG(1) << __func__;
bool is_available = false;
key_system_support_->IsKeySystemSupported(key_system, &is_available,
- &codecs_, &persistent_,
- &encryption_schemes_);
+ &capability_);
return is_available;
}
@@ -67,9 +94,7 @@ class KeySystemSupportTest : public testing::Test {
TestBrowserThreadBundle test_browser_thread_bundle_;
// Updated by IsSupported().
- std::vector<media::VideoCodec> codecs_;
- bool persistent_;
- std::vector<media::EncryptionMode> encryption_schemes_;
+ media::mojom::KeySystemCapabilityPtr capability_;
};
// Note that as CdmRegistry::GetInstance() is a static, it is shared between
@@ -78,45 +103,32 @@ class KeySystemSupportTest : public testing::Test {
TEST_F(KeySystemSupportTest, NoKeySystems) {
EXPECT_FALSE(IsSupported("KeySystem1"));
+ EXPECT_FALSE(capability_);
}
TEST_F(KeySystemSupportTest, OneKeySystem) {
- Register("KeySystem2", {media::VideoCodec::kCodecVP8}, true,
- {media::EncryptionMode::kCenc, media::EncryptionMode::kCbcs});
+ Register("KeySystem2", GetTestCdmCapability());
+
EXPECT_TRUE(IsSupported("KeySystem2"));
- EXPECT_EQ(1u, codecs_.size());
- EXPECT_EQ(media::VideoCodec::kCodecVP8, codecs_[0]);
- EXPECT_TRUE(persistent_);
- EXPECT_EQ(2u, encryption_schemes_.size());
- EXPECT_EQ(media::EncryptionMode::kCenc, encryption_schemes_[0]);
- EXPECT_EQ(media::EncryptionMode::kCbcs, encryption_schemes_[1]);
+ EXPECT_VIDEO_CODECS(VideoCodec::kCodecVP8, VideoCodec::kCodecVP9);
+ EXPECT_ENCRYPTION_SCHEMES(EncryptionMode::kCenc, EncryptionMode::kCbcs);
+ EXPECT_SESSION_TYPES(CdmSessionType::kTemporary,
+ CdmSessionType::kPersistentLicense);
}
TEST_F(KeySystemSupportTest, MultipleKeySystems) {
- Register("KeySystem3",
- {media::VideoCodec::kCodecVP8, media::VideoCodec::kCodecVP9}, true,
- {media::EncryptionMode::kCenc});
- Register("KeySystem4", {media::VideoCodec::kCodecVP9}, false,
- {media::EncryptionMode::kCbcs});
+ Register("KeySystem3", GetTestCdmCapability());
+ Register("KeySystem4", GetTestCdmCapability());
+
EXPECT_TRUE(IsSupported("KeySystem3"));
- EXPECT_EQ(2u, codecs_.size());
- EXPECT_EQ(media::VideoCodec::kCodecVP8, codecs_[0]);
- EXPECT_EQ(media::VideoCodec::kCodecVP9, codecs_[1]);
- EXPECT_TRUE(persistent_);
- EXPECT_EQ(1u, encryption_schemes_.size());
- EXPECT_EQ(media::EncryptionMode::kCenc, encryption_schemes_[0]);
EXPECT_TRUE(IsSupported("KeySystem4"));
- EXPECT_EQ(1u, codecs_.size());
- EXPECT_EQ(media::VideoCodec::kCodecVP9, codecs_[0]);
- EXPECT_FALSE(persistent_);
- EXPECT_EQ(1u, encryption_schemes_.size());
- EXPECT_EQ(media::EncryptionMode::kCbcs, encryption_schemes_[0]);
}
TEST_F(KeySystemSupportTest, MissingKeySystem) {
- Register("KeySystem5", {media::VideoCodec::kCodecVP8}, true,
- {media::EncryptionMode::kCenc});
+ Register("KeySystem5", GetTestCdmCapability());
+
EXPECT_FALSE(IsSupported("KeySystem6"));
+ EXPECT_FALSE(capability_);
}
} // namespace content
diff --git a/chromium/content/browser/media/media_autoplay_browsertest.cc b/chromium/content/browser/media/media_autoplay_browsertest.cc
new file mode 100644
index 00000000000..bb03034fe17
--- /dev/null
+++ b/chromium/content/browser/media/media_autoplay_browsertest.cc
@@ -0,0 +1,66 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/path_service.h"
+#include "content/common/media/media_player_delegate_messages.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+
+namespace content {
+
+namespace {
+
+class WaitForMediaPlaying : public WebContentsObserver {
+ public:
+ WaitForMediaPlaying(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+
+ // WebContentsObserver override.
+ void MediaStartedPlaying(const MediaPlayerInfo&, const MediaPlayerId&) final {
+ run_loop_.Quit();
+ }
+
+ void Wait() { run_loop_.Run(); }
+
+ private:
+ base::RunLoop run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaitForMediaPlaying);
+};
+
+} // namespace
+
+class MediaAutoplayTest : public ContentBrowserTest {
+ public:
+ void SetUpOnMainThread() override {
+ ContentBrowserTest::SetUpOnMainThread();
+
+ base::FilePath test_data_dir;
+ ASSERT_TRUE(base::PathService::Get(content::DIR_TEST_DATA, &test_data_dir));
+ embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+};
+
+// Test that playing a player from an IPC does not lead to a crash the renderer.
+// This is a regression test from a crash from autoplay_initiated_ not being set
+// in the Blink's AutoplayPolicy.
+IN_PROC_BROWSER_TEST_F(MediaAutoplayTest, Crash_AutoplayInitiated) {
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL("/media/video-player.html"));
+
+ WaitForMediaPlaying wait_for_media_playing(shell()->web_contents());
+
+ RenderFrameHost* main_frame = shell()->web_contents()->GetMainFrame();
+ main_frame->Send(
+ new MediaPlayerDelegateMsg_Play(main_frame->GetRoutingID(), 1));
+
+ wait_for_media_playing.Wait();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/media_canplaytype_browsertest.cc b/chromium/content/browser/media/media_canplaytype_browsertest.cc
index f6706151c8f..c517a4bf7c4 100644
--- a/chromium/content/browser/media/media_canplaytype_browsertest.cc
+++ b/chromium/content/browser/media/media_canplaytype_browsertest.cc
@@ -591,21 +591,21 @@ class AV1MediaCanPlayTypeTest : public MediaCanPlayTypeTest {
// Note: This must be a separate test since features can not be changed after
// the initial navigation.
IN_PROC_BROWSER_TEST_F(AV1MediaCanPlayTypeTest, CodecSupportTest_av1) {
- // TODO(dalecurtis): This is not the correct final string. Fix before enabling
- // by default. This test needs to be merged into the existing mp4 and webm
- // before release as well. http://crbug.com/784607
- EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"av1\"'"));
- EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"av1\"'"));
-}
-#endif // BUILDFLAG(ENABLE_AV1_DECODER)
-
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_av1_unsupported) {
- // TODO(dalecurtis): This is not the correct final string. Fix before enabling
- // by default. This test needs to be merged into the existing mp4 and webm
- // before release as well. http://crbug.com/784607
+ // Fully qualified codec strings are required. These tests are not exhaustive
+ // since codec string parsing is exhaustively tested elsewhere.
EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"av1\"'"));
EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"av1\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"av01.0.04M.08\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"av01.0.04M.08\"'"));
}
+#else
+// AV1 is enabled by default. However, on platforms where it is not built, such
+// as ARM-based devices, av1 must be unsupported.
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_av1_unsupported) {
+ EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"av01.0.04M.08\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"av01.0.04M.08\"'"));
+}
+#endif // BUILDFLAG(ENABLE_AV1_DECODER)
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_wav) {
EXPECT_EQ(kMaybe, CanPlay("'audio/wav'"));
diff --git a/chromium/content/browser/media/media_internals.cc b/chromium/content/browser/media/media_internals.cc
index e245a5feada..54b72c76803 100644
--- a/chromium/content/browser/media/media_internals.cc
+++ b/chromium/content/browser/media/media_internals.cc
@@ -16,7 +16,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
-#include "content/browser/media/mojo_audio_logging_adapter.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -118,7 +117,8 @@ const char kAudioLogUpdateFunction[] = "media.updateAudioComponent";
namespace content {
-class AudioLogImpl : public media::mojom::AudioLog {
+class MediaInternals::AudioLogImpl : public media::mojom::AudioLog,
+ public media::AudioLog {
public:
AudioLogImpl(int owner_id,
media::AudioLogFactory::AudioComponent component,
@@ -164,12 +164,13 @@ class AudioLogImpl : public media::mojom::AudioLog {
DISALLOW_COPY_AND_ASSIGN(AudioLogImpl);
};
-AudioLogImpl::AudioLogImpl(int owner_id,
- media::AudioLogFactory::AudioComponent component,
- content::MediaInternals* media_internals,
- int component_id,
- int render_process_id,
- int render_frame_id)
+MediaInternals::AudioLogImpl::AudioLogImpl(
+ int owner_id,
+ media::AudioLogFactory::AudioComponent component,
+ content::MediaInternals* media_internals,
+ int component_id,
+ int render_process_id,
+ int render_frame_id)
: owner_id_(owner_id),
component_(component),
media_internals_(media_internals),
@@ -177,10 +178,16 @@ AudioLogImpl::AudioLogImpl(int owner_id,
render_process_id_(render_process_id),
render_frame_id_(render_frame_id) {}
-AudioLogImpl::~AudioLogImpl() {}
+MediaInternals::AudioLogImpl::~AudioLogImpl() {
+ // Ensure log is always closed. This covers the case of crashes in the audio
+ // service utility process, in which case the log may not be closed
+ // explicitly.
+ OnClosed();
+}
-void AudioLogImpl::OnCreated(const media::AudioParameters& params,
- const std::string& device_id) {
+void MediaInternals::AudioLogImpl::OnCreated(
+ const media::AudioParameters& params,
+ const std::string& device_id) {
base::DictionaryValue dict;
StoreComponentMetadata(&dict);
@@ -199,15 +206,15 @@ void AudioLogImpl::OnCreated(const media::AudioParameters& params,
SetWebContentsTitle();
}
-void AudioLogImpl::OnStarted() {
+void MediaInternals::AudioLogImpl::OnStarted() {
SendSingleStringUpdate(kAudioLogStatusKey, "started");
}
-void AudioLogImpl::OnStopped() {
+void MediaInternals::AudioLogImpl::OnStopped() {
SendSingleStringUpdate(kAudioLogStatusKey, "stopped");
}
-void AudioLogImpl::OnClosed() {
+void MediaInternals::AudioLogImpl::OnClosed() {
base::DictionaryValue dict;
StoreComponentMetadata(&dict);
dict.SetString(kAudioLogStatusKey, "closed");
@@ -216,11 +223,11 @@ void AudioLogImpl::OnClosed() {
&dict);
}
-void AudioLogImpl::OnError() {
+void MediaInternals::AudioLogImpl::OnError() {
SendSingleStringUpdate("error_occurred", "true");
}
-void AudioLogImpl::OnSetVolume(double volume) {
+void MediaInternals::AudioLogImpl::OnSetVolume(double volume) {
base::DictionaryValue dict;
StoreComponentMetadata(&dict);
dict.SetDouble("volume", volume);
@@ -229,11 +236,11 @@ void AudioLogImpl::OnSetVolume(double volume) {
&dict);
}
-void AudioLogImpl::OnLogMessage(const std::string& message) {
+void MediaInternals::AudioLogImpl::OnLogMessage(const std::string& message) {
MediaStreamManager::SendMessageToNativeLog(message);
}
-void AudioLogImpl::SetWebContentsTitle() {
+void MediaInternals::AudioLogImpl::SetWebContentsTitle() {
if (render_process_id_ < 0 || render_frame_id_ < 0)
return;
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
@@ -242,12 +249,12 @@ void AudioLogImpl::SetWebContentsTitle() {
render_process_id_, render_frame_id_);
}
-std::string AudioLogImpl::FormatCacheKey() {
+std::string MediaInternals::AudioLogImpl::FormatCacheKey() {
return base::StringPrintf("%d:%d:%d", owner_id_, component_, component_id_);
}
// static
-void AudioLogImpl::SendWebContentsTitleHelper(
+void MediaInternals::AudioLogImpl::SendWebContentsTitleHelper(
const std::string& cache_key,
std::unique_ptr<base::DictionaryValue> dict,
int render_process_id,
@@ -275,8 +282,9 @@ void AudioLogImpl::SendWebContentsTitleHelper(
dict.get());
}
-void AudioLogImpl::SendSingleStringUpdate(const std::string& key,
- const std::string& value) {
+void MediaInternals::AudioLogImpl::SendSingleStringUpdate(
+ const std::string& key,
+ const std::string& value) {
base::DictionaryValue dict;
StoreComponentMetadata(&dict);
dict.SetString(key, value);
@@ -285,7 +293,8 @@ void AudioLogImpl::SendSingleStringUpdate(const std::string& key,
&dict);
}
-void AudioLogImpl::StoreComponentMetadata(base::DictionaryValue* dict) {
+void MediaInternals::AudioLogImpl::StoreComponentMetadata(
+ base::DictionaryValue* dict) {
dict->SetInteger("owner_id", owner_id_);
dict->SetInteger("component_id", component_id_);
dict->SetInteger("component_type", component_);
@@ -322,6 +331,7 @@ class MediaInternals::MediaInternalsUMAHandler {
std::string audio_codec_name;
std::string video_codec_name;
std::string video_decoder;
+ bool is_platform_video_decoder = false;
GURL origin_url;
};
@@ -410,6 +420,10 @@ void MediaInternals::MediaInternalsUMAHandler::SavePlayerState(
player_info.video_decoder_changed = true;
}
}
+ if (event.params.HasKey("is_platform_video_decoder")) {
+ event.params.GetBoolean("is_platform_video_decoder",
+ &player_info.is_platform_video_decoder);
+ }
if (event.params.HasKey("video_dds")) {
event.params.GetBoolean("video_dds", &player_info.video_dds);
}
@@ -469,8 +483,10 @@ std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream(
uma_name += "DDS.";
}
- if (player_info.video_decoder == media::GpuVideoDecoder::kDecoderName ||
- player_info.video_decoder == "MojoVideoDecoder") {
+ // Note that HW essentailly means 'platform' anyway. MediaCodec has been
+ // reported as HW forever, regardless of the underlying platform
+ // implementation.
+ if (player_info.is_platform_video_decoder) {
uma_name += "HW";
} else {
uma_name += "SW";
@@ -720,8 +736,7 @@ void MediaInternals::UpdateVideoCaptureDeviceCapabilities(
std::unique_ptr<media::AudioLog> MediaInternals::CreateAudioLog(
AudioComponent component,
int component_id) {
- return std::make_unique<MojoAudioLogAdapter>(
- CreateMojoAudioLog(component, component_id));
+ return CreateAudioLogImpl(component, component_id, -1, MSG_ROUTING_NONE);
}
media::mojom::AudioLogPtr MediaInternals::CreateMojoAudioLog(
@@ -729,15 +744,36 @@ media::mojom::AudioLogPtr MediaInternals::CreateMojoAudioLog(
int component_id,
int render_process_id,
int render_frame_id) {
- base::AutoLock auto_lock(lock_);
media::mojom::AudioLogPtr audio_log_ptr;
- mojo::MakeStrongBinding(std::make_unique<AudioLogImpl>(
- owner_ids_[component]++, component, this,
- component_id, render_process_id, render_frame_id),
- mojo::MakeRequest(&audio_log_ptr));
+ CreateMojoAudioLog(component, component_id, mojo::MakeRequest(&audio_log_ptr),
+ render_process_id, render_frame_id);
return audio_log_ptr;
}
+void MediaInternals::CreateMojoAudioLog(
+ media::AudioLogFactory::AudioComponent component,
+ int component_id,
+ media::mojom::AudioLogRequest request,
+ int render_process_id,
+ int render_frame_id) {
+ mojo::MakeStrongBinding(
+ CreateAudioLogImpl(component, component_id, render_process_id,
+ render_frame_id),
+ std::move(request));
+}
+
+std::unique_ptr<MediaInternals::AudioLogImpl>
+MediaInternals::CreateAudioLogImpl(
+ media::AudioLogFactory::AudioComponent component,
+ int component_id,
+ int render_process_id,
+ int render_frame_id) {
+ base::AutoLock auto_lock(lock_);
+ return std::make_unique<AudioLogImpl>(owner_ids_[component]++, component,
+ this, component_id, render_process_id,
+ render_frame_id);
+}
+
void MediaInternals::OnProcessTerminatedForTesting(int process_id) {
uma_handler_->OnProcessTerminated(process_id);
}
diff --git a/chromium/content/browser/media/media_internals.h b/chromium/content/browser/media/media_internals.h
index 25b1085daaf..494c251ad9c 100644
--- a/chromium/content/browser/media/media_internals.h
+++ b/chromium/content/browser/media/media_internals.h
@@ -92,14 +92,21 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
int render_process_id = -1,
int render_frame_id = MSG_ROUTING_NONE);
+ // Strongly bounds |request| to a new media::mojom::AudioLog instance. Safe to
+ // call from any thread.
+ void CreateMojoAudioLog(AudioComponent component,
+ int component_id,
+ media::mojom::AudioLogRequest request,
+ int render_process_id = -1,
+ int render_frame_id = MSG_ROUTING_NONE);
+
void OnProcessTerminatedForTesting(int process_id);
private:
+ class AudioLogImpl;
// Inner class to handle reporting pipelinestatus to UMA
class MediaInternalsUMAHandler;
- friend class AudioLogImpl;
-
MediaInternals();
// Sends |update| to each registered UpdateCallback. Safe to call from any
@@ -123,6 +130,11 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
const std::string& function,
const base::DictionaryValue* value);
+ std::unique_ptr<AudioLogImpl> CreateAudioLogImpl(AudioComponent component,
+ int component_id,
+ int render_process_id,
+ int render_frame_id);
+
// Must only be accessed on the UI thread.
std::vector<UpdateCallback> update_callbacks_;
diff --git a/chromium/content/browser/media/media_source_browsertest.cc b/chromium/content/browser/media/media_source_browsertest.cc
index 5e3cb0006e5..a7d782ba920 100644
--- a/chromium/content/browser/media/media_source_browsertest.cc
+++ b/chromium/content/browser/media/media_source_browsertest.cc
@@ -26,10 +26,17 @@ const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\"";
const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
const char kMp4FlacAudioOnly[] = "audio/mp4; codecs=\"flac\"";
-#if BUILDFLAG(USE_PROPRIETARY_CODECS) && \
- BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+const char kMp4AudioOnly[] = "audio/mp4; codecs=\"mp4a.40.2\"'";
+
+#if !defined(OS_ANDROID)
+const char kMp4VideoOnly[] = "video/mp4; codecs=\"avc1.4D4041\"'";
+#endif // !defined(OS_ANDROID)
+
+#if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
const char kMp2tAudioVideo[] = "video/mp2t; codecs=\"mp4a.40.2, avc1.42E01E\"";
-#endif
+#endif // BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
+#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
namespace content {
@@ -103,8 +110,12 @@ IN_PROC_BROWSER_TEST_F(MediaSourceTest, ConfigChangeVideo) {
#if !defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_Video_MP4_Audio_WEBM) {
base::StringPairs query_params;
- query_params.push_back(std::make_pair("videoFormat", "CLEAR_MP4"));
- query_params.push_back(std::make_pair("audioFormat", "CLEAR_WEBM"));
+ query_params.push_back(
+ std::make_pair("videoFile", "bear-640x360-v_frag.mp4"));
+ query_params.push_back(std::make_pair("videoFormat", kMp4VideoOnly));
+ query_params.push_back(
+ std::make_pair("audioFile", "bear-320x240-audio-only.webm"));
+ query_params.push_back(std::make_pair("audioFormat", kWebMAudioOnly));
RunMediaTestPage("mse_different_containers.html", query_params, media::kEnded,
true);
}
@@ -112,8 +123,12 @@ IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_Video_MP4_Audio_WEBM) {
IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_Video_WEBM_Audio_MP4) {
base::StringPairs query_params;
- query_params.push_back(std::make_pair("videoFormat", "CLEAR_WEBM"));
- query_params.push_back(std::make_pair("audioFormat", "CLEAR_MP4"));
+ query_params.push_back(
+ std::make_pair("videoFile", "bear-320x240-video-only.webm"));
+ query_params.push_back(std::make_pair("videoFormat", kWebMVideoOnly));
+ query_params.push_back(
+ std::make_pair("audioFile", "bear-640x360-a_frag.mp4"));
+ query_params.push_back(std::make_pair("audioFormat", kMp4AudioOnly));
RunMediaTestPage("mse_different_containers.html", query_params, media::kEnded,
true);
}
diff --git a/chromium/content/browser/media/media_web_contents_observer.cc b/chromium/content/browser/media/media_web_contents_observer.cc
index b3abe26c982..1b013f92874 100644
--- a/chromium/content/browser/media/media_web_contents_observer.cc
+++ b/chromium/content/browser/media/media_web_contents_observer.cc
@@ -12,6 +12,7 @@
#include "content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/media/media_player_delegate_messages.h"
+#include "content/public/browser/picture_in_picture_window_controller.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "ipc/ipc_message_macros.h"
@@ -46,11 +47,11 @@ void CheckFullscreenDetectionEnabled(WebContents* web_contents) {
bool MediaPlayerEntryExists(
const WebContentsObserver::MediaPlayerId& player_id,
const MediaWebContentsObserver::ActiveMediaPlayerMap& player_map) {
- const auto& players = player_map.find(player_id.first);
+ const auto& players = player_map.find(player_id.render_frame_host);
if (players == player_map.end())
return false;
- return players->second.find(player_id.second) != players->second.end();
+ return players->second.find(player_id.delegate_id) != players->second.end();
}
} // anonymous namespace
@@ -70,10 +71,16 @@ void MediaWebContentsObserver::RenderFrameDeleted(
ClearWakeLocks(render_frame_host);
session_controllers_manager_.RenderFrameDeleted(render_frame_host);
- if (fullscreen_player_ && fullscreen_player_->first == render_frame_host) {
+ if (fullscreen_player_ &&
+ fullscreen_player_->render_frame_host == render_frame_host) {
picture_in_picture_allowed_in_fullscreen_.reset();
fullscreen_player_.reset();
}
+
+ // Usually the frame will exit PIP before it is deleted but for OOPIF, it
+ // seems that the player never notifies the browser process.
+ if (pip_player_ && pip_player_->render_frame_host == render_frame_host)
+ ExitPictureInPictureInternal();
}
void MediaWebContentsObserver::MaybeUpdateAudibleState() {
@@ -158,10 +165,10 @@ void MediaWebContentsObserver::RequestPersistentVideo(bool value) {
// The message is sent to the renderer even though the video is already the
// fullscreen element itself. It will eventually be handled by Blink.
- RenderFrameHost* target_frame = fullscreen_player_->first;
- int delegate_id = fullscreen_player_->second;
- target_frame->Send(new MediaPlayerDelegateMsg_BecamePersistentVideo(
- target_frame->GetRoutingID(), delegate_id, value));
+ fullscreen_player_->render_frame_host->Send(
+ new MediaPlayerDelegateMsg_BecamePersistentVideo(
+ fullscreen_player_->render_frame_host->GetRoutingID(),
+ fullscreen_player_->delegate_id, value));
}
bool MediaWebContentsObserver::IsPlayerActive(
@@ -176,10 +183,10 @@ void MediaWebContentsObserver::OnPictureInPictureWindowResize(
const gfx::Size& window_size) {
DCHECK(pip_player_.has_value());
- RenderFrameHost* frame = pip_player_->first;
- int delegate_id = pip_player_->second;
- frame->Send(new MediaPlayerDelegateMsg_OnPictureInPictureWindowResize(
- frame->GetRoutingID(), delegate_id, window_size));
+ pip_player_->render_frame_host->Send(
+ new MediaPlayerDelegateMsg_OnPictureInPictureWindowResize(
+ pip_player_->render_frame_host->GetRoutingID(),
+ pip_player_->delegate_id, window_size));
}
void MediaWebContentsObserver::OnMediaDestroyed(
@@ -199,6 +206,18 @@ void MediaWebContentsObserver::OnMediaPaused(RenderFrameHost* render_frame_host,
UpdateVideoLock();
+ // TODO(872066): check for |pip_player_| fully matching paused player.
+ if (!web_contents()->IsBeingDestroyed() && pip_player_.has_value() &&
+ pip_player_->render_frame_host == render_frame_host) {
+ PictureInPictureWindowControllerImpl* pip_controller =
+ PictureInPictureWindowControllerImpl::FromWebContents(
+ web_contents_impl());
+ if (pip_controller) {
+ pip_controller->UpdatePlaybackState(false /* is not playing */,
+ reached_end_of_stream);
+ }
+ }
+
if (removed_audio || removed_video) {
// Notify observers the player has been "paused".
web_contents_impl()->MediaStoppedPlaying(
@@ -243,8 +262,19 @@ void MediaWebContentsObserver::OnMediaPlaying(
return;
}
+ // TODO(872066): check for |pip_player_| fully matching paused player.
+ if (!web_contents()->IsBeingDestroyed() && pip_player_.has_value() &&
+ pip_player_->render_frame_host == render_frame_host) {
+ PictureInPictureWindowControllerImpl* pip_controller =
+ PictureInPictureWindowControllerImpl::FromWebContents(
+ web_contents_impl());
+ if (pip_controller) {
+ pip_controller->UpdatePlaybackState(true /* is not playing */,
+ false /* reached_end_of_stream */);
+ }
+ }
+
// Notify observers of the new player.
- DCHECK(has_audio || has_video);
web_contents_impl()->MediaStartedPlaying(
WebContentsObserver::MediaPlayerInfo(has_video, has_audio), id);
}
@@ -312,17 +342,7 @@ void MediaWebContentsObserver::OnPictureInPictureModeEnded(
RenderFrameHost* render_frame_host,
int delegate_id,
int request_id) {
- // TODO(mlamouri): must be a DCHECK but can't at the moment because we do not
- // correctly notify players when switching PIP video in the same tab.
- if (pip_player_) {
- web_contents_impl()->ExitPictureInPicture();
-
- // Reset must happen after notifying the WebContents because it may interact
- // with it.
- pip_player_.reset();
-
- UpdateVideoLock();
- }
+ ExitPictureInPictureInternal();
render_frame_host->Send(
new MediaPlayerDelegateMsg_OnPictureInPictureModeEnded_ACK(
@@ -337,12 +357,16 @@ void MediaWebContentsObserver::OnPictureInPictureSurfaceChanged(
DCHECK(surface_id.is_valid());
DCHECK(pip_player_);
+ pip_player_ = MediaPlayerId(render_frame_host, delegate_id);
+
PictureInPictureWindowControllerImpl* pip_controller =
PictureInPictureWindowControllerImpl::FromWebContents(
web_contents_impl());
- DCHECK(pip_controller);
- pip_controller->EmbedSurface(surface_id, natural_size);
+ // The PictureInPictureWindowController instance may not have been created by
+ // the embedder.
+ if (pip_controller)
+ pip_controller->EmbedSurface(surface_id, natural_size);
}
void MediaWebContentsObserver::ClearWakeLocks(
@@ -448,18 +472,18 @@ void MediaWebContentsObserver::OnMediaMutedStatusChanged(
void MediaWebContentsObserver::AddMediaPlayerEntry(
const MediaPlayerId& id,
ActiveMediaPlayerMap* player_map) {
- (*player_map)[id.first].insert(id.second);
+ (*player_map)[id.render_frame_host].insert(id.delegate_id);
}
bool MediaWebContentsObserver::RemoveMediaPlayerEntry(
const MediaPlayerId& id,
ActiveMediaPlayerMap* player_map) {
- auto it = player_map->find(id.first);
+ auto it = player_map->find(id.render_frame_host);
if (it == player_map->end())
return false;
// Remove the player.
- bool did_remove = it->second.erase(id.second) == 1;
+ bool did_remove = it->second.erase(id.delegate_id) == 1;
if (!did_remove)
return false;
@@ -484,6 +508,18 @@ void MediaWebContentsObserver::RemoveAllMediaPlayerEntries(
player_map->erase(it);
}
+void MediaWebContentsObserver::ExitPictureInPictureInternal() {
+ DCHECK(pip_player_);
+
+ web_contents_impl()->ExitPictureInPicture();
+
+ // Reset must happen after notifying the WebContents because it may interact
+ // with it.
+ pip_player_.reset();
+
+ UpdateVideoLock();
+}
+
WebContentsImpl* MediaWebContentsObserver::web_contents_impl() const {
return static_cast<WebContentsImpl*>(web_contents());
}
diff --git a/chromium/content/browser/media/media_web_contents_observer.h b/chromium/content/browser/media/media_web_contents_observer.h
index 2655629a1da..67d25de6fd2 100644
--- a/chromium/content/browser/media/media_web_contents_observer.h
+++ b/chromium/content/browser/media/media_web_contents_observer.h
@@ -162,6 +162,10 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
ActiveMediaPlayerMap* player_map,
std::set<MediaPlayerId>* removed_players);
+ // Internal method to exit Picture-in-Picture from an event received from the
+ // renderer process.
+ void ExitPictureInPictureInternal();
+
// Convenience method that casts web_contents() to a WebContentsImpl*.
WebContentsImpl* web_contents_impl() const;
diff --git a/chromium/content/browser/media/midi_host.cc b/chromium/content/browser/media/midi_host.cc
index cc77c0a6895..712e186aab6 100644
--- a/chromium/content/browser/media/midi_host.cc
+++ b/chromium/content/browser/media/midi_host.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/process/process.h"
+#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/bad_message.h"
#include "content/browser/browser_main_loop.h"
@@ -108,8 +109,7 @@ void MidiHost::OnSendData(uint32_t port,
// Blink running in a renderer checks permission to raise a SecurityError
// in JavaScript. The actual permission check for security purposes
// happens here in the browser process.
- if (!has_sys_ex_permission_ &&
- std::find(data.begin(), data.end(), kSysExByte) != data.end()) {
+ if (!has_sys_ex_permission_ && base::ContainsValue(data, kSysExByte)) {
bad_message::ReceivedBadMessage(this, bad_message::MH_SYS_EX_PERMISSION);
return;
}
diff --git a/chromium/content/browser/media/mojo_audio_logging_adapter.cc b/chromium/content/browser/media/mojo_audio_logging_adapter.cc
deleted file mode 100644
index c3ee310692a..00000000000
--- a/chromium/content/browser/media/mojo_audio_logging_adapter.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights 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/mojo_audio_logging_adapter.h"
-
-#include <utility>
-
-#include "content/browser/media/media_internals.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace content {
-
-MojoAudioLogAdapter::MojoAudioLogAdapter(media::mojom::AudioLogPtr audio_log)
- : audio_log_(std::move(audio_log)) {}
-
-MojoAudioLogAdapter::~MojoAudioLogAdapter() = default;
-
-void MojoAudioLogAdapter::OnCreated(const media::AudioParameters& params,
- const std::string& device_id) {
- audio_log_->OnCreated(params, device_id);
-}
-
-void MojoAudioLogAdapter::OnStarted() {
- audio_log_->OnStarted();
-}
-
-void MojoAudioLogAdapter::OnStopped() {
- audio_log_->OnStopped();
-}
-
-void MojoAudioLogAdapter::OnClosed() {
- audio_log_->OnClosed();
-}
-
-void MojoAudioLogAdapter::OnError() {
- audio_log_->OnError();
-}
-
-void MojoAudioLogAdapter::OnSetVolume(double volume) {
- audio_log_->OnSetVolume(volume);
-}
-
-void MojoAudioLogAdapter::OnLogMessage(const std::string& message) {
- audio_log_->OnLogMessage(message);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/mojo_audio_logging_adapter.h b/chromium/content/browser/media/mojo_audio_logging_adapter.h
deleted file mode 100644
index 020d62448e1..00000000000
--- a/chromium/content/browser/media/mojo_audio_logging_adapter.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The Chromium Authors. All 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_MOJO_AUDIO_LOGGING_ADAPTER_H_
-#define CONTENT_BROWSER_MEDIA_MOJO_AUDIO_LOGGING_ADAPTER_H_
-
-#include <map>
-#include <string>
-
-#include "base/macros.h"
-#include "base/sequence_checker.h"
-#include "content/common/content_export.h"
-#include "media/audio/audio_logging.h"
-#include "media/mojo/interfaces/audio_logging.mojom.h"
-
-namespace content {
-
-// This class wraps a media::mojom::AudioLogPtr into a media::AudioLog.
-// TODO(crbug.com/812557): Move this class to the audio service once the audio
-// service is in charge of creating and owning the AudioManager.
-class CONTENT_EXPORT MojoAudioLogAdapter : public media::AudioLog {
- public:
- explicit MojoAudioLogAdapter(media::mojom::AudioLogPtr audio_log);
- ~MojoAudioLogAdapter() override;
-
- // media::AudioLog implementation.
- void OnCreated(const media::AudioParameters& params,
- const std::string& device_id) override;
- void OnStarted() override;
- void OnStopped() override;
- void OnClosed() override;
- void OnError() override;
- void OnSetVolume(double volume) override;
- void OnLogMessage(const std::string& message) override;
-
- private:
- media::mojom::AudioLogPtr audio_log_;
-
- DISALLOW_COPY_AND_ASSIGN(MojoAudioLogAdapter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_MOJO_AUDIO_LOGGING_ADAPTER_H_
diff --git a/chromium/content/browser/media/session/media_session_controller.cc b/chromium/content/browser/media/session/media_session_controller.cc
index 3a59f89f0a0..69df8daac0e 100644
--- a/chromium/content/browser/media/session/media_session_controller.cc
+++ b/chromium/content/browser/media/session/media_session_controller.cc
@@ -77,39 +77,40 @@ bool MediaSessionController::Initialize(
void MediaSessionController::OnSuspend(int player_id) {
DCHECK_EQ(player_id_, player_id);
- id_.first->Send(
- new MediaPlayerDelegateMsg_Pause(id_.first->GetRoutingID(), id_.second));
+ id_.render_frame_host->Send(new MediaPlayerDelegateMsg_Pause(
+ id_.render_frame_host->GetRoutingID(), id_.delegate_id));
}
void MediaSessionController::OnResume(int player_id) {
DCHECK_EQ(player_id_, player_id);
- id_.first->Send(
- new MediaPlayerDelegateMsg_Play(id_.first->GetRoutingID(), id_.second));
+ id_.render_frame_host->Send(new MediaPlayerDelegateMsg_Play(
+ id_.render_frame_host->GetRoutingID(), id_.delegate_id));
}
void MediaSessionController::OnSeekForward(int player_id,
base::TimeDelta seek_time) {
DCHECK_EQ(player_id_, player_id);
- id_.first->Send(new MediaPlayerDelegateMsg_SeekForward(
- id_.first->GetRoutingID(), id_.second, seek_time));
+ id_.render_frame_host->Send(new MediaPlayerDelegateMsg_SeekForward(
+ id_.render_frame_host->GetRoutingID(), id_.delegate_id, seek_time));
}
void MediaSessionController::OnSeekBackward(int player_id,
base::TimeDelta seek_time) {
DCHECK_EQ(player_id_, player_id);
- id_.first->Send(new MediaPlayerDelegateMsg_SeekBackward(
- id_.first->GetRoutingID(), id_.second, seek_time));
+ id_.render_frame_host->Send(new MediaPlayerDelegateMsg_SeekBackward(
+ id_.render_frame_host->GetRoutingID(), id_.delegate_id, seek_time));
}
void MediaSessionController::OnSetVolumeMultiplier(int player_id,
double volume_multiplier) {
DCHECK_EQ(player_id_, player_id);
- id_.first->Send(new MediaPlayerDelegateMsg_UpdateVolumeMultiplier(
- id_.first->GetRoutingID(), id_.second, volume_multiplier));
+ id_.render_frame_host->Send(new MediaPlayerDelegateMsg_UpdateVolumeMultiplier(
+ id_.render_frame_host->GetRoutingID(), id_.delegate_id,
+ volume_multiplier));
}
RenderFrameHost* MediaSessionController::render_frame_host() const {
- return id_.first;
+ return id_.render_frame_host;
}
void MediaSessionController::OnPlaybackPaused() {
diff --git a/chromium/content/browser/media/session/media_session_controller_unittest.cc b/chromium/content/browser/media/session/media_session_controller_unittest.cc
index 96fd8a37b00..433d2de0937 100644
--- a/chromium/content/browser/media/session/media_session_controller_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_controller_unittest.cc
@@ -74,9 +74,9 @@ class MediaSessionControllerTest : public RenderViewHostImplTestHarness {
if (!T::Read(msg, &result))
return false;
- EXPECT_EQ(id_.second, std::get<0>(result));
+ EXPECT_EQ(id_.delegate_id, std::get<0>(result));
test_sink().ClearMessages();
- return id_.second == std::get<0>(result);
+ return id_.delegate_id == std::get<0>(result);
}
template <typename T>
@@ -89,8 +89,8 @@ class MediaSessionControllerTest : public RenderViewHostImplTestHarness {
if (!T::Read(msg, &result))
return false;
- EXPECT_EQ(id_.second, std::get<0>(result));
- if (id_.second != std::get<0>(result))
+ EXPECT_EQ(id_.delegate_id, std::get<0>(result));
+ if (id_.delegate_id != std::get<0>(result))
return false;
EXPECT_EQ(expected_seek_time, std::get<1>(result));
@@ -108,8 +108,8 @@ class MediaSessionControllerTest : public RenderViewHostImplTestHarness {
if (!T::Read(msg, &result))
return false;
- EXPECT_EQ(id_.second, std::get<0>(result));
- if (id_.second != std::get<0>(result))
+ EXPECT_EQ(id_.delegate_id, std::get<0>(result));
+ if (id_.delegate_id != std::get<0>(result))
return false;
EXPECT_EQ(expected_multiplier, std::get<1>(result));
@@ -117,7 +117,8 @@ class MediaSessionControllerTest : public RenderViewHostImplTestHarness {
return expected_multiplier == std::get<1>(result);
}
- WebContentsObserver::MediaPlayerId id_;
+ WebContentsObserver::MediaPlayerId id_ =
+ WebContentsObserver::MediaPlayerId::createMediaPlayerIdForTests();
std::unique_ptr<MediaSessionController> controller_;
};
diff --git a/chromium/content/browser/media/session/media_session_controllers_manager.cc b/chromium/content/browser/media/session/media_session_controllers_manager.cc
index 6eb3dd46032..33947c0d4b6 100644
--- a/chromium/content/browser/media/session/media_session_controllers_manager.cc
+++ b/chromium/content/browser/media/session/media_session_controllers_manager.cc
@@ -38,7 +38,7 @@ void MediaSessionControllersManager::RenderFrameDeleted(
return;
for (auto it = controllers_map_.begin(); it != controllers_map_.end();) {
- if (it->first.first == render_frame_host)
+ if (it->first.render_frame_host == render_frame_host)
it = controllers_map_.erase(it);
else
++it;
diff --git a/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc b/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc
index 61771490a62..e8e18e1f400 100644
--- a/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc
@@ -90,7 +90,9 @@ class MediaSessionControllersManagerTest
}
protected:
- MediaSessionControllersManager::MediaPlayerId media_player_id_;
+ MediaSessionControllersManager::MediaPlayerId media_player_id_ =
+ MediaSessionControllersManager::MediaPlayerId::
+ createMediaPlayerIdForTests();
std::unique_ptr<StrictMock<MockMediaSessionController>>
mock_media_session_controller_;
StrictMock<MockMediaSessionController>* mock_media_session_controller_ptr_ =
diff --git a/chromium/content/browser/media/session/media_session_impl_browsertest.cc b/chromium/content/browser/media/session/media_session_impl_browsertest.cc
index 28fdcebf58d..f423db1ed37 100644
--- a/chromium/content/browser/media/session/media_session_impl_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_browsertest.cc
@@ -13,7 +13,7 @@
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_samples.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h"
#include "content/browser/media/session/audio_focus_delegate.h"
#include "content/browser/media/session/media_session_service_impl.h"
diff --git a/chromium/content/browser/media/session/media_session_impl_uma_unittest.cc b/chromium/content/browser/media/session/media_session_impl_uma_unittest.cc
index 95e428bd4c6..1efa52b4fd1 100644
--- a/chromium/content/browser/media/session/media_session_impl_uma_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_uma_unittest.cc
@@ -8,7 +8,7 @@
#include <memory>
#include "base/metrics/histogram_samples.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "content/browser/media/session/media_session_player_observer.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
diff --git a/chromium/content/browser/media/session/media_session_service_impl_browsertest.cc b/chromium/content/browser/media/session/media_session_service_impl_browsertest.cc
index 2a11394e2b2..00717a379e4 100644
--- a/chromium/content/browser/media/session/media_session_service_impl_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_service_impl_browsertest.cc
@@ -139,9 +139,15 @@ class MediaSessionServiceImplBrowserTest : public ContentBrowserTest {
std::unique_ptr<MockMediaSessionPlayerObserver> player_;
};
+#if defined(LEAK_SANITIZER)
+// TODO(crbug.com/850870) Plug the leaks.
+#define MAYBE_CrashMessageOnUnload DISABLED_CrashMessageOnUnload
+#else
+#define MAYBE_CrashMessageOnUnload CrashMessageOnUnload
+#endif
// Two windows from the same BrowserContext.
IN_PROC_BROWSER_TEST_F(MediaSessionServiceImplBrowserTest,
- CrashMessageOnUnload) {
+ MAYBE_CrashMessageOnUnload) {
NavigateToURL(shell(), GetTestUrl("media/session", "embedder.html"));
// Navigate to a chrome:// URL to avoid render process re-use.
NavigateToURL(shell(), GURL("chrome://flags"));
@@ -154,8 +160,15 @@ IN_PROC_BROWSER_TEST_F(MediaSessionServiceImplBrowserTest,
// observers to wait for the message to be processed on the MediaSessionObserver
// side.
+#if defined(LEAK_SANITIZER)
+// TODO(crbug.com/850870) Plug the leaks.
+#define MAYBE_ResetServiceWhenNavigatingAway \
+ DISABLED_ResetServiceWhenNavigatingAway
+#else
+#define MAYBE_ResetServiceWhenNavigatingAway ResetServiceWhenNavigatingAway
+#endif
IN_PROC_BROWSER_TEST_F(MediaSessionServiceImplBrowserTest,
- ResetServiceWhenNavigatingAway) {
+ MAYBE_ResetServiceWhenNavigatingAway) {
NavigateToURL(shell(), GetTestUrl(".", "title1.html"));
EnsurePlayer();
@@ -176,8 +189,16 @@ IN_PROC_BROWSER_TEST_F(MediaSessionServiceImplBrowserTest,
EXPECT_EQ(0u, GetService()->actions().size());
}
+#if defined(LEAK_SANITIZER)
+// TODO(crbug.com/850870) Plug the leaks.
+#define MAYBE_DontResetServiceForSameDocumentNavigation \
+ DISABLED_DontResetServiceForSameDocumentNavigation
+#else
+#define MAYBE_DontResetServiceForSameDocumentNavigation \
+ DontResetServiceForSameDocumentNavigation
+#endif
IN_PROC_BROWSER_TEST_F(MediaSessionServiceImplBrowserTest,
- DontResetServiceForSameDocumentNavigation) {
+ MAYBE_DontResetServiceForSameDocumentNavigation) {
NavigateToURL(shell(), GetTestUrl(".", "title1.html"));
EnsurePlayer();
diff --git a/chromium/content/browser/media/session/media_session_uma_helper_unittest.cc b/chromium/content/browser/media/session/media_session_uma_helper_unittest.cc
index 4b6fc027436..973d7650b02 100644
--- a/chromium/content/browser/media/session/media_session_uma_helper_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_uma_helper_unittest.cc
@@ -5,7 +5,7 @@
#include "content/browser/media/session/media_session_uma_helper.h"
#include "base/metrics/histogram_samples.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/content/browser/memory/memory_coordinator_impl_browsertest.cc b/chromium/content/browser/memory/memory_coordinator_impl_browsertest.cc
index 9966aafe47a..3a84581863b 100644
--- a/chromium/content/browser/memory/memory_coordinator_impl_browsertest.cc
+++ b/chromium/content/browser/memory/memory_coordinator_impl_browsertest.cc
@@ -6,6 +6,7 @@
#include "base/test/scoped_feature_list.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/public/common/content_features.h"
#include "content/public/test/content_browser_test.h"
@@ -32,10 +33,24 @@ class MemoryCoordinatorImplBrowserTest : public ContentBrowserTest {
// implemented.
#if !defined(OS_MACOSX)
+void GetGpuProcessIDOnIO(int* gpu_process_id, base::WaitableEvent* event) {
+ *gpu_process_id = GpuProcessHost::Get()->GetIDForTesting();
+ event->Signal();
+}
+
IN_PROC_BROWSER_TEST_F(MemoryCoordinatorImplBrowserTest, HandleAdded) {
GURL url = GetTestUrl("", "simple_page.html");
NavigateToURL(shell(), url);
+ // Query the GPU process ID from the IO thread.
+ int gpu_process_id = -1;
+ base::WaitableEvent io_event;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&GetGpuProcessIDOnIO, &gpu_process_id, &io_event));
+ io_event.Wait();
+ ASSERT_NE(gpu_process_id, -1);
+
size_t num_children = 0;
for (auto const& it : MemoryCoordinatorImpl::GetInstance()->children()) {
int process_id = it.first;
@@ -46,6 +61,10 @@ IN_PROC_BROWSER_TEST_F(MemoryCoordinatorImplBrowserTest, HandleAdded) {
if (spare_process && process_id == spare_process->GetID())
continue;
+ // Ignore the GPU process.
+ if (process_id == gpu_process_id)
+ continue;
+
num_children++;
}
diff --git a/chromium/content/browser/mojo_sandbox_browsertest.cc b/chromium/content/browser/mojo_sandbox_browsertest.cc
index 8ec022566d6..89168cc96c9 100644
--- a/chromium/content/browser/mojo_sandbox_browsertest.cc
+++ b/chromium/content/browser/mojo_sandbox_browsertest.cc
@@ -52,6 +52,7 @@ class MojoSandboxTest : public ContentBrowserTest {
private:
void StartUtilityProcessOnIoThread() {
host_.reset(new UtilityProcessHost(nullptr, nullptr));
+ host_->SetMetricsName("mojo_sandbox_test_process");
ASSERT_TRUE(host_->Start());
}
diff --git a/chromium/content/browser/net/network_quality_observer_impl.cc b/chromium/content/browser/net/network_quality_observer_impl.cc
index 6dd157e8218..dafe9179271 100644
--- a/chromium/content/browser/net/network_quality_observer_impl.cc
+++ b/chromium/content/browser/net/network_quality_observer_impl.cc
@@ -91,10 +91,12 @@ class NetworkQualityObserverImpl::UiThreadObserver
// Notify all the existing renderers of the change in the network quality.
for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
!it.IsAtEnd(); it.Advance()) {
- it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged(
- last_notified_type_, last_notified_network_quality_.http_rtt(),
- last_notified_network_quality_.transport_rtt(),
- last_notified_network_quality_.downstream_throughput_kbps());
+ if (it.GetCurrentValue()->IsInitializedAndNotDead()) {
+ it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged(
+ last_notified_type_, last_notified_network_quality_.http_rtt(),
+ last_notified_network_quality_.transport_rtt(),
+ last_notified_network_quality_.downstream_throughput_kbps());
+ }
}
}
@@ -107,10 +109,12 @@ class NetworkQualityObserverImpl::UiThreadObserver
// Notify all the existing renderers of the change in the network quality.
for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
!it.IsAtEnd(); it.Advance()) {
- it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged(
- last_notified_type_, last_notified_network_quality_.http_rtt(),
- last_notified_network_quality_.transport_rtt(),
- last_notified_network_quality_.downstream_throughput_kbps());
+ if (it.GetCurrentValue()->IsInitializedAndNotDead()) {
+ it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged(
+ last_notified_type_, last_notified_network_quality_.http_rtt(),
+ last_notified_network_quality_.transport_rtt(),
+ last_notified_network_quality_.downstream_throughput_kbps());
+ }
}
}
diff --git a/chromium/content/browser/net/network_quality_observer_impl_unittest.cc b/chromium/content/browser/net/network_quality_observer_impl_unittest.cc
index 19e9d677fe8..cd9ab62b89b 100644
--- a/chromium/content/browser/net/network_quality_observer_impl_unittest.cc
+++ b/chromium/content/browser/net/network_quality_observer_impl_unittest.cc
@@ -5,7 +5,7 @@
#include "content/browser/net/network_quality_observer_impl.h"
#include "base/run_loop.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/nqe/effective_connection_type.h"
diff --git a/chromium/content/browser/net/quota_policy_cookie_store.cc b/chromium/content/browser/net/quota_policy_cookie_store.cc
index 98068af557c..116ce029657 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store.cc
@@ -21,102 +21,23 @@
#include "net/cookies/cookie_util.h"
#include "net/extras/sqlite/cookie_crypto_delegate.h"
#include "storage/browser/quota/special_storage_policy.h"
-#include "url/gurl.h"
namespace content {
QuotaPolicyCookieStore::QuotaPolicyCookieStore(
const scoped_refptr<net::SQLitePersistentCookieStore>& cookie_store,
storage::SpecialStoragePolicy* special_storage_policy)
- : special_storage_policy_(special_storage_policy),
- persistent_store_(cookie_store) {
-}
+ : SessionCleanupCookieStore(cookie_store),
+ special_storage_policy_(special_storage_policy) {}
QuotaPolicyCookieStore::~QuotaPolicyCookieStore() {
- using CookieOrigin = net::SQLitePersistentCookieStore::CookieOrigin;
if (!special_storage_policy_.get() ||
!special_storage_policy_->HasSessionOnlyOrigins()) {
return;
}
- std::list<CookieOrigin> session_only_cookies;
- auto delete_cookie_predicate =
- special_storage_policy_->CreateDeleteCookieOnExitPredicate();
- DCHECK(delete_cookie_predicate);
-
- for (const auto& entry : cookies_per_origin_) {
- if (entry.second == 0) {
- continue;
- }
- const CookieOrigin& cookie = entry.first;
- const GURL url(
- net::cookie_util::CookieOriginToURL(cookie.first, cookie.second));
- if (!url.is_valid() ||
- !delete_cookie_predicate.Run(cookie.first, cookie.second)) {
- continue;
- }
- session_only_cookies.push_back(cookie);
- }
-
- persistent_store_->DeleteAllInList(session_only_cookies);
-}
-
-void QuotaPolicyCookieStore::Load(const LoadedCallback& loaded_callback) {
- persistent_store_->Load(
- base::Bind(&QuotaPolicyCookieStore::OnLoad, this, loaded_callback));
-}
-
-void QuotaPolicyCookieStore::LoadCookiesForKey(
- const std::string& key,
- const LoadedCallback& loaded_callback) {
- persistent_store_->LoadCookiesForKey(
- key,
- base::Bind(&QuotaPolicyCookieStore::OnLoad, this, loaded_callback));
-}
-
-void QuotaPolicyCookieStore::AddCookie(const net::CanonicalCookie& cc) {
- net::SQLitePersistentCookieStore::CookieOrigin origin(
- cc.Domain(), cc.IsSecure());
- ++cookies_per_origin_[origin];
- persistent_store_->AddCookie(cc);
-}
-
-void QuotaPolicyCookieStore::UpdateCookieAccessTime(
- const net::CanonicalCookie& cc) {
- persistent_store_->UpdateCookieAccessTime(cc);
-}
-
-void QuotaPolicyCookieStore::DeleteCookie(const net::CanonicalCookie& cc) {
- net::SQLitePersistentCookieStore::CookieOrigin origin(
- cc.Domain(), cc.IsSecure());
- DCHECK_GE(cookies_per_origin_[origin], 1U);
- --cookies_per_origin_[origin];
- persistent_store_->DeleteCookie(cc);
-}
-
-void QuotaPolicyCookieStore::SetForceKeepSessionState() {
- special_storage_policy_ = nullptr;
-}
-
-void QuotaPolicyCookieStore::SetBeforeFlushCallback(
- base::RepeatingClosure callback) {
- persistent_store_->SetBeforeFlushCallback(std::move(callback));
-}
-
-void QuotaPolicyCookieStore::Flush(base::OnceClosure callback) {
- persistent_store_->Flush(std::move(callback));
-}
-
-void QuotaPolicyCookieStore::OnLoad(
- const LoadedCallback& loaded_callback,
- std::vector<std::unique_ptr<net::CanonicalCookie>> cookies) {
- for (const auto& cookie : cookies) {
- net::SQLitePersistentCookieStore::CookieOrigin origin(
- cookie->Domain(), cookie->IsSecure());
- ++cookies_per_origin_[origin];
- }
-
- loaded_callback.Run(std::move(cookies));
+ DeleteSessionCookies(
+ special_storage_policy_->CreateDeleteCookieOnExitPredicate());
}
CookieStoreConfig::CookieStoreConfig()
diff --git a/chromium/content/browser/net/quota_policy_cookie_store.h b/chromium/content/browser/net/quota_policy_cookie_store.h
index f55b34a3a1f..e7540e599aa 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store.h
+++ b/chromium/content/browser/net/quota_policy_cookie_store.h
@@ -11,16 +11,11 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
-#include "net/cookies/cookie_monster.h"
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
-
-namespace net {
-class CanonicalCookie;
-} // namespace net
+#include "services/network/session_cleanup_cookie_store.h"
namespace storage {
class SpecialStoragePolicy;
@@ -34,41 +29,17 @@ namespace content {
// |SpecialStoragePolicy| is consulted when the SQLite database is closed to
// decide which cookies to keep.
class CONTENT_EXPORT QuotaPolicyCookieStore
- : public net::CookieMonster::PersistentCookieStore {
+ : public network::SessionCleanupCookieStore {
public:
// Wraps the passed-in |cookie_store|.
QuotaPolicyCookieStore(
const scoped_refptr<net::SQLitePersistentCookieStore>& cookie_store,
storage::SpecialStoragePolicy* special_storage_policy);
- // net::CookieMonster::PersistentCookieStore:
- void Load(const LoadedCallback& loaded_callback) override;
- void LoadCookiesForKey(const std::string& key,
- const LoadedCallback& callback) override;
- void AddCookie(const net::CanonicalCookie& cc) override;
- void UpdateCookieAccessTime(const net::CanonicalCookie& cc) override;
- void DeleteCookie(const net::CanonicalCookie& cc) override;
- void SetForceKeepSessionState() override;
- void SetBeforeFlushCallback(base::RepeatingClosure callback) override;
- void Flush(base::OnceClosure callback) override;
-
private:
- typedef std::map<net::SQLitePersistentCookieStore::CookieOrigin, size_t>
- CookiesPerOriginMap;
-
~QuotaPolicyCookieStore() override;
- // Called after cookies are loaded from the database. Calls |loaded_callback|
- // when done.
- void OnLoad(const LoadedCallback& loaded_callback,
- std::vector<std::unique_ptr<net::CanonicalCookie>> cookies);
-
- // Map of (domain keys(eTLD+1), is secure cookie) to number of cookies in the
- // database.
- CookiesPerOriginMap cookies_per_origin_;
-
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
- scoped_refptr<net::SQLitePersistentCookieStore> persistent_store_;
DISALLOW_COPY_AND_ASSIGN(QuotaPolicyCookieStore);
};
diff --git a/chromium/content/browser/net/reporting_service_proxy.cc b/chromium/content/browser/net/reporting_service_proxy.cc
index a729bc91dc4..6f525514216 100644
--- a/chromium/content/browser/net/reporting_service_proxy.cc
+++ b/chromium/content/browser/net/reporting_service_proxy.cc
@@ -16,6 +16,7 @@
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/reporting/reporting_report.h"
#include "net/reporting/reporting_service.h"
+#include "net/url_request/http_user_agent_settings.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "third_party/blink/public/platform/reporting.mojom.h"
@@ -35,32 +36,38 @@ class ReportingServiceProxyImpl : public blink::mojom::ReportingServiceProxy {
void QueueInterventionReport(const GURL& url,
const std::string& message,
- const std::string& source_file,
+ const base::Optional<std::string>& source_file,
int line_number,
int column_number) override {
auto body = std::make_unique<base::DictionaryValue>();
body->SetString("message", message);
- body->SetString("sourceFile", source_file);
- body->SetInteger("lineNumber", line_number);
- body->SetInteger("columnNumber", column_number);
+ if (source_file)
+ body->SetString("sourceFile", *source_file);
+ if (line_number)
+ body->SetInteger("lineNumber", line_number);
+ if (column_number)
+ body->SetInteger("columnNumber", column_number);
QueueReport(url, "default", "intervention", std::move(body));
}
void QueueDeprecationReport(const GURL& url,
const std::string& id,
- base::Time anticipatedRemoval,
+ base::Optional<base::Time> anticipatedRemoval,
const std::string& message,
- const std::string& source_file,
+ const base::Optional<std::string>& source_file,
int line_number,
int column_number) override {
auto body = std::make_unique<base::DictionaryValue>();
body->SetString("id", id);
- if (anticipatedRemoval.is_null())
- body->SetDouble("anticipatedRemoval", anticipatedRemoval.ToDoubleT());
+ if (anticipatedRemoval)
+ body->SetDouble("anticipatedRemoval", anticipatedRemoval->ToDoubleT());
body->SetString("message", message);
- body->SetString("sourceFile", source_file);
- body->SetInteger("lineNumber", line_number);
- body->SetInteger("columnNumber", column_number);
+ if (source_file)
+ body->SetString("sourceFile", *source_file);
+ if (line_number)
+ body->SetInteger("lineNumber", line_number);
+ if (column_number)
+ body->SetInteger("columnNumber", column_number);
QueueReport(url, "default", "deprecation", std::move(body));
}
@@ -75,7 +82,7 @@ class ReportingServiceProxyImpl : public blink::mojom::ReportingServiceProxy {
const std::string& blocked_uri,
int line_number,
int column_number,
- const std::string& source_file,
+ const base::Optional<std::string>& source_file,
int status_code,
const std::string& script_sample) override {
auto body = std::make_unique<base::DictionaryValue>();
@@ -90,7 +97,8 @@ class ReportingServiceProxyImpl : public blink::mojom::ReportingServiceProxy {
body->SetInteger("line-number", line_number);
if (column_number)
body->SetInteger("column-number", column_number);
- body->SetString("source-file", source_file);
+ if (source_file)
+ body->SetString("sourceFile", *source_file);
if (status_code)
body->SetInteger("status-code", status_code);
body->SetString("script-sample", script_sample);
@@ -118,7 +126,11 @@ class ReportingServiceProxyImpl : public blink::mojom::ReportingServiceProxy {
// Depth is only non-zero for NEL reports, and those can't come from the
// renderer.
- reporting_service->QueueReport(url, group, type, std::move(body),
+ std::string user_agent;
+ if (request_context->http_user_agent_settings() != nullptr)
+ user_agent = request_context->http_user_agent_settings()->GetUserAgent();
+ reporting_service->QueueReport(url, user_agent, group, type,
+ std::move(body),
/* depth= */ 0);
}
diff --git a/chromium/content/browser/net_info_browsertest.cc b/chromium/content/browser/net_info_browsertest.cc
index 1ef2c6511fd..e5bf126c3c4 100644
--- a/chromium/content/browser/net_info_browsertest.cc
+++ b/chromium/content/browser/net_info_browsertest.cc
@@ -9,7 +9,7 @@
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "content/browser/net/network_quality_observer_impl.h"
#include "content/public/common/content_switches.h"
diff --git a/chromium/content/browser/network_service_browsertest.cc b/chromium/content/browser/network_service_browsertest.cc
index 1e329cf5dfa..e8e70eb852f 100644
--- a/chromium/content/browser/network_service_browsertest.cc
+++ b/chromium/content/browser/network_service_browsertest.cc
@@ -56,12 +56,14 @@ class RenderProcessKilledObserver : public WebContentsObserver {
class WebUITestWebUIControllerFactory : public WebUIControllerFactory {
public:
- WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
- const GURL& url) const override {
+ std::unique_ptr<WebUIController> CreateWebUIControllerForURL(
+ WebUI* web_ui,
+ const GURL& url) const override {
std::string foo(url.path());
if (url.path() == "/nobinding/")
web_ui->SetBindings(0);
- return HasWebUIScheme(url) ? new WebUIController(web_ui) : nullptr;
+ return HasWebUIScheme(url) ? std::make_unique<WebUIController>(web_ui)
+ : nullptr;
}
WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
const GURL& url) const override {
diff --git a/chromium/content/browser/network_service_client.cc b/chromium/content/browser/network_service_client.cc
index 08fdcd44f7e..afeafe636a5 100644
--- a/chromium/content/browser/network_service_client.cc
+++ b/chromium/content/browser/network_service_client.cc
@@ -5,6 +5,7 @@
#include "content/browser/network_service_client.h"
#include "base/optional.h"
+#include "base/task_scheduler/post_task.h"
#include "content/browser/devtools/devtools_url_loader_interceptor.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/ssl/ssl_client_auth_handler.h"
@@ -14,11 +15,14 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/global_request_id.h"
#include "content/public/browser/login_delegate.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/resource_type.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/ssl/client_cert_store.h"
+#include "services/network/public/mojom/network_context.mojom.h"
namespace content {
namespace {
@@ -166,11 +170,14 @@ class LoginHandlerDelegate {
uint32_t routing_id,
uint32_t request_id,
const GURL& url,
+ scoped_refptr<net::HttpResponseHeaders> response_headers,
bool first_auth_attempt)
: auth_challenge_responder_(std::move(auth_challenge_responder)),
auth_info_(auth_info),
+ request_id_(process_id, request_id),
is_request_for_main_frame_(is_request_for_main_frame),
url_(url),
+ response_headers_(std::move(response_headers)),
first_auth_attempt_(first_auth_attempt),
web_contents_getter_(web_contents_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -226,8 +233,9 @@ class LoginHandlerDelegate {
void CreateLoginDelegate() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
login_delegate_ = GetContentClient()->browser()->CreateLoginDelegate(
- auth_info_.get(), web_contents_getter_, is_request_for_main_frame_,
- url_, first_auth_attempt_,
+ auth_info_.get(), web_contents_getter_, request_id_,
+ is_request_for_main_frame_, url_, response_headers_,
+ first_auth_attempt_,
base::BindOnce(&LoginHandlerDelegate::RunAuthCredentials,
base::Unretained(this)));
@@ -255,13 +263,47 @@ class LoginHandlerDelegate {
network::mojom::AuthChallengeResponderPtr auth_challenge_responder_;
scoped_refptr<net::AuthChallengeInfo> auth_info_;
+ const content::GlobalRequestID request_id_;
bool is_request_for_main_frame_;
GURL url_;
+ const scoped_refptr<net::HttpResponseHeaders> response_headers_;
bool first_auth_attempt_;
ResourceRequestInfo::WebContentsGetter web_contents_getter_;
scoped_refptr<LoginDelegate> login_delegate_;
};
+void HandleFileUploadRequest(
+ uint32_t process_id,
+ bool async,
+ const std::vector<base::FilePath>& file_paths,
+ NetworkServiceClient::OnFileUploadRequestedCallback callback,
+ scoped_refptr<base::TaskRunner> task_runner) {
+ std::vector<base::File> files;
+ uint32_t file_flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
+ (async ? base::File::FLAG_ASYNC : 0);
+ ChildProcessSecurityPolicy* cpsp = ChildProcessSecurityPolicy::GetInstance();
+ for (const auto& file_path : file_paths) {
+ if (process_id != network::mojom::kBrowserProcessId &&
+ !cpsp->CanReadFile(process_id, file_path)) {
+ task_runner->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), net::ERR_ACCESS_DENIED,
+ std::vector<base::File>()));
+ return;
+ }
+ files.emplace_back(file_path, file_flags);
+ if (!files.back().IsValid()) {
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback),
+ net::FileErrorToNetError(files.back().error_details()),
+ std::vector<base::File>()));
+ return;
+ }
+ }
+ task_runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback), net::OK,
+ std::move(files)));
+}
+
} // namespace
NetworkServiceClient::NetworkServiceClient(
@@ -279,6 +321,7 @@ void NetworkServiceClient::OnAuthRequired(
bool first_auth_attempt,
const scoped_refptr<net::AuthChallengeInfo>& auth_info,
int32_t resource_type,
+ const base::Optional<network::ResourceResponseHead>& head,
network::mojom::AuthChallengeResponderPtr auth_challenge_responder) {
base::Callback<WebContents*(void)> web_contents_getter =
process_id ? base::Bind(WebContentsImpl::FromRenderFrameHostID,
@@ -302,7 +345,7 @@ void NetworkServiceClient::OnAuthRequired(
new LoginHandlerDelegate(std::move(auth_challenge_responder),
std::move(web_contents_getter), auth_info,
is_request_for_main_frame, process_id, routing_id,
- request_id, url,
+ request_id, url, head ? head->headers : nullptr,
first_auth_attempt); // deletes self
}
@@ -349,4 +392,37 @@ void NetworkServiceClient::OnSSLCertificateError(
std::move(web_contents_getter), ssl_info, fatal);
}
+void NetworkServiceClient::OnFileUploadRequested(
+ uint32_t process_id,
+ bool async,
+ const std::vector<base::FilePath>& file_paths,
+ OnFileUploadRequestedCallback callback) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::BindOnce(&HandleFileUploadRequest, process_id, async, file_paths,
+ std::move(callback),
+ base::SequencedTaskRunnerHandle::Get()));
+}
+
+void NetworkServiceClient::OnCookiesRead(int process_id,
+ int routing_id,
+ const GURL& url,
+ const GURL& first_party_url,
+ const net::CookieList& cookie_list,
+ bool blocked_by_policy) {
+ GetContentClient()->browser()->OnCookiesRead(process_id, routing_id, url,
+ first_party_url, cookie_list,
+ blocked_by_policy);
+}
+
+void NetworkServiceClient::OnCookieChange(int process_id,
+ int routing_id,
+ const GURL& url,
+ const GURL& first_party_url,
+ const net::CanonicalCookie& cookie,
+ bool blocked_by_policy) {
+ GetContentClient()->browser()->OnCookieChange(
+ process_id, routing_id, url, first_party_url, cookie, blocked_by_policy);
+}
+
} // namespace content
diff --git a/chromium/content/browser/network_service_client.h b/chromium/content/browser/network_service_client.h
index 900cba838bc..68c0af0a499 100644
--- a/chromium/content/browser/network_service_client.h
+++ b/chromium/content/browser/network_service_client.h
@@ -6,13 +6,15 @@
#define CONTENT_BROWSER_NETWORK_SERVICE_IMPL_H_
#include "base/macros.h"
+#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "url/gurl.h"
namespace content {
-class NetworkServiceClient : public network::mojom::NetworkServiceClient {
+class CONTENT_EXPORT NetworkServiceClient
+ : public network::mojom::NetworkServiceClient {
public:
explicit NetworkServiceClient(network::mojom::NetworkServiceClientRequest
network_service_client_request);
@@ -27,6 +29,7 @@ class NetworkServiceClient : public network::mojom::NetworkServiceClient {
bool first_auth_attempt,
const scoped_refptr<net::AuthChallengeInfo>& auth_info,
int32_t resource_type,
+ const base::Optional<network::ResourceResponseHead>& head,
network::mojom::AuthChallengeResponderPtr
auth_challenge_responder) override;
void OnCertificateRequested(
@@ -44,6 +47,22 @@ class NetworkServiceClient : public network::mojom::NetworkServiceClient {
const net::SSLInfo& ssl_info,
bool fatal,
OnSSLCertificateErrorCallback response) override;
+ void OnFileUploadRequested(uint32_t process_id,
+ bool async,
+ const std::vector<base::FilePath>& file_paths,
+ OnFileUploadRequestedCallback callback) override;
+ void OnCookiesRead(int process_id,
+ int routing_id,
+ const GURL& url,
+ const GURL& first_party_url,
+ const net::CookieList& cookie_list,
+ bool blocked_by_policy) override;
+ void OnCookieChange(int process_id,
+ int routing_id,
+ const GURL& url,
+ const GURL& first_party_url,
+ const net::CanonicalCookie& cookie,
+ bool blocked_by_policy) override;
private:
mojo::Binding<network::mojom::NetworkServiceClient> binding_;
diff --git a/chromium/content/browser/network_service_client_unittest.cc b/chromium/content/browser/network_service_client_unittest.cc
new file mode 100644
index 00000000000..37bf2ef1fd6
--- /dev/null
+++ b/chromium/content/browser/network_service_client_unittest.cc
@@ -0,0 +1,192 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/network_service_client.h"
+
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/test/scoped_task_environment.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+struct UploadResponse {
+ UploadResponse()
+ : callback(base::BindOnce(&UploadResponse::OnComplete,
+ base::Unretained(this))) {}
+
+ void OnComplete(int error_code, std::vector<base::File> opened_files) {
+ this->error_code = error_code;
+ this->opened_files = std::move(opened_files);
+ }
+
+ network::mojom::NetworkServiceClient::OnFileUploadRequestedCallback callback;
+ int error_code;
+ std::vector<base::File> opened_files;
+};
+
+void GrantAccess(const base::FilePath& file, int process_id) {
+ ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(process_id, file);
+}
+
+void CreateFile(const base::FilePath& path, const char* content) {
+ base::File file(path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
+ ASSERT_TRUE(file.IsValid());
+ int content_size = strlen(content);
+ int bytes_written = file.Write(0, content, content_size);
+ EXPECT_EQ(bytes_written, content_size);
+}
+
+void ValidateFileContents(base::File& file, const char* expected_content) {
+ int expected_length = strlen(expected_content);
+ ASSERT_EQ(file.GetLength(), expected_length);
+ char content[expected_length];
+ file.Read(0, content, expected_length);
+ EXPECT_EQ(0, strncmp(content, expected_content, expected_length));
+}
+
+const int kBrowserProcessId = 0;
+const int kRendererProcessId = 1;
+const char kFileContent1[] = "test file content one";
+const char kFileContent2[] = "test file content two";
+
+} // namespace
+
+class NetworkServiceClientTest : public testing::Test {
+ public:
+ NetworkServiceClientTest() : client_(mojo::MakeRequest(&client_ptr_)) {}
+
+ void SetUp() override {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ ChildProcessSecurityPolicyImpl::GetInstance()->Add(kRendererProcessId);
+ }
+
+ void TearDown() override {
+ ChildProcessSecurityPolicyImpl::GetInstance()->Remove(kRendererProcessId);
+ }
+
+ protected:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ network::mojom::NetworkServiceClientPtr client_ptr_;
+ NetworkServiceClient client_;
+ base::ScopedTempDir temp_dir_;
+};
+
+TEST_F(NetworkServiceClientTest, UploadNoFiles) {
+ UploadResponse response;
+ client_.OnFileUploadRequested(kRendererProcessId, true, {},
+ std::move(response.callback));
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_EQ(net::OK, response.error_code);
+ EXPECT_EQ(0U, response.opened_files.size());
+}
+
+TEST_F(NetworkServiceClientTest, UploadOneValidAsyncFile) {
+ base::FilePath path = temp_dir_.GetPath().AppendASCII("filename");
+ CreateFile(path, kFileContent1);
+ GrantAccess(path, kRendererProcessId);
+
+ UploadResponse response;
+ client_.OnFileUploadRequested(kRendererProcessId, true, {path},
+ std::move(response.callback));
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_EQ(net::OK, response.error_code);
+ ASSERT_EQ(1U, response.opened_files.size());
+ EXPECT_TRUE(response.opened_files[0].async());
+}
+
+TEST_F(NetworkServiceClientTest, UploadOneValidFile) {
+ base::FilePath path = temp_dir_.GetPath().AppendASCII("filename");
+ CreateFile(path, kFileContent1);
+ GrantAccess(path, kRendererProcessId);
+
+ UploadResponse response;
+ client_.OnFileUploadRequested(kRendererProcessId, false, {path},
+ std::move(response.callback));
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_EQ(net::OK, response.error_code);
+ ASSERT_EQ(1U, response.opened_files.size());
+ EXPECT_FALSE(response.opened_files[0].async());
+ ValidateFileContents(response.opened_files[0], kFileContent1);
+}
+
+TEST_F(NetworkServiceClientTest, UploadTwoValidFiles) {
+ base::FilePath path1 = temp_dir_.GetPath().AppendASCII("filename1");
+ base::FilePath path2 = temp_dir_.GetPath().AppendASCII("filename2");
+ CreateFile(path1, kFileContent1);
+ CreateFile(path2, kFileContent2);
+ GrantAccess(path1, kRendererProcessId);
+ GrantAccess(path2, kRendererProcessId);
+
+ UploadResponse response;
+ client_.OnFileUploadRequested(kRendererProcessId, false, {path1, path2},
+ std::move(response.callback));
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_EQ(net::OK, response.error_code);
+ ASSERT_EQ(2U, response.opened_files.size());
+ ValidateFileContents(response.opened_files[0], kFileContent1);
+ ValidateFileContents(response.opened_files[1], kFileContent2);
+}
+
+TEST_F(NetworkServiceClientTest, UploadOneUnauthorizedFile) {
+ base::FilePath path = temp_dir_.GetPath().AppendASCII("filename");
+ CreateFile(path, kFileContent1);
+
+ UploadResponse response;
+ client_.OnFileUploadRequested(kRendererProcessId, false, {path},
+ std::move(response.callback));
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_EQ(net::ERR_ACCESS_DENIED, response.error_code);
+ EXPECT_EQ(0U, response.opened_files.size());
+}
+
+TEST_F(NetworkServiceClientTest, UploadOneValidFileAndOneUnauthorized) {
+ base::FilePath path1 = temp_dir_.GetPath().AppendASCII("filename1");
+ base::FilePath path2 = temp_dir_.GetPath().AppendASCII("filename2");
+ CreateFile(path1, kFileContent1);
+ CreateFile(path2, kFileContent2);
+ GrantAccess(path1, kRendererProcessId);
+
+ UploadResponse response;
+ client_.OnFileUploadRequested(kRendererProcessId, false, {path1, path2},
+ std::move(response.callback));
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_EQ(net::ERR_ACCESS_DENIED, response.error_code);
+ EXPECT_EQ(0U, response.opened_files.size());
+}
+
+TEST_F(NetworkServiceClientTest, UploadOneValidFileAndOneNotFound) {
+ base::FilePath path1 = temp_dir_.GetPath().AppendASCII("filename1");
+ base::FilePath path2 = temp_dir_.GetPath().AppendASCII("filename2");
+ CreateFile(path1, kFileContent1);
+ GrantAccess(path1, kRendererProcessId);
+ GrantAccess(path2, kRendererProcessId);
+
+ UploadResponse response;
+ client_.OnFileUploadRequested(kRendererProcessId, false, {path1, path2},
+ std::move(response.callback));
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, response.error_code);
+ EXPECT_EQ(0U, response.opened_files.size());
+}
+
+TEST_F(NetworkServiceClientTest, UploadFromBrowserProcess) {
+ base::FilePath path = temp_dir_.GetPath().AppendASCII("filename");
+ CreateFile(path, kFileContent1);
+ // No grant necessary for browser process.
+
+ UploadResponse response;
+ client_.OnFileUploadRequested(kBrowserProcessId, false, {path},
+ std::move(response.callback));
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_EQ(net::OK, response.error_code);
+ ASSERT_EQ(1U, response.opened_files.size());
+ ValidateFileContents(response.opened_files[0], kFileContent1);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/network_service_instance.cc b/chromium/content/browser/network_service_instance.cc
index c62cf6403bf..374ac6da02d 100644
--- a/chromium/content/browser/network_service_instance.cc
+++ b/chromium/content/browser/network_service_instance.cc
@@ -58,6 +58,9 @@ network::mojom::NetworkService* GetNetworkService() {
delete g_client; // In case we're recreating the network service.
g_client = new NetworkServiceClient(mojo::MakeRequest(&client_ptr));
(*g_network_service_ptr)->SetClient(std::move(client_ptr));
+
+ GetContentClient()->browser()->OnNetworkServiceCreated(
+ g_network_service_ptr->get());
}
return g_network_service_ptr->get();
}
diff --git a/chromium/content/browser/notifications/blink_notification_service_impl.cc b/chromium/content/browser/notifications/blink_notification_service_impl.cc
index 53101e0342c..cbcd2b5369f 100644
--- a/chromium/content/browser/notifications/blink_notification_service_impl.cc
+++ b/chromium/content/browser/notifications/blink_notification_service_impl.cc
@@ -11,15 +11,16 @@
#include "base/strings/string16.h"
#include "content/browser/notifications/notification_event_dispatcher_impl.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/notification_database_data.h"
+#include "content/public/browser/permission_controller.h"
+#include "content/public/browser/permission_type.h"
#include "content/public/browser/platform_notification_service.h"
#include "content/public/common/content_client.h"
#include "content/public/common/notification_resources.h"
#include "content/public/common/platform_notification_data.h"
-#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
namespace content {
@@ -27,32 +28,28 @@ namespace content {
namespace {
// Returns the implementation of the PlatformNotificationService. May be NULL.
-PlatformNotificationService* Service() {
+PlatformNotificationService* GetNotificationService() {
return GetContentClient()->browser()->GetPlatformNotificationService();
}
} // namespace
+using blink::mojom::PersistentNotificationError;
+
BlinkNotificationServiceImpl::BlinkNotificationServiceImpl(
PlatformNotificationContextImpl* notification_context,
BrowserContext* browser_context,
- ResourceContext* resource_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- int render_process_id,
const url::Origin& origin,
mojo::InterfaceRequest<blink::mojom::NotificationService> request)
: notification_context_(notification_context),
browser_context_(browser_context),
- resource_context_(resource_context),
service_worker_context_(std::move(service_worker_context)),
- render_process_id_(render_process_id),
origin_(origin),
- binding_(this, std::move(request)),
- weak_ptr_factory_(this) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ binding_(this, std::move(request)) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(notification_context_);
DCHECK(browser_context_);
- DCHECK(resource_context_);
binding_.set_connection_error_handler(base::BindOnce(
&BlinkNotificationServiceImpl::OnConnectionError,
@@ -60,23 +57,22 @@ BlinkNotificationServiceImpl::BlinkNotificationServiceImpl(
}
BlinkNotificationServiceImpl::~BlinkNotificationServiceImpl() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
void BlinkNotificationServiceImpl::GetPermissionStatus(
GetPermissionStatusCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!Service()) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!GetNotificationService()) {
std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
return;
}
- blink::mojom::PermissionStatus permission_status = CheckPermissionStatus();
-
- std::move(callback).Run(permission_status);
+ std::move(callback).Run(CheckPermissionStatus());
}
void BlinkNotificationServiceImpl::OnConnectionError() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
notification_context_->RemoveService(this);
// |this| has now been deleted.
}
@@ -86,9 +82,10 @@ void BlinkNotificationServiceImpl::DisplayNonPersistentNotification(
const PlatformNotificationData& platform_notification_data,
const NotificationResources& notification_resources,
blink::mojom::NonPersistentNotificationListenerPtr event_listener_ptr) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!Service())
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!GetNotificationService())
return;
+
if (CheckPermissionStatus() != blink::mojom::PermissionStatus::GRANTED)
return;
@@ -96,51 +93,31 @@ void BlinkNotificationServiceImpl::DisplayNonPersistentNotification(
notification_context_->notification_id_generator()
->GenerateForNonPersistentNotification(origin_, token);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&BlinkNotificationServiceImpl::
- DisplayNonPersistentNotificationOnUIThread,
- weak_ptr_factory_.GetWeakPtr(), notification_id,
- origin_.GetURL(), platform_notification_data,
- notification_resources,
- event_listener_ptr.PassInterface()));
-}
-
-void BlinkNotificationServiceImpl::DisplayNonPersistentNotificationOnUIThread(
- const std::string& notification_id,
- const GURL& origin,
- const content::PlatformNotificationData& notification_data,
- const content::NotificationResources& notification_resources,
- blink::mojom::NonPersistentNotificationListenerPtrInfo listener_ptr_info) {
NotificationEventDispatcherImpl* event_dispatcher =
NotificationEventDispatcherImpl::GetInstance();
event_dispatcher->RegisterNonPersistentNotificationListener(
- notification_id, std::move(listener_ptr_info));
+ notification_id, std::move(event_listener_ptr));
- Service()->DisplayNotification(browser_context_, notification_id, origin,
- notification_data, notification_resources);
+ GetNotificationService()->DisplayNotification(
+ browser_context_, notification_id, origin_.GetURL(),
+ platform_notification_data, notification_resources);
}
void BlinkNotificationServiceImpl::CloseNonPersistentNotification(
const std::string& token) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!Service())
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!GetNotificationService())
+ return;
+
+ if (CheckPermissionStatus() != blink::mojom::PermissionStatus::GRANTED)
return;
std::string notification_id =
notification_context_->notification_id_generator()
->GenerateForNonPersistentNotification(origin_, token);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&BlinkNotificationServiceImpl::
- CloseNonPersistentNotificationOnUIThread,
- weak_ptr_factory_.GetWeakPtr(), notification_id));
-}
-
-void BlinkNotificationServiceImpl::CloseNonPersistentNotificationOnUIThread(
- const std::string& notification_id) {
- Service()->CloseNotification(browser_context_, notification_id);
+ GetNotificationService()->CloseNotification(browser_context_,
+ notification_id);
// TODO(https://crbug.com/442141): Pass a callback here to focus the tab
// which created the notification, unless the event is canceled.
@@ -150,8 +127,10 @@ void BlinkNotificationServiceImpl::CloseNonPersistentNotificationOnUIThread(
blink::mojom::PermissionStatus
BlinkNotificationServiceImpl::CheckPermissionStatus() {
- return Service()->CheckPermissionOnIOThread(
- resource_context_, origin_.GetURL(), render_process_id_);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return BrowserContext::GetPermissionController(browser_context_)
+ ->GetPermissionStatus(PermissionType::NOTIFICATIONS, origin_.GetURL(),
+ origin_.GetURL());
}
void BlinkNotificationServiceImpl::DisplayPersistentNotification(
@@ -159,18 +138,39 @@ void BlinkNotificationServiceImpl::DisplayPersistentNotification(
const PlatformNotificationData& platform_notification_data,
const NotificationResources& notification_resources,
DisplayPersistentNotificationCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!Service()) {
- std::move(callback).Run(
- blink::mojom::PersistentNotificationError::INTERNAL_ERROR);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!GetNotificationService()) {
+ std::move(callback).Run(PersistentNotificationError::INTERNAL_ERROR);
return;
}
+
if (CheckPermissionStatus() != blink::mojom::PermissionStatus::GRANTED) {
- std::move(callback).Run(
- blink::mojom::PersistentNotificationError::PERMISSION_DENIED);
+ std::move(callback).Run(PersistentNotificationError::PERMISSION_DENIED);
return;
}
+ int64_t next_persistent_id =
+ GetNotificationService()->ReadNextPersistentNotificationId(
+ browser_context_);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&BlinkNotificationServiceImpl::
+ DisplayPersistentNotificationOnIOThread,
+ weak_factory_for_io_.GetWeakPtr(),
+ service_worker_registration_id, next_persistent_id,
+ platform_notification_data, notification_resources,
+ std::move(callback)));
+}
+
+void BlinkNotificationServiceImpl::DisplayPersistentNotificationOnIOThread(
+ int64_t service_worker_registration_id,
+ int64_t next_persistent_notification_id,
+ const PlatformNotificationData& platform_notification_data,
+ const NotificationResources& notification_resources,
+ DisplayPersistentNotificationCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
// TODO(awdf): Necessary to validate resources here?
NotificationDatabaseData database_data;
@@ -179,100 +179,102 @@ void BlinkNotificationServiceImpl::DisplayPersistentNotification(
database_data.notification_data = platform_notification_data;
notification_context_->WriteNotificationData(
- origin_.GetURL(), database_data,
+ next_persistent_notification_id, origin_.GetURL(), database_data,
base::AdaptCallbackForRepeating(base::BindOnce(
- &BlinkNotificationServiceImpl::DisplayPersistentNotificationWithId,
- weak_ptr_factory_.GetWeakPtr(), service_worker_registration_id,
+ &BlinkNotificationServiceImpl::
+ DisplayPersistentNotificationWithIdOnIOThread,
+ weak_factory_for_io_.GetWeakPtr(), service_worker_registration_id,
platform_notification_data, notification_resources,
std::move(callback))));
}
-void BlinkNotificationServiceImpl::DisplayPersistentNotificationWithId(
- int64_t service_worker_registration_id,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources,
- DisplayPersistentNotificationCallback callback,
- bool success,
- const std::string& notification_id) {
+void BlinkNotificationServiceImpl::
+ DisplayPersistentNotificationWithIdOnIOThread(
+ int64_t service_worker_registration_id,
+ const PlatformNotificationData& platform_notification_data,
+ const NotificationResources& notification_resources,
+ DisplayPersistentNotificationCallback callback,
+ bool success,
+ const std::string& notification_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
if (!success) {
- std::move(callback).Run(
- blink::mojom::PersistentNotificationError::INTERNAL_ERROR);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(callback),
+ PersistentNotificationError::INTERNAL_ERROR));
return;
}
service_worker_context_->FindReadyRegistrationForId(
service_worker_registration_id, origin_.GetURL(),
- base::BindOnce(&BlinkNotificationServiceImpl::
- DisplayPersistentNotificationWithIdForServiceWorker,
- weak_ptr_factory_.GetWeakPtr(), notification_id,
- platform_notification_data, notification_resources,
- std::move(callback)));
+ base::BindOnce(
+ &BlinkNotificationServiceImpl::
+ DisplayPersistentNotificationWithServiceWorkerOnIOThread,
+ weak_factory_for_io_.GetWeakPtr(), notification_id,
+ platform_notification_data, notification_resources,
+ std::move(callback)));
}
void BlinkNotificationServiceImpl::
- DisplayPersistentNotificationWithIdForServiceWorker(
+ DisplayPersistentNotificationWithServiceWorkerOnIOThread(
const std::string& notification_id,
const PlatformNotificationData& platform_notification_data,
const NotificationResources& notification_resources,
DisplayPersistentNotificationCallback callback,
- content::ServiceWorkerStatusCode service_worker_status,
- scoped_refptr<content::ServiceWorkerRegistration> registration) {
+ blink::ServiceWorkerStatusCode service_worker_status,
+ scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (service_worker_status != SERVICE_WORKER_OK) {
- std::move(callback).Run(
- blink::mojom::PersistentNotificationError::INTERNAL_ERROR);
- LOG(ERROR) << "Registration not found for " << origin_.GetURL().spec();
- // TODO(peter): Add UMA to track how often this occurs.
- return;
- }
-
- if (registration->pattern().GetOrigin() != origin_.GetURL()) {
- // Bail out, something's wrong.
- std::move(callback).Run(
- blink::mojom::PersistentNotificationError::INTERNAL_ERROR);
- return;
+ PersistentNotificationError error =
+ PersistentNotificationError::INTERNAL_ERROR;
+
+ // Display the notification if the Service Worker's origin matches the origin
+ // of the notification's sender.
+ if (service_worker_status == blink::ServiceWorkerStatusCode::kOk &&
+ registration->pattern().GetOrigin() == origin_.GetURL()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &PlatformNotificationService::DisplayPersistentNotification,
+ base::Unretained(GetNotificationService()), browser_context_,
+ notification_id, registration->pattern(), origin_.GetURL(),
+ platform_notification_data, notification_resources));
+
+ error = PersistentNotificationError::NONE;
}
- // Using base::Unretained here is safe because Service() returns a singleton.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(
- &PlatformNotificationService::DisplayPersistentNotification,
- base::Unretained(Service()), browser_context_, notification_id,
- registration->pattern(), origin_.GetURL(), platform_notification_data,
- notification_resources));
-
- std::move(callback).Run(blink::mojom::PersistentNotificationError::NONE);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(callback), error));
}
void BlinkNotificationServiceImpl::ClosePersistentNotification(
const std::string& notification_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!GetNotificationService())
+ return;
if (CheckPermissionStatus() != blink::mojom::PermissionStatus::GRANTED)
return;
- // Using base::Unretained here is safe because Service() returns a singleton.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&PlatformNotificationService::ClosePersistentNotification,
- base::Unretained(Service()), browser_context_,
- notification_id));
+ GetNotificationService()->ClosePersistentNotification(browser_context_,
+ notification_id);
- notification_context_->DeleteNotificationData(
- notification_id, origin_.GetURL(), base::DoNothing());
+ // Deleting the data associated with |notification_id| from the notification
+ // database has to be done on the IO thread, but there's no reason to postpone
+ // removing the notification from the user's display until that's done.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PlatformNotificationContextImpl::DeleteNotificationData,
+ notification_context_, notification_id, origin_.GetURL(),
+ base::DoNothing()));
}
void BlinkNotificationServiceImpl::GetNotifications(
int64_t service_worker_registration_id,
const std::string& filter_tag,
GetNotificationsCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (CheckPermissionStatus() != blink::mojom::PermissionStatus::GRANTED) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!GetNotificationService() ||
+ CheckPermissionStatus() != blink::mojom::PermissionStatus::GRANTED) {
// No permission has been granted for the given origin. It is harmless to
// try to get notifications without permission, so return empty vectors
// indicating that no (accessible) notifications exist at this time.
@@ -281,18 +283,27 @@ void BlinkNotificationServiceImpl::GetNotifications(
return;
}
- notification_context_->ReadAllNotificationDataForServiceWorkerRegistration(
- origin_.GetURL(), service_worker_registration_id,
- base::AdaptCallbackForRepeating(base::BindOnce(
- &BlinkNotificationServiceImpl::DidGetNotifications,
- weak_ptr_factory_.GetWeakPtr(), filter_tag, std::move(callback))));
+ auto read_notification_data_callback = base::BindOnce(
+ &BlinkNotificationServiceImpl::DidGetNotificationsOnIOThread,
+ weak_factory_for_io_.GetWeakPtr(), filter_tag, std::move(callback));
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PlatformNotificationContextImpl::
+ ReadAllNotificationDataForServiceWorkerRegistration,
+ notification_context_, origin_.GetURL(),
+ service_worker_registration_id,
+ base::AdaptCallbackForRepeating(
+ std::move(read_notification_data_callback))));
}
-void BlinkNotificationServiceImpl::DidGetNotifications(
+void BlinkNotificationServiceImpl::DidGetNotificationsOnIOThread(
const std::string& filter_tag,
GetNotificationsCallback callback,
bool success,
const std::vector<NotificationDatabaseData>& notifications) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
std::vector<std::string> ids;
std::vector<PlatformNotificationData> datas;
@@ -305,7 +316,10 @@ void BlinkNotificationServiceImpl::DidGetNotifications(
}
}
- std::move(callback).Run(ids, datas);
+ // Make sure to invoke the |callback| on the UI thread again.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(callback), std::move(ids), std::move(datas)));
}
} // namespace content
diff --git a/chromium/content/browser/notifications/blink_notification_service_impl.h b/chromium/content/browser/notifications/blink_notification_service_impl.h
index 1ddd97d69ef..193f5d241c3 100644
--- a/chromium/content/browser/notifications/blink_notification_service_impl.h
+++ b/chromium/content/browser/notifications/blink_notification_service_impl.h
@@ -13,6 +13,7 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "third_party/blink/public/platform/modules/notifications/notification_service.mojom.h"
+#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
#include "url/origin.h"
namespace content {
@@ -20,20 +21,18 @@ namespace content {
struct NotificationDatabaseData;
class PlatformNotificationContextImpl;
struct PlatformNotificationData;
-class ResourceContext;
// Implementation of the NotificationService used for Web Notifications. Is
// responsible for displaying, updating and reading of both non-persistent
-// and persistent notifications. Lives on the IO thread.
+// and persistent notifications. Primarily lives on the UI thread, but jumps to
+// the IO thread when needing to interact with the PlatformNotificationContext.
class CONTENT_EXPORT BlinkNotificationServiceImpl
: public blink::mojom::NotificationService {
public:
BlinkNotificationServiceImpl(
PlatformNotificationContextImpl* notification_context,
BrowserContext* browser_context,
- ResourceContext* resource_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- int render_process_id,
const url::Origin& origin,
mojo::InterfaceRequest<blink::mojom::NotificationService> request);
~BlinkNotificationServiceImpl() override;
@@ -60,14 +59,17 @@ class CONTENT_EXPORT BlinkNotificationServiceImpl
// Called when an error is detected on binding_.
void OnConnectionError();
- void DisplayNonPersistentNotificationOnUIThread(
- const std::string& notification_id,
- const GURL& origin,
- const content::PlatformNotificationData& notification_data,
- const content::NotificationResources& notification_resources,
- blink::mojom::NonPersistentNotificationListenerPtrInfo listener_ptr_info);
+ // Check the permission status for the current |origin_|.
+ blink::mojom::PermissionStatus CheckPermissionStatus();
+
+ void DisplayPersistentNotificationOnIOThread(
+ int64_t service_worker_registration_id,
+ int64_t persistent_notification_id,
+ const PlatformNotificationData& platform_notification_data,
+ const NotificationResources& notification_resources,
+ DisplayPersistentNotificationCallback callback);
- void DisplayPersistentNotificationWithId(
+ void DisplayPersistentNotificationWithIdOnIOThread(
int64_t service_worker_registration_id,
const PlatformNotificationData& platform_notification_data,
const NotificationResources& notification_resources,
@@ -75,20 +77,15 @@ class CONTENT_EXPORT BlinkNotificationServiceImpl
bool success,
const std::string& notification_id);
- void DisplayPersistentNotificationWithIdForServiceWorker(
+ void DisplayPersistentNotificationWithServiceWorkerOnIOThread(
const std::string& notification_id,
const PlatformNotificationData& platform_notification_data,
const NotificationResources& notification_resources,
DisplayPersistentNotificationCallback callback,
- content::ServiceWorkerStatusCode service_worker_status,
- scoped_refptr<content::ServiceWorkerRegistration> registration);
+ blink::ServiceWorkerStatusCode service_worker_status,
+ scoped_refptr<ServiceWorkerRegistration> registration);
- void CloseNonPersistentNotificationOnUIThread(
- const std::string& notification_id);
-
- blink::mojom::PermissionStatus CheckPermissionStatus();
-
- void DidGetNotifications(
+ void DidGetNotificationsOnIOThread(
const std::string& filter_tag,
GetNotificationsCallback callback,
bool success,
@@ -99,18 +96,15 @@ class CONTENT_EXPORT BlinkNotificationServiceImpl
BrowserContext* browser_context_;
- ResourceContext* resource_context_;
-
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
- int render_process_id_;
-
// The origin that this notification service is communicating with.
url::Origin origin_;
mojo::Binding<blink::mojom::NotificationService> binding_;
- base::WeakPtrFactory<BlinkNotificationServiceImpl> weak_ptr_factory_;
+ base::WeakPtrFactory<BlinkNotificationServiceImpl> weak_factory_for_io_{this};
+ base::WeakPtrFactory<BlinkNotificationServiceImpl> weak_factory_for_ui_{this};
DISALLOW_COPY_AND_ASSIGN(BlinkNotificationServiceImpl);
};
diff --git a/chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc b/chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc
index 26622dee5f7..618c7bd88cd 100644
--- a/chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc
+++ b/chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc
@@ -18,7 +18,8 @@
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/test/mock_resource_context.h"
+#include "content/public/browser/permission_type.h"
+#include "content/public/test/mock_permission_manager.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
@@ -26,16 +27,18 @@
#include "content/test/test_content_browser_client.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_request.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/notifications/notification_service.mojom.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
+using ::testing::Return;
+using ::testing::_;
+
namespace content {
namespace {
-const int kFakeRenderProcessId = 1;
-
const char kTestOrigin[] = "https://example.com";
const char kTestServiceWorkerUrl[] = "https://example.com/sw.js";
@@ -53,7 +56,9 @@ class MockNonPersistentNotificationListener
// NonPersistentNotificationListener interface.
void OnShow() override {}
- void OnClick() override {}
+ void OnClick(OnClickCallback completed_closure) override {
+ std::move(completed_closure).Run();
+ }
void OnClose(OnCloseCallback completed_closure) override {
std::move(completed_closure).Run();
}
@@ -107,10 +112,14 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
blink::mojom::NotificationServicePtr notification_service_ptr;
notification_service_ = std::make_unique<BlinkNotificationServiceImpl>(
- notification_context_.get(), &browser_context_, &resource_context_,
- embedded_worker_helper_->context_wrapper(), kFakeRenderProcessId,
+ notification_context_.get(), &browser_context_,
+ embedded_worker_helper_->context_wrapper(),
url::Origin::Create(GURL(kTestOrigin)),
mojo::MakeRequest(&notification_service_ptr));
+
+ // Provide a mock permission manager to the |browser_context_|.
+ browser_context_.SetPermissionControllerDelegate(
+ std::make_unique<testing::NiceMock<MockPermissionManager>>());
}
void TearDown() override {
@@ -132,10 +141,10 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
base::RunLoop run_loop;
embedded_worker_helper_->context()->RegisterServiceWorker(
GURL(kTestServiceWorkerUrl), options,
- base::AdaptCallbackForRepeating(base::BindOnce(
+ base::BindOnce(
&BlinkNotificationServiceImplTest::DidRegisterServiceWorker,
base::Unretained(this), &service_worker_registration_id,
- run_loop.QuitClosure())));
+ run_loop.QuitClosure()));
run_loop.Run();
}
@@ -166,11 +175,12 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
void DidRegisterServiceWorker(int64_t* out_service_worker_registration_id,
base::OnceClosure quit_closure,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t service_worker_registration_id) {
DCHECK(out_service_worker_registration_id);
- EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
*out_service_worker_registration_id = service_worker_registration_id;
@@ -180,10 +190,11 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
void DidFindServiceWorkerRegistration(
scoped_refptr<ServiceWorkerRegistration>* out_service_worker_registration,
base::OnceClosure quit_closure,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
DCHECK(out_service_worker_registration);
- EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
*out_service_worker_registration = service_worker_registration;
@@ -191,8 +202,10 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
}
void DidGetPermissionStatus(
+ base::OnceClosure quit_closure,
blink::mojom::PermissionStatus permission_status) {
permission_callback_result_ = permission_status;
+ std::move(quit_closure).Run();
}
blink::mojom::PermissionStatus GetPermissionCallbackResult() {
@@ -272,8 +285,9 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
// PlatformNotificationContext::ReadNotificationData
bool ReadNotificationData(const std::string& notification_id) {
base::RunLoop run_loop;
- notification_context_->ReadNotificationData(
+ notification_context_->ReadNotificationDataAndRecordInteraction(
notification_id, GURL(kTestOrigin),
+ PlatformNotificationContext::Interaction::NONE,
base::AdaptCallbackForRepeating(base::BindOnce(
&BlinkNotificationServiceImplTest::DidReadNotificationData,
base::Unretained(this), run_loop.QuitClosure())));
@@ -281,6 +295,18 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
return read_notification_data_callback_result_;
}
+ // Updates the permission status for the |kTestOrigin| to the given
+ // |permission_status| through the PermissionManager.
+ void SetPermissionStatus(blink::mojom::PermissionStatus permission_status) {
+ MockPermissionManager* mock_permission_manager =
+ static_cast<MockPermissionManager*>(
+ browser_context_.GetPermissionControllerDelegate());
+
+ ON_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::NOTIFICATIONS, _, _))
+ .WillByDefault(Return(permission_status));
+ }
+
protected:
TestBrowserThreadBundle thread_bundle_; // Must be first member.
@@ -310,41 +336,52 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
bool read_notification_data_callback_result_ = false;
- MockResourceContext resource_context_;
-
DISALLOW_COPY_AND_ASSIGN(BlinkNotificationServiceImplTest);
};
TEST_F(BlinkNotificationServiceImplTest, GetPermissionStatus) {
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::GRANTED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
- notification_service_->GetPermissionStatus(
- base::BindOnce(&BlinkNotificationServiceImplTest::DidGetPermissionStatus,
- base::Unretained(this)));
+ {
+ base::RunLoop run_loop;
+ notification_service_->GetPermissionStatus(base::BindOnce(
+ &BlinkNotificationServiceImplTest::DidGetPermissionStatus,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+ }
EXPECT_EQ(blink::mojom::PermissionStatus::GRANTED,
GetPermissionCallbackResult());
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::DENIED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::DENIED);
- notification_service_->GetPermissionStatus(
- base::BindOnce(&BlinkNotificationServiceImplTest::DidGetPermissionStatus,
- base::Unretained(this)));
+ {
+ base::RunLoop run_loop;
+ notification_service_->GetPermissionStatus(base::BindOnce(
+ &BlinkNotificationServiceImplTest::DidGetPermissionStatus,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+ }
EXPECT_EQ(blink::mojom::PermissionStatus::DENIED,
GetPermissionCallbackResult());
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::ASK);
- notification_service_->GetPermissionStatus(
- base::BindOnce(&BlinkNotificationServiceImplTest::DidGetPermissionStatus,
- base::Unretained(this)));
+ SetPermissionStatus(blink::mojom::PermissionStatus::ASK);
+
+ {
+ base::RunLoop run_loop;
+ notification_service_->GetPermissionStatus(base::BindOnce(
+ &BlinkNotificationServiceImplTest::DidGetPermissionStatus,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+ }
EXPECT_EQ(blink::mojom::PermissionStatus::ASK, GetPermissionCallbackResult());
}
TEST_F(BlinkNotificationServiceImplTest,
DisplayNonPersistentNotificationWithPermission) {
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::GRANTED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
notification_service_->DisplayNonPersistentNotification(
"token", PlatformNotificationData(), NotificationResources(),
@@ -361,7 +398,7 @@ TEST_F(BlinkNotificationServiceImplTest,
TEST_F(BlinkNotificationServiceImplTest,
DisplayNonPersistentNotificationWithoutPermission) {
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::DENIED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::DENIED);
notification_service_->DisplayNonPersistentNotification(
"token", PlatformNotificationData(), NotificationResources(),
@@ -378,7 +415,7 @@ TEST_F(BlinkNotificationServiceImplTest,
TEST_F(BlinkNotificationServiceImplTest,
DisplayPersistentNotificationWithPermission) {
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::GRANTED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
@@ -396,7 +433,7 @@ TEST_F(BlinkNotificationServiceImplTest,
}
TEST_F(BlinkNotificationServiceImplTest, CloseDisplayedPersistentNotification) {
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::GRANTED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
@@ -423,7 +460,7 @@ TEST_F(BlinkNotificationServiceImplTest, CloseDisplayedPersistentNotification) {
TEST_F(BlinkNotificationServiceImplTest,
ClosePersistentNotificationDeletesFromDatabase) {
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::GRANTED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
@@ -456,7 +493,7 @@ TEST_F(BlinkNotificationServiceImplTest,
TEST_F(BlinkNotificationServiceImplTest,
DisplayPersistentNotificationWithoutPermission) {
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::DENIED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::DENIED);
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
@@ -475,7 +512,7 @@ TEST_F(BlinkNotificationServiceImplTest,
TEST_F(BlinkNotificationServiceImplTest,
DisplayMultiplePersistentNotifications) {
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::GRANTED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
@@ -493,7 +530,7 @@ TEST_F(BlinkNotificationServiceImplTest,
}
TEST_F(BlinkNotificationServiceImplTest, GetNotifications) {
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::GRANTED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
@@ -512,7 +549,7 @@ TEST_F(BlinkNotificationServiceImplTest, GetNotifications) {
}
TEST_F(BlinkNotificationServiceImplTest, GetNotificationsWithoutPermission) {
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::GRANTED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
@@ -523,14 +560,14 @@ TEST_F(BlinkNotificationServiceImplTest, GetNotificationsWithoutPermission) {
// Wait for service to receive all the Display calls.
RunAllTasksUntilIdle();
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::DENIED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::DENIED);
EXPECT_EQ(
0u, GetNotificationsSync(registration->id(), "" /* filter_tag */).size());
}
TEST_F(BlinkNotificationServiceImplTest, GetNotificationsWithFilter) {
- mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::GRANTED);
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
diff --git a/chromium/content/browser/notifications/notification_database.cc b/chromium/content/browser/notifications/notification_database.cc
index 87dca497209..28ff2f47881 100644
--- a/chromium/content/browser/notifications/notification_database.cc
+++ b/chromium/content/browser/notifications/notification_database.cc
@@ -7,6 +7,7 @@
#include <string>
#include "base/files/file_util.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "content/browser/notifications/notification_database_data_conversions.h"
@@ -37,15 +38,11 @@ namespace content {
namespace {
// Keys of the fields defined in the database.
-const char kNextNotificationIdKey[] = "NEXT_NOTIFICATION_ID";
const char kDataKeyPrefix[] = "DATA:";
// Separates the components of compound keys.
const char kNotificationKeySeparator = '\x00';
-// The first notification id which to be handed out by the database.
-const int64_t kFirstPersistentNotificationId = 1;
-
// Converts the LevelDB |status| to one of the notification database's values.
NotificationDatabase::Status LevelDBStatusToNotificationDatabaseStatus(
const leveldb::Status& status) {
@@ -99,6 +96,15 @@ NotificationDatabase::Status DeserializedNotificationData(
return NotificationDatabase::STATUS_ERROR_CORRUPTED;
}
+// Updates the time of the last click on the notification, and the first if
+// necessary.
+void UpdateNotificationClickTimestamps(NotificationDatabaseData* data) {
+ base::TimeDelta delta = base::Time::Now() - data->creation_time_millis;
+ if (!data->time_until_first_click_millis.has_value())
+ data->time_until_first_click_millis = delta;
+ data->time_until_last_click_millis = delta;
+}
+
} // namespace
NotificationDatabase::NotificationDatabase(const base::FilePath& path)
@@ -111,7 +117,7 @@ NotificationDatabase::~NotificationDatabase() {
NotificationDatabase::Status NotificationDatabase::Open(
bool create_if_missing) {
DCHECK(sequence_checker_.CalledOnValidSequence());
- DCHECK_EQ(STATE_UNINITIALIZED, state_);
+ DCHECK_EQ(State::UNINITIALIZED, state_);
if (!create_if_missing) {
if (IsInMemoryDatabase() || !base::PathExists(path_) ||
@@ -134,16 +140,10 @@ NotificationDatabase::Status NotificationDatabase::Open(
Status status = LevelDBStatusToNotificationDatabaseStatus(
leveldb_env::OpenDB(options, path_.AsUTF8Unsafe(), &db_));
- if (status != STATUS_OK)
- return status;
-
- state_ = STATE_INITIALIZED;
+ if (status == STATUS_OK)
+ state_ = State::INITIALIZED;
- return ReadNextPersistentNotificationId();
-}
-
-int64_t NotificationDatabase::GetNextPersistentNotificationId() {
- return next_persistent_notification_id_++;
+ return status;
}
NotificationDatabase::Status NotificationDatabase::ReadNotificationData(
@@ -151,7 +151,7 @@ NotificationDatabase::Status NotificationDatabase::ReadNotificationData(
const GURL& origin,
NotificationDatabaseData* notification_database_data) const {
DCHECK(sequence_checker_.CalledOnValidSequence());
- DCHECK_EQ(STATE_INITIALIZED, state_);
+ DCHECK_EQ(State::INITIALIZED, state_);
DCHECK(!notification_id.empty());
DCHECK(origin.is_valid());
DCHECK(notification_database_data);
@@ -168,6 +168,43 @@ NotificationDatabase::Status NotificationDatabase::ReadNotificationData(
notification_database_data);
}
+NotificationDatabase::Status
+NotificationDatabase::ReadNotificationDataAndRecordInteraction(
+ const std::string& notification_id,
+ const GURL& origin,
+ PlatformNotificationContext::Interaction interaction,
+ NotificationDatabaseData* notification_database_data) {
+ Status status =
+ ReadNotificationData(notification_id, origin, notification_database_data);
+ if (status != STATUS_OK)
+ return status;
+
+ // Update the appropriate fields for UKM logging purposes.
+ switch (interaction) {
+ case PlatformNotificationContext::Interaction::CLOSED:
+ notification_database_data->time_until_close_millis =
+ base::Time::Now() - notification_database_data->creation_time_millis;
+ break;
+ case PlatformNotificationContext::Interaction::NONE:
+ return status;
+ case PlatformNotificationContext::Interaction::ACTION_BUTTON_CLICKED:
+ notification_database_data->num_action_button_clicks += 1;
+ UpdateNotificationClickTimestamps(notification_database_data);
+ break;
+ case PlatformNotificationContext::Interaction::CLICKED:
+ notification_database_data->num_clicks += 1;
+ UpdateNotificationClickTimestamps(notification_database_data);
+ break;
+ }
+
+ // Write the changed values to the database.
+ status = WriteNotificationData(origin, *notification_database_data);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Notifications.Database.ReadResultRecordInteraction", status,
+ NotificationDatabase::STATUS_COUNT);
+ return status;
+}
+
NotificationDatabase::Status NotificationDatabase::ReadAllNotificationData(
std::vector<NotificationDatabaseData>* notification_data_vector) const {
return ReadAllNotificationDataInternal(
@@ -197,7 +234,7 @@ NotificationDatabase::Status NotificationDatabase::WriteNotificationData(
const GURL& origin,
const NotificationDatabaseData& notification_data) {
DCHECK(sequence_checker_.CalledOnValidSequence());
- DCHECK_EQ(STATE_INITIALIZED, state_);
+ DCHECK_EQ(State::INITIALIZED, state_);
DCHECK(origin.is_valid());
const std::string& notification_id = notification_data.notification_id;
@@ -213,12 +250,6 @@ NotificationDatabase::Status NotificationDatabase::WriteNotificationData(
leveldb::WriteBatch batch;
batch.Put(CreateDataKey(origin, notification_id), serialized_data);
- if (written_persistent_notification_id_ != next_persistent_notification_id_) {
- written_persistent_notification_id_ = next_persistent_notification_id_;
- batch.Put(kNextNotificationIdKey,
- base::Int64ToString(next_persistent_notification_id_));
- }
-
return LevelDBStatusToNotificationDatabaseStatus(
db_->Write(leveldb::WriteOptions(), &batch));
}
@@ -227,7 +258,7 @@ NotificationDatabase::Status NotificationDatabase::DeleteNotificationData(
const std::string& notification_id,
const GURL& origin) {
DCHECK(sequence_checker_.CalledOnValidSequence());
- DCHECK_EQ(STATE_INITIALIZED, state_);
+ DCHECK_EQ(State::INITIALIZED, state_);
DCHECK(!notification_id.empty());
DCHECK(origin.is_valid());
@@ -267,7 +298,7 @@ NotificationDatabase::Status NotificationDatabase::Destroy() {
options.env = env_.get();
}
- state_ = STATE_DISABLED;
+ state_ = State::DISABLED;
db_.reset();
return LevelDBStatusToNotificationDatabaseStatus(
@@ -275,31 +306,6 @@ NotificationDatabase::Status NotificationDatabase::Destroy() {
}
NotificationDatabase::Status
-NotificationDatabase::ReadNextPersistentNotificationId() {
- std::string value;
- Status status = LevelDBStatusToNotificationDatabaseStatus(
- db_->Get(leveldb::ReadOptions(), kNextNotificationIdKey, &value));
-
- if (status == STATUS_ERROR_NOT_FOUND) {
- next_persistent_notification_id_ = kFirstPersistentNotificationId;
- written_persistent_notification_id_ = kFirstPersistentNotificationId;
- return STATUS_OK;
- }
-
- if (status != STATUS_OK)
- return status;
-
- if (!base::StringToInt64(value, &next_persistent_notification_id_) ||
- next_persistent_notification_id_ < kFirstPersistentNotificationId) {
- return STATUS_ERROR_CORRUPTED;
- }
-
- written_persistent_notification_id_ = next_persistent_notification_id_;
-
- return STATUS_OK;
-}
-
-NotificationDatabase::Status
NotificationDatabase::ReadAllNotificationDataInternal(
const GURL& origin,
int64_t service_worker_registration_id,
@@ -377,11 +383,7 @@ NotificationDatabase::DeleteAllNotificationDataInternal(
batch.Delete(iter->key());
- // Silently remove the notification if it doesn't have an ID assigned.
- // TODO(peter): Remove this clause when Chrome 55 has branched.
- if (notification_database_data.notification_id.empty())
- continue;
-
+ DCHECK(!notification_database_data.notification_id.empty());
deleted_notification_ids->insert(
notification_database_data.notification_id);
}
diff --git a/chromium/content/browser/notifications/notification_database.h b/chromium/content/browser/notifications/notification_database.h
index e85594f0ee6..5237a8e323c 100644
--- a/chromium/content/browser/notifications/notification_database.h
+++ b/chromium/content/browser/notifications/notification_database.h
@@ -14,6 +14,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/sequence_checker.h"
+#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/common/content_export.h"
class GURL;
@@ -90,6 +91,15 @@ class CONTENT_EXPORT NotificationDatabase {
const GURL& origin,
NotificationDatabaseData* notification_data) const;
+ // This function is identical to ReadNotificationData above, but also records
+ // an interaction with that notification in the database for UKM logging
+ // purposes.
+ Status ReadNotificationDataAndRecordInteraction(
+ const std::string& notification_id,
+ const GURL& origin,
+ PlatformNotificationContext::Interaction interaction,
+ NotificationDatabaseData* notification_data);
+
// Reads all notification data for all origins from the database, and appends
// the data to |notification_data_vector|. Returns the status code.
Status ReadAllNotificationData(
@@ -147,12 +157,10 @@ class CONTENT_EXPORT NotificationDatabase {
private:
friend class NotificationDatabaseTest;
- // TODO(peter): Convert to an enum class when DCHECK_EQ supports this.
- // See https://crbug.com/463869.
- enum State {
- STATE_UNINITIALIZED,
- STATE_INITIALIZED,
- STATE_DISABLED,
+ enum class State {
+ UNINITIALIZED,
+ INITIALIZED,
+ DISABLED,
};
// Reads the next available persistent notification id from the database and
@@ -193,9 +201,6 @@ class CONTENT_EXPORT NotificationDatabase {
base::FilePath path_;
- int64_t next_persistent_notification_id_ = 0;
- int64_t written_persistent_notification_id_ = 0;
-
std::unique_ptr<const leveldb::FilterPolicy> filter_policy_;
// The declaration order for these members matters, as |db_| depends on |env_|
@@ -203,7 +208,7 @@ class CONTENT_EXPORT NotificationDatabase {
std::unique_ptr<leveldb::Env> env_;
std::unique_ptr<leveldb::DB> db_;
- State state_ = STATE_UNINITIALIZED;
+ State state_ = State::UNINITIALIZED;
base::SequenceChecker sequence_checker_;
diff --git a/chromium/content/browser/notifications/notification_database_data_conversions.cc b/chromium/content/browser/notifications/notification_database_data_conversions.cc
index 557692ae53e..656108caa62 100644
--- a/chromium/content/browser/notifications/notification_database_data_conversions.cc
+++ b/chromium/content/browser/notifications/notification_database_data_conversions.cc
@@ -83,6 +83,8 @@ bool DeserializeNotificationDatabaseData(const std::string& input,
if (payload.vibration_pattern().size() > 0) {
notification_data->vibration_pattern.assign(
payload.vibration_pattern().begin(), payload.vibration_pattern().end());
+ } else {
+ notification_data->vibration_pattern.clear();
}
notification_data->timestamp =
@@ -94,8 +96,12 @@ bool DeserializeNotificationDatabaseData(const std::string& input,
if (payload.data().length()) {
notification_data->data.assign(payload.data().begin(),
payload.data().end());
+ } else {
+ notification_data->data.clear();
}
+ notification_data->actions.clear();
+
for (const auto& payload_action : payload.actions()) {
PlatformNotificationAction action;
@@ -208,12 +214,18 @@ bool SerializeNotificationDatabaseData(const NotificationDatabaseData& input,
message.set_num_action_button_clicks(input.num_action_button_clicks);
message.set_creation_time_millis(
input.creation_time_millis.ToDeltaSinceWindowsEpoch().InMicroseconds());
- message.set_time_until_first_click_millis(
- input.time_until_first_click_millis.InMilliseconds());
- message.set_time_until_last_click_millis(
- input.time_until_last_click_millis.InMilliseconds());
- message.set_time_until_close_millis(
- input.time_until_close_millis.InMilliseconds());
+ if (input.time_until_first_click_millis.has_value()) {
+ message.set_time_until_first_click_millis(
+ input.time_until_first_click_millis.value().InMilliseconds());
+ }
+ if (input.time_until_last_click_millis.has_value()) {
+ message.set_time_until_last_click_millis(
+ input.time_until_last_click_millis.value().InMilliseconds());
+ }
+ if (input.time_until_close_millis.has_value()) {
+ message.set_time_until_close_millis(
+ input.time_until_close_millis.value().InMilliseconds());
+ }
switch (input.closed_reason) {
case NotificationDatabaseData::ClosedReason::USER:
diff --git a/chromium/content/browser/notifications/notification_database_data_unittest.cc b/chromium/content/browser/notifications/notification_database_data_unittest.cc
index 6436f409c4e..9de61d52c50 100644
--- a/chromium/content/browser/notifications/notification_database_data_unittest.cc
+++ b/chromium/content/browser/notifications/notification_database_data_unittest.cc
@@ -170,6 +170,34 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) {
}
}
+TEST(NotificationDatabaseDataTest, ActionDeserializationIsNotAdditive) {
+ NotificationDatabaseData database_data;
+
+ for (size_t i = 0; i < blink::kWebNotificationMaxActions; ++i)
+ database_data.notification_data.actions.emplace_back();
+
+ std::string serialized_data;
+ NotificationDatabaseData copied_database_data;
+
+ // Serialize the data in |notification_data| to the string |serialized_data|,
+ // and then deserialize it again immediately to |copied_database_data|.
+ ASSERT_TRUE(
+ SerializeNotificationDatabaseData(database_data, &serialized_data));
+ ASSERT_TRUE(DeserializeNotificationDatabaseData(serialized_data,
+ &copied_database_data));
+
+ EXPECT_EQ(copied_database_data.notification_data.actions.size(),
+ blink::kWebNotificationMaxActions);
+
+ // Deserialize it again in the same |copied_database_data|. The number of
+ // actions in the structure should not be affected.
+ ASSERT_TRUE(DeserializeNotificationDatabaseData(serialized_data,
+ &copied_database_data));
+
+ EXPECT_EQ(copied_database_data.notification_data.actions.size(),
+ blink::kWebNotificationMaxActions);
+}
+
TEST(NotificationDatabaseDataTest, SerializeAndDeserializeActionTypes) {
PlatformNotificationActionType action_types[] = {
PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON,
@@ -222,7 +250,7 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeDirections) {
}
}
-TEST(NotificationDatabaseDataTest, SerializeAndDeserializeclosed_reasons) {
+TEST(NotificationDatabaseDataTest, SerializeAndDeserializeClosedReasons) {
NotificationDatabaseData::ClosedReason closed_reasons[] = {
NotificationDatabaseData::ClosedReason::USER,
NotificationDatabaseData::ClosedReason::DEVELOPER,
diff --git a/chromium/content/browser/notifications/notification_database_unittest.cc b/chromium/content/browser/notifications/notification_database_unittest.cc
index b1eca237f6c..f6fdef1f358 100644
--- a/chromium/content/browser/notifications/notification_database_unittest.cc
+++ b/chromium/content/browser/notifications/notification_database_unittest.cc
@@ -188,10 +188,6 @@ TEST_F(NotificationDatabaseTest, NotificationIdIncrements) {
ASSERT_EQ(NotificationDatabase::STATUS_OK,
database->Open(true /* create_if_missing */));
- EXPECT_EQ(database->GetNextPersistentNotificationId(), 1);
- EXPECT_EQ(database->GetNextPersistentNotificationId(), 2);
- EXPECT_EQ(database->GetNextPersistentNotificationId(), 3);
-
GURL origin("https://example.com");
std::string notification_id;
@@ -202,10 +198,6 @@ TEST_F(NotificationDatabaseTest, NotificationIdIncrements) {
database.reset(CreateDatabaseOnFileSystem(database_dir.GetPath()));
ASSERT_EQ(NotificationDatabase::STATUS_OK,
database->Open(false /* create_if_missing */));
-
- // Verify that the next persistent notification id was stored in the database,
- // and continues where we expect it to be, even after closing and opening it.
- EXPECT_EQ(database->GetNextPersistentNotificationId(), 4);
}
TEST_F(NotificationDatabaseTest, NotificationIdIncrementsStorage) {
@@ -228,35 +220,6 @@ TEST_F(NotificationDatabaseTest, NotificationIdIncrementsStorage) {
EXPECT_EQ(database_data.notification_id, read_database_data.notification_id);
}
-TEST_F(NotificationDatabaseTest, NotificationIdCorruption) {
- base::ScopedTempDir database_dir;
- ASSERT_TRUE(database_dir.CreateUniqueTempDir());
-
- std::unique_ptr<NotificationDatabase> database(
- CreateDatabaseOnFileSystem(database_dir.GetPath()));
-
- ASSERT_EQ(NotificationDatabase::STATUS_OK,
- database->Open(true /* create_if_missing */));
-
- GURL origin("https://example.com");
-
- NotificationDatabaseData database_data;
- database_data.notification_id = GenerateNotificationId();
-
- ASSERT_EQ(NotificationDatabase::STATUS_OK,
- database->WriteNotificationData(origin, database_data));
-
- // Deliberately write an invalid value as the next notification id. When
- // re-opening the database, the Open() method should realize that an invalid
- // value is being read, and mark the database as corrupted.
- ASSERT_NO_FATAL_FAILURE(
- WriteLevelDBKeyValuePair(database.get(), "NEXT_NOTIFICATION_ID", "-42"));
-
- database.reset(CreateDatabaseOnFileSystem(database_dir.GetPath()));
- EXPECT_EQ(NotificationDatabase::STATUS_ERROR_CORRUPTED,
- database->Open(false /* create_if_missing */));
-}
-
TEST_F(NotificationDatabaseTest, ReadInvalidNotificationData) {
std::unique_ptr<NotificationDatabase> database(CreateDatabaseInMemory());
ASSERT_EQ(NotificationDatabase::STATUS_OK,
@@ -394,6 +357,63 @@ TEST_F(NotificationDatabaseTest, ReadWriteMultipleNotificationData) {
}
}
+TEST_F(NotificationDatabaseTest, ReadNotificationUpdateInteraction) {
+ std::unique_ptr<NotificationDatabase> database(CreateDatabaseInMemory());
+ ASSERT_EQ(NotificationDatabase::STATUS_OK,
+ database->Open(true /* create_if_missing */));
+
+ GURL origin("https://example.com");
+
+ NotificationDatabaseData database_data, read_database_data;
+ database_data.notification_id = GenerateNotificationId();
+ database_data.notification_data.title = base::UTF8ToUTF16("My Notification");
+
+ ASSERT_EQ(NotificationDatabase::STATUS_OK,
+ database->WriteNotificationData(origin, database_data));
+
+ // Check that the time deltas have not yet been set.
+ EXPECT_EQ(false,
+ read_database_data.time_until_first_click_millis.has_value());
+ EXPECT_EQ(false, read_database_data.time_until_last_click_millis.has_value());
+ EXPECT_EQ(false, read_database_data.time_until_close_millis.has_value());
+
+ // Check that when a notification has an interaction, the appropriate field is
+ // updated on the read.
+ ASSERT_EQ(NotificationDatabase::STATUS_OK,
+ database->ReadNotificationDataAndRecordInteraction(
+ database_data.notification_id, origin,
+ PlatformNotificationContext::Interaction::CLICKED,
+ &read_database_data));
+ EXPECT_EQ(1, read_database_data.num_clicks);
+
+ ASSERT_EQ(NotificationDatabase::STATUS_OK,
+ database->ReadNotificationDataAndRecordInteraction(
+ database_data.notification_id, origin,
+ PlatformNotificationContext::Interaction::ACTION_BUTTON_CLICKED,
+ &read_database_data));
+ EXPECT_EQ(1, read_database_data.num_action_button_clicks);
+
+ ASSERT_EQ(NotificationDatabase::STATUS_OK,
+ database->ReadNotificationDataAndRecordInteraction(
+ database_data.notification_id, origin,
+ PlatformNotificationContext::Interaction::ACTION_BUTTON_CLICKED,
+ &read_database_data));
+ EXPECT_EQ(2, read_database_data.num_action_button_clicks);
+
+ // Check that the click timestamps are correctly updated.
+ EXPECT_EQ(true, read_database_data.time_until_first_click_millis.has_value());
+ EXPECT_EQ(true, read_database_data.time_until_last_click_millis.has_value());
+
+ // Check that when a read with a CLOSED interaction occurs, the correct
+ // field is updated.
+ ASSERT_EQ(NotificationDatabase::STATUS_OK,
+ database->ReadNotificationDataAndRecordInteraction(
+ database_data.notification_id, origin,
+ PlatformNotificationContext::Interaction::CLOSED,
+ &read_database_data));
+ EXPECT_EQ(true, read_database_data.time_until_close_millis.has_value());
+}
+
TEST_F(NotificationDatabaseTest, DeleteInvalidNotificationData) {
std::unique_ptr<NotificationDatabase> database(CreateDatabaseInMemory());
ASSERT_EQ(NotificationDatabase::STATUS_OK,
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
index 1f00936370a..879ab76c96d 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -13,7 +13,7 @@
#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/platform_notification_messages.h"
+#include "content/common/platform_notification_param_traits.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
@@ -45,44 +45,44 @@ void NotificationEventFinished(
}
// 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.
+// blink::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) {
+ blink::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 notification event has finished: " << service_worker_status;
+ LOG(INFO) << "The notification event has finished: "
+ << blink::ServiceWorkerStatusToString(service_worker_status);
#endif
PersistentNotificationStatus status = PERSISTENT_NOTIFICATION_STATUS_SUCCESS;
switch (service_worker_status) {
- case SERVICE_WORKER_OK:
+ case blink::ServiceWorkerStatusCode::kOk:
// Success status was initialized above.
break;
- case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED:
+ case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
status = PERSISTENT_NOTIFICATION_STATUS_EVENT_WAITUNTIL_REJECTED;
break;
- case SERVICE_WORKER_ERROR_FAILED:
- case SERVICE_WORKER_ERROR_ABORT:
- case SERVICE_WORKER_ERROR_START_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND:
- case SERVICE_WORKER_ERROR_NOT_FOUND:
- case SERVICE_WORKER_ERROR_EXISTS:
- case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_IPC_FAILED:
- case SERVICE_WORKER_ERROR_NETWORK:
- case SERVICE_WORKER_ERROR_SECURITY:
- case SERVICE_WORKER_ERROR_STATE:
- case SERVICE_WORKER_ERROR_TIMEOUT:
- case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED:
- case SERVICE_WORKER_ERROR_DISK_CACHE:
- case SERVICE_WORKER_ERROR_REDUNDANT:
- case SERVICE_WORKER_ERROR_DISALLOWED:
- case SERVICE_WORKER_ERROR_MAX_VALUE:
+ case blink::ServiceWorkerStatusCode::kErrorFailed:
+ case blink::ServiceWorkerStatusCode::kErrorAbort:
+ case blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorProcessNotFound:
+ case blink::ServiceWorkerStatusCode::kErrorNotFound:
+ case blink::ServiceWorkerStatusCode::kErrorExists:
+ case blink::ServiceWorkerStatusCode::kErrorInstallWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorActivateWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorIpcFailed:
+ case blink::ServiceWorkerStatusCode::kErrorNetwork:
+ case blink::ServiceWorkerStatusCode::kErrorSecurity:
+ case blink::ServiceWorkerStatusCode::kErrorState:
+ case blink::ServiceWorkerStatusCode::kErrorTimeout:
+ case blink::ServiceWorkerStatusCode::kErrorScriptEvaluateFailed:
+ case blink::ServiceWorkerStatusCode::kErrorDiskCache:
+ case blink::ServiceWorkerStatusCode::kErrorRedundant:
+ case blink::ServiceWorkerStatusCode::kErrorDisallowed:
status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR;
break;
}
@@ -97,7 +97,7 @@ void DispatchNotificationEventOnRegistration(
const scoped_refptr<PlatformNotificationContext>& notification_context,
const NotificationOperationCallback& dispatch_event_action,
const NotificationDispatchCompleteCallback& dispatch_error_callback,
- ServiceWorkerStatusCode service_worker_status,
+ blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
#if defined(OS_ANDROID)
@@ -105,9 +105,9 @@ void DispatchNotificationEventOnRegistration(
// 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;
+ << blink::ServiceWorkerStatusToString(service_worker_status);
#endif
- if (service_worker_status == SERVICE_WORKER_OK) {
+ if (service_worker_status == blink::ServiceWorkerStatusCode::kOk) {
DCHECK(service_worker_registration->active_version());
dispatch_event_action.Run(service_worker_registration.get(),
@@ -117,30 +117,29 @@ void DispatchNotificationEventOnRegistration(
PersistentNotificationStatus status = PERSISTENT_NOTIFICATION_STATUS_SUCCESS;
switch (service_worker_status) {
- case SERVICE_WORKER_ERROR_NOT_FOUND:
+ case blink::ServiceWorkerStatusCode::kErrorNotFound:
status = PERSISTENT_NOTIFICATION_STATUS_NO_SERVICE_WORKER;
break;
- case SERVICE_WORKER_ERROR_FAILED:
- case SERVICE_WORKER_ERROR_ABORT:
- case SERVICE_WORKER_ERROR_START_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND:
- case SERVICE_WORKER_ERROR_EXISTS:
- case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_IPC_FAILED:
- case SERVICE_WORKER_ERROR_NETWORK:
- case SERVICE_WORKER_ERROR_SECURITY:
- case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED:
- case SERVICE_WORKER_ERROR_STATE:
- case SERVICE_WORKER_ERROR_TIMEOUT:
- case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED:
- case SERVICE_WORKER_ERROR_DISK_CACHE:
- case SERVICE_WORKER_ERROR_REDUNDANT:
- case SERVICE_WORKER_ERROR_DISALLOWED:
- case SERVICE_WORKER_ERROR_MAX_VALUE:
+ case blink::ServiceWorkerStatusCode::kErrorFailed:
+ case blink::ServiceWorkerStatusCode::kErrorAbort:
+ case blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorProcessNotFound:
+ case blink::ServiceWorkerStatusCode::kErrorExists:
+ case blink::ServiceWorkerStatusCode::kErrorInstallWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorActivateWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorIpcFailed:
+ case blink::ServiceWorkerStatusCode::kErrorNetwork:
+ case blink::ServiceWorkerStatusCode::kErrorSecurity:
+ case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
+ case blink::ServiceWorkerStatusCode::kErrorState:
+ case blink::ServiceWorkerStatusCode::kErrorTimeout:
+ case blink::ServiceWorkerStatusCode::kErrorScriptEvaluateFailed:
+ case blink::ServiceWorkerStatusCode::kErrorDiskCache:
+ case blink::ServiceWorkerStatusCode::kErrorRedundant:
+ case blink::ServiceWorkerStatusCode::kErrorDisallowed:
status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR;
break;
- case SERVICE_WORKER_OK:
+ case blink::ServiceWorkerStatusCode::kOk:
NOTREACHED();
break;
}
@@ -187,13 +186,14 @@ void FindServiceWorkerRegistration(
void ReadNotificationDatabaseData(
const std::string& notification_id,
const GURL& origin,
+ PlatformNotificationContext::Interaction interaction,
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(
- notification_id, origin,
+ notification_context->ReadNotificationDataAndRecordInteraction(
+ notification_id, origin, interaction,
base::Bind(&FindServiceWorkerRegistration, origin, service_worker_context,
notification_context, notification_read_callback,
dispatch_error_callback));
@@ -209,9 +209,9 @@ void DispatchNotificationClickEventOnWorker(
const base::Optional<int>& action_index,
const base::Optional<base::string16>& reply,
ServiceWorkerVersion::StatusCallback callback,
- ServiceWorkerStatusCode start_worker_status) {
+ blink::ServiceWorkerStatusCode start_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (start_worker_status != SERVICE_WORKER_OK) {
+ if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(start_worker_status);
return;
}
@@ -223,7 +223,7 @@ void DispatchNotificationClickEventOnWorker(
if (action_index.has_value())
action_index_int = action_index.value();
- service_worker->event_dispatcher()->DispatchNotificationClickEvent(
+ service_worker->endpoint()->DispatchNotificationClickEvent(
notification_database_data.notification_id,
notification_database_data.notification_data, action_index_int, reply,
service_worker->CreateSimpleEventCallback(request_id));
@@ -252,10 +252,10 @@ void DoDispatchNotificationClickEvent(
// Called when the notification data has been deleted to finish the notification
// close event.
void OnPersistentNotificationDataDeleted(
- ServiceWorkerStatusCode service_worker_status,
+ blink::ServiceWorkerStatusCode service_worker_status,
const NotificationDispatchCompleteCallback& dispatch_complete_callback,
bool success) {
- if (service_worker_status != SERVICE_WORKER_OK) {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
ServiceWorkerNotificationEventFinished(dispatch_complete_callback,
service_worker_status);
return;
@@ -273,7 +273,7 @@ void DeleteNotificationDataFromDatabase(
const GURL& origin,
const scoped_refptr<PlatformNotificationContext>& notification_context,
const NotificationDispatchCompleteCallback& dispatch_complete_callback,
- ServiceWorkerStatusCode status_code) {
+ blink::ServiceWorkerStatusCode status_code) {
notification_context->DeleteNotificationData(
notification_id, origin,
base::Bind(&OnPersistentNotificationDataDeleted, status_code,
@@ -286,9 +286,9 @@ void DispatchNotificationCloseEventOnWorker(
const scoped_refptr<ServiceWorkerVersion>& service_worker,
const NotificationDatabaseData& notification_database_data,
ServiceWorkerVersion::StatusCallback callback,
- ServiceWorkerStatusCode start_worker_status) {
+ blink::ServiceWorkerStatusCode start_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (start_worker_status != SERVICE_WORKER_OK) {
+ if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(start_worker_status);
return;
}
@@ -296,7 +296,7 @@ void DispatchNotificationCloseEventOnWorker(
int request_id = service_worker->StartRequest(
ServiceWorkerMetrics::EventType::NOTIFICATION_CLOSE, std::move(callback));
- service_worker->event_dispatcher()->DispatchNotificationCloseEvent(
+ service_worker->endpoint()->DispatchNotificationCloseEvent(
notification_database_data.notification_id,
notification_database_data.notification_data,
service_worker->CreateSimpleEventCallback(request_id));
@@ -324,7 +324,7 @@ void DoDispatchNotificationCloseEvent(
DeleteNotificationDataFromDatabase(
notification_id, notification_database_data.origin,
notification_context, dispatch_complete_callback,
- ServiceWorkerStatusCode::SERVICE_WORKER_OK);
+ blink::ServiceWorkerStatusCode::kOk);
}
}
@@ -334,6 +334,7 @@ void DispatchNotificationEvent(
BrowserContext* browser_context,
const std::string& notification_id,
const GURL& origin,
+ const PlatformNotificationContext::Interaction interaction,
const NotificationOperationCallbackWithContext&
notification_action_callback,
const NotificationDispatchCompleteCallback& notification_error_callback) {
@@ -353,7 +354,7 @@ void DispatchNotificationEvent(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
- &ReadNotificationDatabaseData, notification_id, origin,
+ &ReadNotificationDatabaseData, notification_id, origin, interaction,
service_worker_context, notification_context,
base::Bind(notification_action_callback, notification_context),
notification_error_callback));
@@ -387,8 +388,13 @@ void NotificationEventDispatcherImpl::DispatchNotificationClickEvent(
auto repeating_callback =
base::AdaptCallbackForRepeating(std::move(dispatch_complete_callback));
+ PlatformNotificationContext::Interaction interaction =
+ action_index.has_value()
+ ? PlatformNotificationContext::Interaction::ACTION_BUTTON_CLICKED
+ : PlatformNotificationContext::Interaction::CLICKED;
+
DispatchNotificationEvent(
- browser_context, notification_id, origin,
+ browser_context, notification_id, origin, interaction,
base::Bind(&DoDispatchNotificationClickEvent, action_index, reply,
repeating_callback),
repeating_callback /* notification_error_callback */);
@@ -407,6 +413,7 @@ void NotificationEventDispatcherImpl::DispatchNotificationCloseEvent(
DispatchNotificationEvent(
browser_context, notification_id, origin,
+ PlatformNotificationContext::Interaction::CLOSED,
base::Bind(&DoDispatchNotificationCloseEvent, notification_id, by_user,
repeating_callback),
repeating_callback /* notification_error_callback */);
@@ -414,7 +421,7 @@ void NotificationEventDispatcherImpl::DispatchNotificationCloseEvent(
void NotificationEventDispatcherImpl::RegisterNonPersistentNotificationListener(
const std::string& notification_id,
- blink::mojom::NonPersistentNotificationListenerPtrInfo listener_ptr_info) {
+ blink::mojom::NonPersistentNotificationListenerPtr event_listener_ptr) {
if (non_persistent_notification_listeners_.count(notification_id)) {
// Dispatch the close event for any previously displayed notification with
// the same notification id. This happens whenever a non-persistent
@@ -425,19 +432,16 @@ void NotificationEventDispatcherImpl::RegisterNonPersistentNotificationListener(
DispatchNonPersistentCloseEvent(notification_id, base::DoNothing());
}
- blink::mojom::NonPersistentNotificationListenerPtr listener_ptr(
- std::move(listener_ptr_info));
-
// Observe connection errors, which occur when the JavaScript object or the
// renderer hosting them goes away. (For example through navigation.) The
// listener gets freed together with |this|, thus the Unretained is safe.
- listener_ptr.set_connection_error_handler(base::BindOnce(
+ event_listener_ptr.set_connection_error_handler(base::BindOnce(
&NotificationEventDispatcherImpl::
HandleConnectionErrorForNonPersistentNotificationListener,
base::Unretained(this), notification_id));
non_persistent_notification_listeners_.emplace(notification_id,
- std::move(listener_ptr));
+ std::move(event_listener_ptr));
}
void NotificationEventDispatcherImpl::DispatchNonPersistentShowEvent(
@@ -448,10 +452,15 @@ void NotificationEventDispatcherImpl::DispatchNonPersistentShowEvent(
}
void NotificationEventDispatcherImpl::DispatchNonPersistentClickEvent(
- const std::string& notification_id) {
- if (!non_persistent_notification_listeners_.count(notification_id))
+ const std::string& notification_id,
+ NotificationClickEventCallback callback) {
+ if (!non_persistent_notification_listeners_.count(notification_id)) {
+ std::move(callback).Run(false /* success */);
return;
- non_persistent_notification_listeners_[notification_id]->OnClick();
+ }
+
+ non_persistent_notification_listeners_[notification_id]->OnClick(
+ base::BindOnce(std::move(callback), true /* success */));
}
void NotificationEventDispatcherImpl::DispatchNonPersistentCloseEvent(
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.h b/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
index dff47bf1dbe..230c56df61a 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
@@ -41,7 +41,8 @@ class CONTENT_EXPORT NotificationEventDispatcherImpl
void DispatchNonPersistentShowEvent(
const std::string& notification_id) override;
void DispatchNonPersistentClickEvent(
- const std::string& notification_id) override;
+ const std::string& notification_id,
+ NotificationClickEventCallback callback) override;
void DispatchNonPersistentCloseEvent(
const std::string& notification_id,
base::OnceClosure completed_closure) override;
@@ -50,7 +51,7 @@ class CONTENT_EXPORT NotificationEventDispatcherImpl
// non-persistent notification identified by |notification_id|.
void RegisterNonPersistentNotificationListener(
const std::string& notification_id,
- blink::mojom::NonPersistentNotificationListenerPtrInfo listener_ptr_info);
+ blink::mojom::NonPersistentNotificationListenerPtr event_listener_ptr);
private:
friend class NotificationEventDispatcherImplTest;
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc b/chromium/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc
index a2bbe92a81e..d1bf4fe4d95 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc
@@ -50,7 +50,10 @@ class TestNotificationListener
// blink::mojom::NonPersistentNotificationListener implementation.
void OnShow() override { on_show_count_++; }
- void OnClick() override { on_click_count_++; }
+ void OnClick(OnClickCallback completed_closure) override {
+ on_click_count_++;
+ std::move(completed_closure).Run();
+ }
void OnClose(OnCloseCallback completed_closure) override {
on_close_count_++;
std::move(completed_closure).Run();
@@ -94,11 +97,11 @@ class NotificationEventDispatcherImplTest : public ::testing::Test {
TEST_F(NotificationEventDispatcherImplTest,
DispatchNonPersistentShowEvent_NotifiesCorrectRegisteredListener) {
auto listener = std::make_unique<TestNotificationListener>();
- dispatcher_->RegisterNonPersistentNotificationListener(
- kPrimaryUniqueId, listener->GetPtr().PassInterface());
+ dispatcher_->RegisterNonPersistentNotificationListener(kPrimaryUniqueId,
+ listener->GetPtr());
auto other_listener = std::make_unique<TestNotificationListener>();
dispatcher_->RegisterNonPersistentNotificationListener(
- kSomeOtherUniqueId, other_listener->GetPtr().PassInterface());
+ kSomeOtherUniqueId, other_listener->GetPtr());
dispatcher_->DispatchNonPersistentShowEvent(kPrimaryUniqueId);
@@ -119,7 +122,7 @@ TEST_F(NotificationEventDispatcherImplTest,
RegisterReplacementNonPersistentListener_FirstListenerGetsOnClose) {
auto original_listener = std::make_unique<TestNotificationListener>();
dispatcher_->RegisterNonPersistentNotificationListener(
- kPrimaryUniqueId, original_listener->GetPtr().PassInterface());
+ kPrimaryUniqueId, original_listener->GetPtr());
dispatcher_->DispatchNonPersistentShowEvent(kPrimaryUniqueId);
@@ -127,7 +130,7 @@ TEST_F(NotificationEventDispatcherImplTest,
auto replacement_listener = std::make_unique<TestNotificationListener>();
dispatcher_->RegisterNonPersistentNotificationListener(
- kPrimaryUniqueId, replacement_listener->GetPtr().PassInterface());
+ kPrimaryUniqueId, replacement_listener->GetPtr());
WaitForMojoTasksToComplete();
@@ -138,20 +141,22 @@ TEST_F(NotificationEventDispatcherImplTest,
TEST_F(NotificationEventDispatcherImplTest,
DispatchNonPersistentClickEvent_NotifiesCorrectRegisteredListener) {
auto listener = std::make_unique<TestNotificationListener>();
- dispatcher_->RegisterNonPersistentNotificationListener(
- kPrimaryUniqueId, listener->GetPtr().PassInterface());
+ dispatcher_->RegisterNonPersistentNotificationListener(kPrimaryUniqueId,
+ listener->GetPtr());
auto other_listener = std::make_unique<TestNotificationListener>();
dispatcher_->RegisterNonPersistentNotificationListener(
- kSomeOtherUniqueId, other_listener->GetPtr().PassInterface());
+ kSomeOtherUniqueId, other_listener->GetPtr());
- dispatcher_->DispatchNonPersistentClickEvent(kPrimaryUniqueId);
+ dispatcher_->DispatchNonPersistentClickEvent(kPrimaryUniqueId,
+ base::DoNothing());
WaitForMojoTasksToComplete();
EXPECT_EQ(listener->on_click_count(), 1);
EXPECT_EQ(other_listener->on_click_count(), 0);
- dispatcher_->DispatchNonPersistentClickEvent(kSomeOtherUniqueId);
+ dispatcher_->DispatchNonPersistentClickEvent(kSomeOtherUniqueId,
+ base::DoNothing());
WaitForMojoTasksToComplete();
@@ -162,11 +167,11 @@ TEST_F(NotificationEventDispatcherImplTest,
TEST_F(NotificationEventDispatcherImplTest,
DispatchNonPersistentCloseEvent_NotifiesCorrectRegisteredListener) {
auto listener = std::make_unique<TestNotificationListener>();
- dispatcher_->RegisterNonPersistentNotificationListener(
- kPrimaryUniqueId, listener->GetPtr().PassInterface());
+ dispatcher_->RegisterNonPersistentNotificationListener(kPrimaryUniqueId,
+ listener->GetPtr());
auto other_listener = std::make_unique<TestNotificationListener>();
dispatcher_->RegisterNonPersistentNotificationListener(
- kSomeOtherUniqueId, other_listener->GetPtr().PassInterface());
+ kSomeOtherUniqueId, other_listener->GetPtr());
dispatcher_->DispatchNonPersistentCloseEvent(kPrimaryUniqueId,
base::DoNothing());
@@ -188,11 +193,12 @@ TEST_F(NotificationEventDispatcherImplTest,
TEST_F(NotificationEventDispatcherImplTest,
DispatchMultipleNonPersistentEvents_StopsNotifyingAfterClose) {
auto listener = std::make_unique<TestNotificationListener>();
- dispatcher_->RegisterNonPersistentNotificationListener(
- kPrimaryUniqueId, listener->GetPtr().PassInterface());
+ dispatcher_->RegisterNonPersistentNotificationListener(kPrimaryUniqueId,
+ listener->GetPtr());
dispatcher_->DispatchNonPersistentShowEvent(kPrimaryUniqueId);
- dispatcher_->DispatchNonPersistentClickEvent(kPrimaryUniqueId);
+ dispatcher_->DispatchNonPersistentClickEvent(kPrimaryUniqueId,
+ base::DoNothing());
dispatcher_->DispatchNonPersistentCloseEvent(kPrimaryUniqueId,
base::DoNothing());
@@ -203,7 +209,8 @@ TEST_F(NotificationEventDispatcherImplTest,
EXPECT_EQ(listener->on_close_count(), 1);
// Should not be counted as the notification was already closed.
- dispatcher_->DispatchNonPersistentClickEvent(kPrimaryUniqueId);
+ dispatcher_->DispatchNonPersistentClickEvent(kPrimaryUniqueId,
+ base::DoNothing());
WaitForMojoTasksToComplete();
diff --git a/chromium/content/browser/notifications/platform_notification_context_impl.cc b/chromium/content/browser/notifications/platform_notification_context_impl.cc
index e174998b4d5..627e8dbd251 100644
--- a/chromium/content/browser/notifications/platform_notification_context_impl.cc
+++ b/chromium/content/browser/notifications/platform_notification_context_impl.cc
@@ -105,6 +105,9 @@ void PlatformNotificationContextImpl::InitializeOnIO(
void PlatformNotificationContextImpl::Shutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ services_.clear();
+
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&PlatformNotificationContextImpl::ShutdownOnIO, this));
@@ -113,40 +116,23 @@ void PlatformNotificationContextImpl::Shutdown() {
void PlatformNotificationContextImpl::ShutdownOnIO() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- services_.clear();
-
// |service_worker_context_| may be NULL in tests.
if (service_worker_context_)
service_worker_context_->RemoveObserver(this);
}
void PlatformNotificationContextImpl::CreateService(
- int render_process_id,
const url::Origin& origin,
blink::mojom::NotificationServiceRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PlatformNotificationContextImpl::CreateServiceOnIO, this,
- render_process_id, origin,
- browser_context_->GetResourceContext(),
- std::move(request)));
-}
-
-void PlatformNotificationContextImpl::CreateServiceOnIO(
- int render_process_id,
- const url::Origin& origin,
- ResourceContext* resource_context,
- mojo::InterfaceRequest<blink::mojom::NotificationService> request) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
services_.push_back(std::make_unique<BlinkNotificationServiceImpl>(
- this, browser_context_, resource_context, service_worker_context_,
- render_process_id, origin, std::move(request)));
+ this, browser_context_, service_worker_context_, origin,
+ std::move(request)));
}
void PlatformNotificationContextImpl::RemoveService(
BlinkNotificationServiceImpl* service) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::EraseIf(
services_,
[service](const std::unique_ptr<BlinkNotificationServiceImpl>& ptr) {
@@ -154,27 +140,30 @@ void PlatformNotificationContextImpl::RemoveService(
});
}
-void PlatformNotificationContextImpl::ReadNotificationData(
+void PlatformNotificationContextImpl::ReadNotificationDataAndRecordInteraction(
const std::string& notification_id,
const GURL& origin,
+ const PlatformNotificationContext::Interaction interaction,
const ReadResultCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
LazyInitialize(
base::Bind(&PlatformNotificationContextImpl::DoReadNotificationData, this,
- notification_id, origin, callback),
+ notification_id, origin, interaction, callback),
base::Bind(callback, false /* success */, NotificationDatabaseData()));
}
void PlatformNotificationContextImpl::DoReadNotificationData(
const std::string& notification_id,
const GURL& origin,
+ Interaction interaction,
const ReadResultCallback& callback) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
NotificationDatabaseData database_data;
NotificationDatabase::Status status =
- database_->ReadNotificationData(notification_id, origin, &database_data);
+ database_->ReadNotificationDataAndRecordInteraction(
+ notification_id, origin, interaction, &database_data);
UMA_HISTOGRAM_ENUMERATION("Notifications.Database.ReadResult", status,
NotificationDatabase::STATUS_COUNT);
@@ -319,17 +308,20 @@ void PlatformNotificationContextImpl::
}
void PlatformNotificationContextImpl::WriteNotificationData(
+ int64_t persistent_notification_id,
const GURL& origin,
const NotificationDatabaseData& database_data,
const WriteResultCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
LazyInitialize(
base::Bind(&PlatformNotificationContextImpl::DoWriteNotificationData,
- this, origin, database_data, callback),
+ this, persistent_notification_id, origin, database_data,
+ callback),
base::Bind(callback, false /* success */, "" /* notification_id */));
}
void PlatformNotificationContextImpl::DoWriteNotificationData(
+ int64_t persistent_notification_id,
const GURL& origin,
const NotificationDatabaseData& database_data,
const WriteResultCallback& callback) {
@@ -366,7 +358,7 @@ void PlatformNotificationContextImpl::DoWriteNotificationData(
write_database_data.notification_id =
notification_id_generator_.GenerateForPersistentNotification(
origin, database_data.notification_data.tag,
- database_->GetNextPersistentNotificationId());
+ persistent_notification_id);
NotificationDatabase::Status status =
database_->WriteNotificationData(origin, write_database_data);
diff --git a/chromium/content/browser/notifications/platform_notification_context_impl.h b/chromium/content/browser/notifications/platform_notification_context_impl.h
index a780c453cca..7ea92b62620 100644
--- a/chromium/content/browser/notifications/platform_notification_context_impl.h
+++ b/chromium/content/browser/notifications/platform_notification_context_impl.h
@@ -39,7 +39,6 @@ class BlinkNotificationServiceImpl;
class BrowserContext;
class NotificationDatabase;
struct NotificationDatabaseData;
-class ResourceContext;
class ServiceWorkerContextWrapper;
// Implementation of the Web Notification storage context. The public methods
@@ -65,14 +64,12 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
void Shutdown();
// Creates a BlinkNotificationServiceImpl that is owned by this context. Must
- // be called on the UI thread, although the service will be created on and
- // bound to the IO thread.
- void CreateService(int render_process_id,
- const url::Origin& origin,
+ // be called on the UI thread.
+ void CreateService(const url::Origin& origin,
blink::mojom::NotificationServiceRequest request);
// Removes |service| from the list of owned services, for example because the
- // Mojo pipe disconnected. Must be called on the IO thread.
+ // Mojo pipe disconnected. Must be called on the UI thread.
void RemoveService(BlinkNotificationServiceImpl* service);
// Returns the notification Id generator owned by the context.
@@ -81,10 +78,13 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
}
// PlatformNotificationContext implementation.
- void ReadNotificationData(const std::string& notification_id,
- const GURL& origin,
- const ReadResultCallback& callback) override;
- void WriteNotificationData(const GURL& origin,
+ void ReadNotificationDataAndRecordInteraction(
+ const std::string& notification_id,
+ const GURL& origin,
+ Interaction interaction,
+ const ReadResultCallback& callback) override;
+ void WriteNotificationData(int64_t persistent_notification_id,
+ const GURL& origin,
const NotificationDatabaseData& database_data,
const WriteResultCallback& callback) override;
void DeleteNotificationData(const std::string& notification_id,
@@ -112,11 +112,6 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
std::unique_ptr<std::set<std::string>> displayed_notifications,
bool supports_synchronization);
void ShutdownOnIO();
- void CreateServiceOnIO(
- int render_process_id,
- const url::Origin& origin,
- ResourceContext* resource_context,
- mojo::InterfaceRequest<blink::mojom::NotificationService> request);
// Initializes the database if neccesary. Must be called on the IO thread.
// |success_closure| will be invoked on a the |task_runner_| thread when
@@ -136,6 +131,7 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
// IO thread when the operation has completed.
void DoReadNotificationData(const std::string& notification_id,
const GURL& origin,
+ Interaction interaction,
const ReadResultCallback& callback);
// Updates the database (and the result callback) based on
@@ -169,7 +165,8 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
// Actually writes the notification database to the database. Must only be
// called on the |task_runner_| thread. |callback| will be invoked on the
// IO thread when the operation has completed.
- void DoWriteNotificationData(const GURL& origin,
+ void DoWriteNotificationData(int64_t persistent_notification_id,
+ const GURL& origin,
const NotificationDatabaseData& database_data,
const WriteResultCallback& callback);
diff --git a/chromium/content/browser/notifications/platform_notification_context_unittest.cc b/chromium/content/browser/notifications/platform_notification_context_unittest.cc
index d661a252d6f..ffe0ebb1681 100644
--- a/chromium/content/browser/notifications/platform_notification_context_unittest.cc
+++ b/chromium/content/browser/notifications/platform_notification_context_unittest.cc
@@ -68,19 +68,19 @@ class PlatformNotificationContextTest : public ::testing::Test {
// Callback to provide when registering a Service Worker with a Service
// Worker Context. Will write the registration id to |store_registration_id|.
void DidRegisterServiceWorker(int64_t* store_registration_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t service_worker_registration_id) {
DCHECK(store_registration_id);
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
*store_registration_id = service_worker_registration_id;
}
// Callback to provide when unregistering a Service Worker. Will write the
// resulting status code to |store_status|.
- void DidUnregisterServiceWorker(ServiceWorkerStatusCode* store_status,
- ServiceWorkerStatusCode status) {
+ void DidUnregisterServiceWorker(blink::ServiceWorkerStatusCode* store_status,
+ blink::ServiceWorkerStatusCode status) {
DCHECK(store_status);
*store_status = status;
}
@@ -123,6 +123,11 @@ class PlatformNotificationContextTest : public ::testing::Test {
// Returns whether the last invoked callback finished successfully.
bool success() const { return success_; }
+ // Returns the next persistent notification id for tests.
+ int64_t next_persistent_notification_id() {
+ return next_persistent_notification_id_++;
+ }
+
// Returns the NotificationDatabaseData associated with the last invoked
// ReadNotificationData callback.
const NotificationDatabaseData& database_data() const {
@@ -133,20 +138,22 @@ class PlatformNotificationContextTest : public ::testing::Test {
const std::string& notification_id() const { return notification_id_; }
private:
- TestBrowserThreadBundle thread_bundle_;
+ TestBrowserThreadBundle thread_bundle_; // Must be first member
TestBrowserContext browser_context_;
bool success_;
NotificationDatabaseData database_data_;
std::string notification_id_;
+ int64_t next_persistent_notification_id_ = 1;
};
TEST_F(PlatformNotificationContextTest, ReadNonExistentNotification) {
scoped_refptr<PlatformNotificationContextImpl> context =
CreatePlatformNotificationContext();
- context->ReadNotificationData(
+ context->ReadNotificationDataAndRecordInteraction(
"invalid-notification-id", GURL("https://example.com"),
+ PlatformNotificationContext::Interaction::NONE,
base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
base::Unretained(this)));
@@ -165,7 +172,7 @@ TEST_F(PlatformNotificationContextTest, WriteReadNotification) {
notification_database_data.origin = origin;
context->WriteNotificationData(
- origin, notification_database_data,
+ next_persistent_notification_id(), origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -175,8 +182,8 @@ TEST_F(PlatformNotificationContextTest, WriteReadNotification) {
ASSERT_TRUE(success());
EXPECT_FALSE(notification_id().empty());
- context->ReadNotificationData(
- notification_id(), origin,
+ context->ReadNotificationDataAndRecordInteraction(
+ notification_id(), origin, PlatformNotificationContext::Interaction::NONE,
base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
base::Unretained(this)));
@@ -206,10 +213,9 @@ TEST_F(PlatformNotificationContextTest, WriteReadReplacedNotification) {
// Write the first notification with the given |tag|.
context->WriteNotificationData(
- origin, notification_database_data,
+ next_persistent_notification_id(), origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
-
base::RunLoop().RunUntilIdle();
std::string read_notification_id = notification_id();
@@ -223,7 +229,7 @@ TEST_F(PlatformNotificationContextTest, WriteReadReplacedNotification) {
// Write the second notification with the given |tag|.
context->WriteNotificationData(
- origin, notification_database_data,
+ next_persistent_notification_id(), origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -277,7 +283,7 @@ TEST_F(PlatformNotificationContextTest, DeleteNotification) {
NotificationDatabaseData notification_database_data;
context->WriteNotificationData(
- origin, notification_database_data,
+ next_persistent_notification_id(), origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -297,8 +303,8 @@ TEST_F(PlatformNotificationContextTest, DeleteNotification) {
// The notification existed, so it should have been removed successfully.
ASSERT_TRUE(success());
- context->ReadNotificationData(
- notification_id(), origin,
+ context->ReadNotificationDataAndRecordInteraction(
+ notification_id(), origin, PlatformNotificationContext::Interaction::NONE,
base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
base::Unretained(this)));
@@ -345,7 +351,7 @@ TEST_F(PlatformNotificationContextTest, ServiceWorkerUnregistered) {
// Create a notification for that Service Worker registration.
notification_context->WriteNotificationData(
- origin, notification_database_data,
+ next_persistent_notification_id(), origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -354,7 +360,7 @@ TEST_F(PlatformNotificationContextTest, ServiceWorkerUnregistered) {
ASSERT_TRUE(success());
EXPECT_FALSE(notification_id().empty());
- ServiceWorkerStatusCode unregister_status;
+ blink::ServiceWorkerStatusCode unregister_status;
// Now drop the Service Worker registration which owns that notification.
embedded_worker_test_helper->context()->UnregisterServiceWorker(
@@ -363,11 +369,11 @@ TEST_F(PlatformNotificationContextTest, ServiceWorkerUnregistered) {
base::Unretained(this), &unregister_status));
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(SERVICE_WORKER_OK, unregister_status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, unregister_status);
// And verify that the associated notification has indeed been dropped.
- notification_context->ReadNotificationData(
- notification_id(), origin,
+ notification_context->ReadNotificationDataAndRecordInteraction(
+ notification_id(), origin, PlatformNotificationContext::Interaction::NONE,
base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
base::Unretained(this)));
@@ -384,7 +390,7 @@ TEST_F(PlatformNotificationContextTest, DestroyDatabaseOnStorageWiped) {
NotificationDatabaseData notification_database_data;
context->WriteNotificationData(
- origin, notification_database_data,
+ next_persistent_notification_id(), origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -401,8 +407,8 @@ TEST_F(PlatformNotificationContextTest, DestroyDatabaseOnStorageWiped) {
// Verify that reading notification data fails because the data does not
// exist anymore. Deliberately omit RunUntilIdle(), since this is unlikely to
// be the case when OnStorageWiped gets called in production.
- context->ReadNotificationData(
- notification_id(), origin,
+ context->ReadNotificationDataAndRecordInteraction(
+ notification_id(), origin, PlatformNotificationContext::Interaction::NONE,
base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
base::Unretained(this)));
@@ -424,8 +430,9 @@ TEST_F(PlatformNotificationContextTest, DestroyOnDiskDatabase) {
OverrideTaskRunnerForTesting(context.get());
// Trigger a read-operation to force creating the database.
- context->ReadNotificationData(
+ context->ReadNotificationDataAndRecordInteraction(
"invalid-notification-id", GURL("https://example.com"),
+ PlatformNotificationContext::Interaction::NONE,
base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
base::Unretained(this)));
@@ -476,7 +483,7 @@ TEST_F(PlatformNotificationContextTest, ReadAllServiceWorkerDataFilled) {
// test Service Worker Registration id.
for (int i = 0; i < 10; ++i) {
context->WriteNotificationData(
- origin, notification_database_data,
+ next_persistent_notification_id(), origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -520,7 +527,7 @@ TEST_F(PlatformNotificationContextTest, SynchronizeNotifications) {
content::NotificationResources notification_resources;
context->WriteNotificationData(
- origin, notification_database_data,
+ next_persistent_notification_id(), origin, notification_database_data,
base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData,
base::Unretained(this)));
@@ -558,8 +565,9 @@ TEST_F(PlatformNotificationContextTest, SynchronizeNotifications) {
ASSERT_TRUE(success());
ASSERT_EQ(0u, notification_database_datas.size());
- context->ReadNotificationData(
+ context->ReadNotificationDataAndRecordInteraction(
notification_id(), origin,
+ PlatformNotificationContext::Interaction::CLOSED,
base::Bind(&PlatformNotificationContextTest::DidReadNotificationData,
base::Unretained(this)));
diff --git a/chromium/content/browser/oop_browsertest.cc b/chromium/content/browser/oop_browsertest.cc
index e6e00b92256..390c73409e9 100644
--- a/chromium/content/browser/oop_browsertest.cc
+++ b/chromium/content/browser/oop_browsertest.cc
@@ -7,11 +7,14 @@
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "build/build_config.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.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_utils.h"
@@ -33,9 +36,9 @@ class OOPBrowserTest : public ContentBrowserTest {
ContentBrowserTest::SetUpCommandLine(command_line);
command_line->AppendSwitch(switches::kEnableGpuRasterization);
command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
- command_line->AppendSwitch(switches::kEnableOOPRasterization);
+ command_line->AppendSwitch(switches::kEnableOopRasterization);
- const bool use_gpu_in_tests = !features::IsMashEnabled();
+ const bool use_gpu_in_tests = features::IsAshInBrowserProcess();
if (use_gpu_in_tests)
command_line->AppendSwitch(switches::kUseGpuInTests);
}
@@ -58,10 +61,13 @@ IN_PROC_BROWSER_TEST_F(OOPBrowserTest, Basic) {
"<style>div{background-color:blue; width:100; height:100;}</style>"
"<body bgcolor=blue><div></div></body>");
NavigateToURLBlockUntilNavigationsComplete(shell(), url, 1);
- shell()->web_contents()->GetMainFrame()->InsertVisualStateCallback(base::Bind(
- &OOPBrowserTest::VerifyVisualStateUpdated, base::Unretained(this),
- base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()));
- content::RunMessageLoop();
+
+ // Wait for the renderer to submit a frame.
+ RenderFrameSubmissionObserver frame_observer(
+ RenderWidgetHostImpl::From(
+ shell()->web_contents()->GetRenderViewHost()->GetWidget())
+ ->render_frame_metadata_provider());
+ frame_observer.WaitForAnyFrameSubmission();
auto* rwh = shell()->web_contents()->GetRenderViewHost()->GetWidget();
ASSERT_TRUE(rwh->GetView()->IsSurfaceAvailableForCopy());
@@ -78,7 +84,7 @@ IN_PROC_BROWSER_TEST_F(OOPBrowserTest, Basic) {
&snapshot, run_loop.QuitWhenIdleClosure()));
run_loop.Run();
- EXPECT_FALSE(snapshot.drawsNothing());
+ ASSERT_FALSE(snapshot.drawsNothing());
for (int i = 0; i < snapshot.width(); ++i) {
for (int j = 0; j < snapshot.height(); ++j) {
ASSERT_EQ(snapshot.getColor(i, j), SK_ColorBLUE);
diff --git a/chromium/content/browser/origin_manifest/origin_manifest_parser.cc b/chromium/content/browser/origin_manifest/origin_manifest_parser.cc
deleted file mode 100644
index 1b6a3db52d2..00000000000
--- a/chromium/content/browser/origin_manifest/origin_manifest_parser.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/origin_manifest/origin_manifest_parser.h"
-
-#include "base/json/json_reader.h"
-#include "base/strings/string_util.h"
-
-namespace content {
-namespace origin_manifest_parser {
-
-std::unique_ptr<blink::OriginManifest> Parse(std::string json) {
- // TODO throw some meaningful errors when parsing does not go well
- std::unique_ptr<base::DictionaryValue> directives_dict =
- base::DictionaryValue::From(
- base::JSONReader::Read(json, base::JSON_ALLOW_TRAILING_COMMAS));
-
- std::unique_ptr<blink::OriginManifest> origin_manifest;
-
- // TODO(dhausknecht) that's playing safe. But we should do something to tell
- // things went wrong here.
- if (!directives_dict)
- return origin_manifest;
-
- origin_manifest.reset(new blink::OriginManifest());
-
- for (base::detail::dict_iterator_proxy::iterator it =
- directives_dict->DictItems().begin();
- it != directives_dict->DictItems().end(); ++it) {
- switch (GetDirectiveType(it->first)) {
- // content-security-policy
- case DirectiveType::kContentSecurityPolicy:
- ParseContentSecurityPolicy(origin_manifest.get(),
- std::move(it->second));
- break;
- case DirectiveType::kUnknown:
- // Ignore unknown directives for forward-compatibility
- break;
- }
- }
-
- return origin_manifest;
-}
-
-DirectiveType GetDirectiveType(const std::string& name) {
- if (name == "content-security-policy") {
- return DirectiveType::kContentSecurityPolicy;
- }
-
- return DirectiveType::kUnknown;
-}
-
-void ParseContentSecurityPolicy(blink::OriginManifest* const om,
- base::Value value) {
- // TODO give respective parsing errors
- if (!value.is_list())
- return;
-
- for (auto& elem : value.GetList()) {
- if (!elem.is_dict())
- continue;
-
- std::string policy = "";
- blink::OriginManifest::ContentSecurityPolicyType disposition =
- blink::OriginManifest::ContentSecurityPolicyType::kEnforce;
- blink::OriginManifest::ActivationType activation_type =
- blink::OriginManifest::ActivationType::kFallback;
-
- const base::Value* v = elem.FindKey("policy");
- if (v && v->is_string())
- policy = v->GetString();
-
- v = elem.FindKey("disposition");
- if (v && v->is_string())
- disposition = GetCSPDisposition(v->GetString());
-
- v = elem.FindKey("allow-override");
- if (v && v->is_bool()) {
- activation_type = GetCSPActivationType(v->GetBool());
- }
-
- om->AddContentSecurityPolicy(policy, disposition, activation_type);
- }
-}
-
-blink::OriginManifest::ContentSecurityPolicyType GetCSPDisposition(
- const std::string& name) {
- if (name == "enforce")
- return blink::OriginManifest::ContentSecurityPolicyType::kEnforce;
- if (name == "report-only")
- return blink::OriginManifest::ContentSecurityPolicyType::kReport;
-
- return blink::OriginManifest::ContentSecurityPolicyType::kEnforce;
-}
-
-blink::OriginManifest::ActivationType GetCSPActivationType(const bool value) {
- if (value)
- return blink::OriginManifest::ActivationType::kBaseline;
-
- return blink::OriginManifest::ActivationType::kFallback;
-}
-
-} // namespace origin_manifest_parser
-} // namespace content
diff --git a/chromium/content/browser/origin_manifest/origin_manifest_parser.h b/chromium/content/browser/origin_manifest/origin_manifest_parser.h
deleted file mode 100644
index fa3ef6ba71f..00000000000
--- a/chromium/content/browser/origin_manifest/origin_manifest_parser.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2017 The Chromium Authors. All 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_ORIGIN_MANIFEST_ORIGIN_MANIFEST_PARSER_H_
-#define CONTENT_BROWSER_ORIGIN_MANIFEST_ORIGIN_MANIFEST_PARSER_H_
-
-#include <string>
-
-#include "base/values.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/common/origin_manifest/origin_manifest.h"
-
-namespace base {
-class Value;
-}
-
-namespace content {
-namespace origin_manifest_parser {
-
-// Tries to parse an Origin Manifest from string. In case it fails the pointer
-// is set to nullptr.
-std::unique_ptr<blink::OriginManifest> CONTENT_EXPORT Parse(std::string json);
-
-enum class DirectiveType {
- kContentSecurityPolicy,
- kUnknown,
-};
-
-// Tries to parse the |DirectiveType| from string. Valid strings are all
-// top-level keywords from the Origin Manifest JSON format, e.g.
-// 'content-security-policy'. Returns kUnknown on failure.
-DirectiveType CONTENT_EXPORT GetDirectiveType(const std::string& str);
-
-// Reads out the values from |value| to add a ContentSecurityPolicy to the given
-// OriginManifest using its interface. In case invalid values are set they are
-// simply ignored. In case values are missing the respective default values are
-// set.
-void CONTENT_EXPORT ParseContentSecurityPolicy(blink::OriginManifest* const om,
- base::Value value);
-
-// Tries to parse the |ContentSecurityPolicyType| from string. Valid values are
-// "enforce" and "report-only". Returns kUnknown on failure.
-blink::OriginManifest::ContentSecurityPolicyType CONTENT_EXPORT
-GetCSPDisposition(const std::string& json);
-
-// If |value| is true returns kBaseline, kFallback otherwise.
-blink::OriginManifest::ActivationType CONTENT_EXPORT
-GetCSPActivationType(const bool value);
-
-} // namespace origin_manifest_parser
-} // namespace content
-
-#endif // CONTENT_BROWSER_ORIGIN_MANIFEST_ORIGIN_MANIFEST_PARSER_H_
diff --git a/chromium/content/browser/origin_manifest/origin_manifest_parser_unittest.cc b/chromium/content/browser/origin_manifest/origin_manifest_parser_unittest.cc
deleted file mode 100644
index 5f12ec7bac8..00000000000
--- a/chromium/content/browser/origin_manifest/origin_manifest_parser_unittest.cc
+++ /dev/null
@@ -1,386 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdio.h>
-
-#include "content/browser/origin_manifest/origin_manifest_parser.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-namespace origin_manifest_parser {
-
-class OriginManifestParserTest : public testing::Test {};
-
-// Note that we do not initialize the persistent store here since that
-// is subject to testing the persistent store itself.
-
-TEST_F(OriginManifestParserTest, ParsingSuccess) {
- // basically it should only create an Origin Manifest on valid JSON
- struct TestCase {
- std::string json;
- bool equalsNull;
- } cases[] = {
- {"", true},
- {"{ \"I am not valid\"", true},
- {"{ }", false},
- {"{ \"valid\": \"JSON\", \"but\": [\"unknown\", \"structure\"] }", false},
- {"{ \"tls\": {}, \"tls\": {} }", false}};
-
- for (const auto& test : cases) {
- EXPECT_EQ(Parse(test.json).get() == nullptr, test.equalsNull);
- }
-}
-
-TEST_F(OriginManifestParserTest, ParseCSPWithUnexpectedSyntax) {
- // CSP value not a list
- std::string json = "{ \"content-security-policy\": 42 }";
- std::unique_ptr<blink::OriginManifest> om = Parse(json);
- ASSERT_FALSE(om.get() == nullptr);
- EXPECT_EQ(om->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks)
- .size(),
- 0ul);
-
- // not a list of objects but directly the CSP attributes
- json =
- "{ \"content-security-policy\": [ \"this is not the content\", \"you are "
- "looking for\" ] }";
- om = Parse(json);
- ASSERT_FALSE(om.get() == nullptr);
- EXPECT_EQ(om->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks)
- .size(),
- 0ul);
-
- // CSP alongside unknown attributes should be fine
- json =
- "{ "
- "\"unknown\": 42,"
- "\"content-security-policy\": ["
- " { \"policy\": \"default-src 'none'\" },"
- "],"
- "\"hardcore\": \"unknown\","
- " }";
- om = Parse(json);
- ASSERT_FALSE(om.get() == nullptr);
- EXPECT_EQ(om->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks)
- .size(),
- 1ul);
-
- // containing unknown attributes should be fine
- json =
- "{ "
- "\"content-security-policy\": [ {"
- " \"unknown\": 42,"
- " \"policy\": \"default-src 'none'\","
- " \"hardcore\": \"unknown\","
- " } ],"
- "}";
- om = Parse(json);
- ASSERT_FALSE(om.get() == nullptr);
- EXPECT_EQ(om->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks)
- .size(),
- 1ul);
- EXPECT_EQ(
- om->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks)[0]
- .policy,
- "default-src 'none'");
-
- // multiple CSPs
- json =
- "{ \"content-security-policy\": ["
- "{ \"policy\": \"default-src 'none'\" },"
- "{ \"policy\": \"default-src 'none'\" }"
- "] }";
- om = Parse(json);
- ASSERT_FALSE(om.get() == nullptr);
- EXPECT_EQ(om->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks)
- .size(),
- 2ul);
-}
-
-TEST_F(OriginManifestParserTest, ParseCSPWithMissingAttributes) {
- // invalid values are tested separately below, no need to re-test it here
- struct TestCase {
- std::string policy;
- std::string disposition;
- std::string allow_override;
- std::string expected_policy;
- blink::OriginManifest::ContentSecurityPolicyType expected_disposition;
- bool expected_allow_override;
- } cases[] = {
- {"", "", "", "",
- blink::OriginManifest::ContentSecurityPolicyType::kEnforce, false},
- {"", "report-only", "true", "",
- blink::OriginManifest::ContentSecurityPolicyType::kReport, true},
- {"", "", "true", "",
- blink::OriginManifest::ContentSecurityPolicyType::kEnforce, true},
- {"", "report-only", "", "",
- blink::OriginManifest::ContentSecurityPolicyType::kReport, false},
- {"default-src 'none'", "", "true", "default-src 'none'",
- blink::OriginManifest::ContentSecurityPolicyType::kEnforce, true},
- {"default-src 'none'", "", "", "default-src 'none'",
- blink::OriginManifest::ContentSecurityPolicyType::kEnforce, false},
- {"default-src 'none'", "report-only", "", "default-src 'none'",
- blink::OriginManifest::ContentSecurityPolicyType::kReport, false},
- {"default-src 'none'", "report-only", "true", "default-src 'none'",
- blink::OriginManifest::ContentSecurityPolicyType::kReport, true},
- };
-
- for (const auto& test : cases) {
- std::ostringstream str_stream;
- str_stream << "{ \"content-security-policy\": [ {";
- if (test.policy.length() > 0)
- str_stream << "\"policy\": \"" << test.policy << "\", ";
- if (test.disposition.length() > 0)
- str_stream << "\"disposition\": \"" << test.disposition << "\", ";
- if (test.allow_override.length() > 0)
- str_stream << "\"allow-override\": " << test.allow_override << ", ";
- str_stream << "}, ] }";
-
- std::unique_ptr<blink::OriginManifest> om = Parse(str_stream.str());
-
- ASSERT_FALSE(om.get() == nullptr);
- std::vector<blink::OriginManifest::ContentSecurityPolicy>
- baseline_fallback = om->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks);
- ASSERT_EQ(baseline_fallback.size(), 1ul);
-
- EXPECT_EQ(baseline_fallback[0].policy, test.expected_policy);
- EXPECT_EQ(baseline_fallback[0].disposition, test.expected_disposition);
-
- // if override is not allowed it is a fallback and baseline should be empty
- std::vector<blink::OriginManifest::ContentSecurityPolicy> baseline =
- om->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kBaselineOnly);
- EXPECT_EQ(baseline.size(), (test.expected_allow_override) ? 1ul : 0ul);
- }
-}
-
-TEST_F(OriginManifestParserTest, GetDirectiveType) {
- DirectiveType type = GetDirectiveType("content-security-policy");
- EXPECT_EQ(type, DirectiveType::kContentSecurityPolicy);
-
- type = GetDirectiveType("asdf");
- EXPECT_EQ(type, DirectiveType::kUnknown);
-}
-
-TEST_F(OriginManifestParserTest, GetCSPDisposition) {
- blink::OriginManifest::ContentSecurityPolicyType type =
- GetCSPDisposition("enforce");
- EXPECT_EQ(type, blink::OriginManifest::ContentSecurityPolicyType::kEnforce);
-
- type = GetCSPDisposition("report-only");
- EXPECT_EQ(type, blink::OriginManifest::ContentSecurityPolicyType::kReport);
-
- type = GetCSPDisposition("");
- EXPECT_EQ(type, blink::OriginManifest::ContentSecurityPolicyType::kEnforce);
-
- type = GetCSPDisposition("asdf");
- EXPECT_EQ(type, blink::OriginManifest::ContentSecurityPolicyType::kEnforce);
-}
-
-TEST_F(OriginManifestParserTest, GetCSPActivationType) {
- // the function returns the right values
- EXPECT_EQ(GetCSPActivationType(true),
- blink::OriginManifest::ActivationType::kBaseline);
- EXPECT_EQ(GetCSPActivationType(false),
- blink::OriginManifest::ActivationType::kFallback);
-
- // check different manifest values in JSON
- struct TestCase {
- std::string value;
- unsigned long expected_baseline_only_size;
- unsigned long expected_include_fallbacks_size;
- } tests[]{
- {"true", 1, 1}, {"false", 0, 1}, {"42", 0, 1},
- };
-
- for (auto test : tests) {
- std::ostringstream str_stream;
- str_stream << "{ \"content-security-policy\": [ {"
- << " \"allow-override\": " << test.value << ", "
- << "}, ] }";
-
- std::unique_ptr<blink::OriginManifest> om = Parse(str_stream.str());
- // more details are checked in origin manifest unit tests
- EXPECT_EQ(om->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kBaselineOnly)
- .size(),
- test.expected_baseline_only_size);
- EXPECT_EQ(
- om->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks)
- .size(),
- test.expected_include_fallbacks_size);
- }
-}
-
-TEST_F(OriginManifestParserTest, ParseContentSecurityPolicy) {
- // Wrong structure
- blink::OriginManifest om;
- base::Value dict(base::Value::Type::DICTIONARY);
- ParseContentSecurityPolicy(&om, std::move(dict));
- EXPECT_EQ(om.GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks)
- .size(),
- 0ul);
-
- // empty list
- om = blink::OriginManifest();
- base::Value list(base::Value::Type::LIST);
- ParseContentSecurityPolicy(&om, std::move(list));
- EXPECT_EQ(om.GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks)
- .size(),
- 0ul);
-
- // list with completely unexpected element
- om = blink::OriginManifest();
- list = base::Value(base::Value::Type::LIST);
- list.GetList().push_back(base::Value(42));
- ParseContentSecurityPolicy(&om, std::move(list));
- EXPECT_EQ(om.GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks)
- .size(),
- 0ul);
-
- // list with 1 valid, 2 invalid CSPs -> 3 policies (we don't validate CSPs)
- om = blink::OriginManifest();
- list = base::Value(base::Value::Type::LIST);
-
- std::string policy0 = "default-src 'none'";
- std::string policy1 = "";
- std::string policy2 = "asdf";
-
- base::Value csp0(base::Value::Type::DICTIONARY);
- csp0.SetKey("policy", base::Value(policy0));
- csp0.SetKey("disposition", base::Value("report-only"));
- csp0.SetKey("allow-override", base::Value(true));
- list.GetList().push_back(std::move(csp0));
-
- base::Value csp1(base::Value::Type::DICTIONARY);
- csp1.SetKey("policy", base::Value(policy1));
- csp1.SetKey("disposition", base::Value(23));
- csp1.SetKey("allow-override", base::Value(42));
- list.GetList().push_back(std::move(csp1));
-
- base::Value csp2(base::Value::Type::DICTIONARY);
- csp2.SetKey("policy", base::Value(policy2));
- list.GetList().push_back(std::move(csp2));
-
- ParseContentSecurityPolicy(&om, std::move(list));
-
- std::vector<blink::OriginManifest::ContentSecurityPolicy> baseline =
- om.GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kBaselineOnly);
- ASSERT_EQ(baseline.size(), 1ul);
- EXPECT_TRUE(baseline[0].policy == policy0);
-
- // we know that every CSP s a dictionary and has a unique policy here.
- std::vector<blink::OriginManifest::ContentSecurityPolicy> baseline_fallback =
- om.GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks);
- ASSERT_EQ(baseline_fallback.size(), 3ul);
- std::vector<blink::OriginManifest::ContentSecurityPolicy>::iterator it;
- for (it = baseline_fallback.begin(); it != baseline_fallback.end(); ++it) {
- if (it->policy == policy0)
- break;
- }
- ASSERT_FALSE(it == baseline_fallback.end());
- baseline_fallback.erase(it);
- if (baseline_fallback[0].policy == policy1)
- EXPECT_TRUE(baseline_fallback[1].policy == policy2);
- else
- EXPECT_TRUE(baseline_fallback[0].policy == policy1);
-}
-
-TEST_F(OriginManifestParserTest, CaseSensitiveKeys) {
- struct TestCase {
- std::string policy;
- std::string expected_equivalent_policy;
- } tests[]{
- {"{ \"Content-Security-Policy\": [{ \"policy\": \"asdf\"}] }", "{}"},
- {"{ \"content-security-policy\": [{ \"PoLiCy\": \"asdf\"}] }",
- "{ \"content-security-policy\": [{}] }"},
- {"{ \"content-security-policy\": [{ \"DiSpOsItIoN\": \"enforce\" }] }",
- "{ \"content-security-policy\": [{}] }"},
- {"{ \"content-security-policy\": [{ \"disposition\": \"EnFoRcE\" }] }",
- "{ \"content-security-policy\": [{}] }"},
- {"{ \"content-security-policy\": [{ \"disposition\": \"RePoRt-OnLy\" }] "
- "}",
- "{ \"content-security-policy\": [{}] }"},
- {"{ \"content-security-policy\": [{ \"AlLoW-OvErRiDe\": true }] }",
- "{ \"content-security-policy\": [{}] }"},
- };
-
- for (const auto& test : tests) {
- std::unique_ptr<blink::OriginManifest> bad_case = Parse(test.policy);
- std::unique_ptr<blink::OriginManifest> expected =
- Parse(test.expected_equivalent_policy);
-
- ASSERT_TRUE(bad_case.get() != nullptr);
- ASSERT_TRUE(expected.get() != nullptr);
-
- std::vector<blink::OriginManifest::ContentSecurityPolicy> bad_case_csps =
- bad_case->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks);
- std::vector<blink::OriginManifest::ContentSecurityPolicy> expected_csps =
- expected->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks);
-
- ASSERT_EQ(bad_case_csps.size(), expected_csps.size());
-
- for (unsigned long i = 0; i < bad_case_csps.size(); ++i) {
- EXPECT_EQ(bad_case_csps[i].policy, expected_csps[i].policy);
- EXPECT_EQ(bad_case_csps[i].disposition, expected_csps[i].disposition);
- }
- }
-}
-
-TEST_F(OriginManifestParserTest, MultiDefinitions) {
- struct TestCase {
- std::string policy;
- std::string expected_equivalent_policy;
- } tests[]{
- {"{ \"content-security-policy\": [{ \"policy\": \"first\"}], "
- " \"content-security-policy\": [{ \"policy\": \"second\"}] }",
- "{ \"content-security-policy\": [{ \"policy\": \"second\"}] }"},
-
- {"{ \"content-security-policy\": [{ \"policy\": \"first\", \"policy\": "
- "\"second\"}] }",
- "{ \"content-security-policy\": [{ \"policy\": \"second\"}] }"},
- };
-
- for (const auto& test : tests) {
- std::unique_ptr<blink::OriginManifest> multi = Parse(test.policy);
- std::unique_ptr<blink::OriginManifest> expected =
- Parse(test.expected_equivalent_policy);
-
- ASSERT_TRUE(multi.get() != nullptr);
- ASSERT_TRUE(expected.get() != nullptr);
-
- std::vector<blink::OriginManifest::ContentSecurityPolicy> multi_csps =
- multi->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks);
- std::vector<blink::OriginManifest::ContentSecurityPolicy> expected_csps =
- expected->GetContentSecurityPolicies(
- blink::OriginManifest::FallbackDisposition::kIncludeFallbacks);
-
- ASSERT_EQ(multi_csps.size(), expected_csps.size());
-
- for (unsigned long i = 0; i < multi_csps.size(); ++i) {
- EXPECT_EQ(multi_csps[i].policy, expected_csps[i].policy);
- EXPECT_EQ(multi_csps[i].disposition, expected_csps[i].disposition);
- }
- }
-}
-
-} // namespace origin_manifest_parser
-} // namespace content
diff --git a/chromium/content/browser/payments/payment_app_browsertest.cc b/chromium/content/browser/payments/payment_app_browsertest.cc
index bd35aa9b848..0c837e8f51b 100644
--- a/chromium/content/browser/payments/payment_app_browsertest.cc
+++ b/chromium/content/browser/payments/payment_app_browsertest.cc
@@ -183,7 +183,7 @@ class PaymentAppBrowserTest : public ContentBrowserTest {
event_data->payment_request_origin = GURL("https://example.com");
event_data->method_data.push_back(PaymentMethodData::New());
- event_data->method_data[0]->supported_methods = {supported_method};
+ event_data->method_data[0]->supported_method = supported_method;
PaymentDetailsModifierPtr modifier = PaymentDetailsModifier::New();
modifier->total = PaymentItem::New();
@@ -191,7 +191,7 @@ class PaymentAppBrowserTest : public ContentBrowserTest {
modifier->total->amount->currency = "USD";
modifier->total->amount->value = "55";
modifier->method_data = PaymentMethodData::New();
- modifier->method_data->supported_methods = {supported_method};
+ modifier->method_data->supported_method = supported_method;
event_data->modifiers.push_back(std::move(modifier));
return event_data;
@@ -209,7 +209,7 @@ class PaymentAppBrowserTest : public ContentBrowserTest {
event_data->payment_request_id = "payment-request-id";
event_data->method_data.push_back(PaymentMethodData::New());
- event_data->method_data[0]->supported_methods = {supported_method};
+ event_data->method_data[0]->supported_method = supported_method;
event_data->total = PaymentCurrencyAmount::New();
event_data->total->currency = "USD";
@@ -221,7 +221,7 @@ class PaymentAppBrowserTest : public ContentBrowserTest {
modifier->total->amount->currency = "USD";
modifier->total->amount->value = "55";
modifier->method_data = PaymentMethodData::New();
- modifier->method_data->supported_methods = {supported_method};
+ modifier->method_data->supported_method = supported_method;
event_data->modifiers.push_back(std::move(modifier));
event_data->instrument_key = instrument_key;
@@ -275,10 +275,10 @@ IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, CanMakePayment) {
EXPECT_EQ("https://example.com/", PopConsoleString() /* topOrigin */);
EXPECT_EQ("https://example.com/",
PopConsoleString() /* paymentRequestOrigin */);
- EXPECT_EQ("[{\"supportedMethods\":[\"basic-card\"]}]",
+ EXPECT_EQ("[{\"supportedMethods\":\"basic-card\"}]",
PopConsoleString() /* methodData */);
EXPECT_EQ(
- "[{\"additionalDisplayItems\":[],\"supportedMethods\":[\"basic-card\"],"
+ "[{\"additionalDisplayItems\":[],\"supportedMethods\":\"basic-card\","
"\"total\":{\"amount\":{\"currency\":\"USD\","
"\"value\":\"55\"},\"label\":\"\",\"pending\":false}}"
"]",
@@ -320,14 +320,14 @@ IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, PaymentAppInvocation) {
EXPECT_EQ("https://example.com/",
PopConsoleString() /* paymentRequestOrigin */);
EXPECT_EQ("payment-request-id", PopConsoleString() /* paymentRequestId */);
- EXPECT_EQ("[{\"supportedMethods\":[\"basic-card\"]}]",
+ EXPECT_EQ("[{\"supportedMethods\":\"basic-card\"}]",
PopConsoleString() /* methodData */);
EXPECT_EQ(
"{\"currency\":\"USD\","
"\"value\":\"55\"}",
PopConsoleString() /* total */);
EXPECT_EQ(
- "[{\"additionalDisplayItems\":[],\"supportedMethods\":[\"basic-card\"],"
+ "[{\"additionalDisplayItems\":[],\"supportedMethods\":\"basic-card\","
"\"total\":{\"amount\":{\"currency\":\"USD\","
"\"value\":\"55\"},\"label\":\"\",\"pending\":false}}"
"]",
@@ -357,13 +357,13 @@ IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, PaymentAppOpenWindowFailed) {
EXPECT_EQ("https://example.com/",
PopConsoleString() /* paymentRequestOrigin */);
EXPECT_EQ("payment-request-id", PopConsoleString() /* paymentRequestId */);
- EXPECT_EQ("[{\"supportedMethods\":[\"https://bobpay.com\"]}]",
+ EXPECT_EQ("[{\"supportedMethods\":\"https://bobpay.com\"}]",
PopConsoleString() /* methodData */);
EXPECT_EQ("{\"currency\":\"USD\",\"value\":\"55\"}",
PopConsoleString() /* total */);
EXPECT_EQ(
- "[{\"additionalDisplayItems\":[],\"supportedMethods\":[\"https://"
- "bobpay.com\"],"
+ "[{\"additionalDisplayItems\":[],\"supportedMethods\":\"https://"
+ "bobpay.com\","
"\"total\":{\"amount\":{\"currency\":\"USD\","
"\"value\":\"55\"},\"label\":\"\",\"pending\":false}}"
"]",
diff --git a/chromium/content/browser/payments/payment_app_content_unittest_base.cc b/chromium/content/browser/payments/payment_app_content_unittest_base.cc
index 35732115848..d604c1992fa 100644
--- a/chromium/content/browser/payments/payment_app_content_unittest_base.cc
+++ b/chromium/content/browser/payments/payment_app_content_unittest_base.cc
@@ -15,12 +15,12 @@
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/storage_partition_impl.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "mojo/public/cpp/bindings/interface_request.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace content {
@@ -29,17 +29,19 @@ namespace {
void RegisterServiceWorkerCallback(bool* called,
int64_t* out_registration_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
- EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
*called = true;
*out_registration_id = registration_id;
}
void UnregisterServiceWorkerCallback(bool* called,
- ServiceWorkerStatusCode status) {
- EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+ blink::ServiceWorkerStatusCode status) {
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
*called = true;
}
@@ -64,7 +66,7 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
const GURL& scope,
const GURL& script_url,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -76,7 +78,7 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
last_sw_scope_ = scope;
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id, service_worker_version_id, scope, script_url,
- pause_after_download, std::move(dispatcher_request),
+ pause_after_download, std::move(service_worker_request),
std::move(controller_request), std::move(instance_host),
std::move(provider_info), std::move(installed_scripts_info));
}
@@ -84,8 +86,8 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
void OnPaymentRequestEvent(
payments::mojom::PaymentRequestEventDataPtr event_data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchPaymentRequestEventCallback
- callback) override {
+ mojom::ServiceWorker::DispatchPaymentRequestEventCallback callback)
+ override {
if (respond_payment_request_immediately) {
EmbeddedWorkerTestHelper::OnPaymentRequestEvent(
std::move(event_data), std::move(response_callback),
@@ -100,8 +102,8 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
void OnCanMakePaymentEvent(
payments::mojom::CanMakePaymentEventDataPtr event_data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
- callback) override {
+ mojom::ServiceWorker::DispatchCanMakePaymentEventCallback callback)
+ override {
EmbeddedWorkerTestHelper::OnCanMakePaymentEvent(
std::move(event_data), std::move(response_callback),
std::move(callback));
@@ -109,8 +111,8 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
void OnAbortPaymentEvent(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
- callback) override {
+ mojom::ServiceWorker::DispatchCanMakePaymentEventCallback callback)
+ override {
EmbeddedWorkerTestHelper::OnAbortPaymentEvent(std::move(response_callback),
std::move(callback));
}
diff --git a/chromium/content/browser/payments/payment_app_database.cc b/chromium/content/browser/payments/payment_app_database.cc
index 664e105455e..924d36591cc 100644
--- a/chromium/content/browser/payments/payment_app_database.cc
+++ b/chromium/content/browser/payments/payment_app_database.cc
@@ -71,7 +71,7 @@ PaymentInstrumentPtr ToPaymentInstrumentForMojo(const std::string& input) {
PaymentInstrumentPtr instrument = PaymentInstrument::New();
instrument->name = instrument_proto.name();
for (const auto& icon_proto : instrument_proto.icons()) {
- blink::Manifest::Icon icon;
+ blink::Manifest::ImageResource icon;
icon.src = GURL(icon_proto.src());
icon.type = base::UTF8ToUTF16(icon_proto.type());
for (const auto& size_proto : icon_proto.sizes()) {
@@ -197,7 +197,7 @@ void PaymentAppDatabase::WritePaymentInstrument(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (instrument->icons.size() > 0) {
- std::vector<blink::Manifest::Icon> icons(instrument->icons);
+ std::vector<blink::Manifest::ImageResource> icons(instrument->icons);
PaymentInstrumentIconFetcher::Start(
scope, service_worker_context_->GetProviderHostIds(scope.GetOrigin()),
icons,
@@ -264,10 +264,10 @@ void PaymentAppDatabase::FetchPaymentAppInfoCallback(
void PaymentAppDatabase::DidFindRegistrationToUpdatePaymentAppInfo(
FetchAndUpdatePaymentAppInfoCallback callback,
std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
return;
}
@@ -285,9 +285,9 @@ void PaymentAppDatabase::DidGetPaymentAppInfoToUpdatePaymentAppInfo(
std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info,
scoped_refptr<ServiceWorkerRegistration> registration,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
return;
}
@@ -331,14 +331,14 @@ void PaymentAppDatabase::DidGetPaymentAppInfoToUpdatePaymentAppInfo(
void PaymentAppDatabase::DidUpdatePaymentApp(
FetchAndUpdatePaymentAppInfoCallback callback,
bool fetch_app_info_failed,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
PaymentHandlerStatus handler_status =
fetch_app_info_failed
? PaymentHandlerStatus::FETCH_PAYMENT_APP_INFO_FAILED
: PaymentHandlerStatus::SUCCESS;
- handler_status = status == SERVICE_WORKER_OK
+ handler_status = status == blink::ServiceWorkerStatusCode::kOk
? handler_status
: PaymentHandlerStatus::STORAGE_OPERATION_FAILED;
return std::move(callback).Run(handler_status);
@@ -369,10 +369,10 @@ void PaymentAppDatabase::SetPaymentAppUserHint(const GURL& scope,
void PaymentAppDatabase::DidFindRegistrationToSetPaymentAppUserHint(
const std::string& user_hint,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK)
+ if (status != blink::ServiceWorkerStatusCode::kOk)
return;
service_worker_context_->GetRegistrationUserDataByKeyPrefix(
@@ -387,9 +387,9 @@ void PaymentAppDatabase::DidGetPaymentAppInfoToSetUserHint(
int64_t registration_id,
const GURL& pattern,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK)
+ if (status != blink::ServiceWorkerStatusCode::kOk)
return;
DCHECK_LE(data.size(), 1U);
@@ -411,9 +411,9 @@ void PaymentAppDatabase::DidGetPaymentAppInfoToSetUserHint(
}
void PaymentAppDatabase::DidSetPaymentAppUserHint(
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(status == SERVICE_WORKER_OK);
+ DCHECK(status == blink::ServiceWorkerStatusCode::kOk);
}
void PaymentAppDatabase::SetPaymentAppInfoForRegisteredServiceWorker(
@@ -438,11 +438,11 @@ void PaymentAppDatabase::DidFindRegistrationToSetPaymentApp(
const std::string& icon,
const std::string& method,
SetPaymentAppInfoCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
return;
}
@@ -477,10 +477,10 @@ void PaymentAppDatabase::DidWritePaymentAppForSetPaymentApp(
const std::string& method,
SetPaymentAppInfoCallback callback,
scoped_refptr<ServiceWorkerRegistration> registration,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
return;
}
@@ -514,10 +514,10 @@ void PaymentAppDatabase::DidWritePaymentAppForSetPaymentApp(
void PaymentAppDatabase::DidWritePaymentInstrumentForSetPaymentApp(
SetPaymentAppInfoCallback callback,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return std::move(callback).Run(
- status == SERVICE_WORKER_OK
+ status == blink::ServiceWorkerStatusCode::kOk
? PaymentHandlerStatus::SUCCESS
: PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
}
@@ -525,9 +525,9 @@ void PaymentAppDatabase::DidWritePaymentInstrumentForSetPaymentApp(
void PaymentAppDatabase::DidReadAllPaymentApps(
ReadAllPaymentAppsCallback callback,
const std::vector<std::pair<int64_t, std::string>>& raw_data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(PaymentApps());
return;
}
@@ -556,9 +556,9 @@ void PaymentAppDatabase::DidReadAllPaymentInstruments(
PaymentApps apps,
ReadAllPaymentAppsCallback callback,
const std::vector<std::pair<int64_t, std::string>>& raw_data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(std::move(apps));
return;
}
@@ -589,10 +589,10 @@ void PaymentAppDatabase::DidReadAllPaymentInstruments(
void PaymentAppDatabase::DidFindRegistrationToDeletePaymentInstrument(
const std::string& instrument_key,
DeletePaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
return;
}
@@ -609,9 +609,9 @@ void PaymentAppDatabase::DidFindPaymentInstrument(
const std::string& instrument_key,
DeletePaymentInstrumentCallback callback,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK || data.size() != 1) {
+ if (status != blink::ServiceWorkerStatusCode::kOk || data.size() != 1) {
std::move(callback).Run(PaymentHandlerStatus::NOT_FOUND);
return;
}
@@ -626,9 +626,9 @@ void PaymentAppDatabase::DidFindPaymentInstrument(
void PaymentAppDatabase::DidDeletePaymentInstrument(
DeletePaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return std::move(callback).Run(status == SERVICE_WORKER_OK
+ return std::move(callback).Run(status == blink::ServiceWorkerStatusCode::kOk
? PaymentHandlerStatus::SUCCESS
: PaymentHandlerStatus::NOT_FOUND);
}
@@ -636,10 +636,10 @@ void PaymentAppDatabase::DidDeletePaymentInstrument(
void PaymentAppDatabase::DidFindRegistrationToReadPaymentInstrument(
const std::string& instrument_key,
ReadPaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(PaymentInstrument::New(),
PaymentHandlerStatus::NO_ACTIVE_WORKER);
return;
@@ -654,9 +654,9 @@ void PaymentAppDatabase::DidFindRegistrationToReadPaymentInstrument(
void PaymentAppDatabase::DidReadPaymentInstrument(
ReadPaymentInstrumentCallback callback,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK || data.size() != 1) {
+ if (status != blink::ServiceWorkerStatusCode::kOk || data.size() != 1) {
std::move(callback).Run(PaymentInstrument::New(),
PaymentHandlerStatus::NOT_FOUND);
return;
@@ -674,10 +674,10 @@ void PaymentAppDatabase::DidReadPaymentInstrument(
void PaymentAppDatabase::DidFindRegistrationToGetKeys(
KeysOfPaymentInstrumentsCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(std::vector<std::string>(),
PaymentHandlerStatus::NO_ACTIVE_WORKER);
return;
@@ -692,9 +692,9 @@ void PaymentAppDatabase::DidFindRegistrationToGetKeys(
void PaymentAppDatabase::DidGetKeysOfPaymentInstruments(
KeysOfPaymentInstrumentsCallback callback,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(std::vector<std::string>(),
PaymentHandlerStatus::NOT_FOUND);
return;
@@ -711,10 +711,10 @@ void PaymentAppDatabase::DidGetKeysOfPaymentInstruments(
void PaymentAppDatabase::DidFindRegistrationToHasPaymentInstrument(
const std::string& instrument_key,
HasPaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
return;
}
@@ -728,9 +728,9 @@ void PaymentAppDatabase::DidFindRegistrationToHasPaymentInstrument(
void PaymentAppDatabase::DidHasPaymentInstrument(
DeletePaymentInstrumentCallback callback,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK || data.size() != 1) {
+ if (status != blink::ServiceWorkerStatusCode::kOk || data.size() != 1) {
std::move(callback).Run(PaymentHandlerStatus::NOT_FOUND);
return;
}
@@ -743,10 +743,10 @@ void PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument(
PaymentInstrumentPtr instrument,
const std::string& decoded_instrument_icon,
WritePaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
return;
}
@@ -800,10 +800,10 @@ void PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument(
void PaymentAppDatabase::DidWritePaymentInstrument(
WritePaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return std::move(callback).Run(
- status == SERVICE_WORKER_OK
+ status == blink::ServiceWorkerStatusCode::kOk
? PaymentHandlerStatus::SUCCESS
: PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
}
@@ -811,11 +811,11 @@ void PaymentAppDatabase::DidWritePaymentInstrument(
void PaymentAppDatabase::DidFindRegistrationToClearPaymentInstruments(
const GURL& scope,
ClearPaymentInstrumentsCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
return;
}
@@ -857,9 +857,9 @@ void PaymentAppDatabase::DidGetKeysToClearPaymentInstruments(
void PaymentAppDatabase::DidClearPaymentInstruments(
ClearPaymentInstrumentsCallback callback,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return std::move(callback).Run(status == SERVICE_WORKER_OK
+ return std::move(callback).Run(status == blink::ServiceWorkerStatusCode::kOk
? PaymentHandlerStatus::SUCCESS
: PaymentHandlerStatus::NOT_FOUND);
}
diff --git a/chromium/content/browser/payments/payment_app_database.h b/chromium/content/browser/payments/payment_app_database.h
index baca8a422be..07bb2e8c310 100644
--- a/chromium/content/browser/payments/payment_app_database.h
+++ b/chromium/content/browser/payments/payment_app_database.h
@@ -16,9 +16,9 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/common/content_export.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/browser/stored_payment_app.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
namespace content {
@@ -90,55 +90,55 @@ class CONTENT_EXPORT PaymentAppDatabase {
void DidReadAllPaymentApps(
ReadAllPaymentAppsCallback callback,
const std::vector<std::pair<int64_t, std::string>>& raw_data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void DidReadAllPaymentInstruments(
PaymentApps apps,
ReadAllPaymentAppsCallback callback,
const std::vector<std::pair<int64_t, std::string>>& raw_data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// DeletePaymentInstrument callbacks
void DidFindRegistrationToDeletePaymentInstrument(
const std::string& instrument_key,
DeletePaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void DidFindPaymentInstrument(int64_t registration_id,
const std::string& instrument_key,
DeletePaymentInstrumentCallback callback,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void DidDeletePaymentInstrument(DeletePaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// ReadPaymentInstrument callbacks
void DidFindRegistrationToReadPaymentInstrument(
const std::string& instrument_key,
ReadPaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void DidReadPaymentInstrument(ReadPaymentInstrumentCallback callback,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// KeysOfPaymentInstruments callbacks
void DidFindRegistrationToGetKeys(
KeysOfPaymentInstrumentsCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void DidGetKeysOfPaymentInstruments(KeysOfPaymentInstrumentsCallback callback,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// HasPaymentInstrument callbacks
void DidFindRegistrationToHasPaymentInstrument(
const std::string& instrument_key,
HasPaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void DidHasPaymentInstrument(DeletePaymentInstrumentCallback callback,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// WritePaymentInstrument callbacks
void DidFindRegistrationToWritePaymentInstrument(
@@ -146,10 +146,10 @@ class CONTENT_EXPORT PaymentAppDatabase {
payments::mojom::PaymentInstrumentPtr instrument,
const std::string& decoded_instrument_icon,
WritePaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void DidWritePaymentInstrument(WritePaymentInstrumentCallback callback,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// FetchAndUpdatePaymentAppInfo callbacks.
void FetchPaymentAppInfoCallback(
@@ -159,17 +159,17 @@ class CONTENT_EXPORT PaymentAppDatabase {
void DidFindRegistrationToUpdatePaymentAppInfo(
FetchAndUpdatePaymentAppInfoCallback callback,
std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void DidGetPaymentAppInfoToUpdatePaymentAppInfo(
FetchAndUpdatePaymentAppInfoCallback callback,
std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info,
scoped_refptr<ServiceWorkerRegistration> registration,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void DidUpdatePaymentApp(FetchAndUpdatePaymentAppInfoCallback callback,
bool fetch_app_info_failed,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// PaymentInstrumentIconFetcherCallback.
void DidFetchedPaymentInstrumentIcon(
@@ -183,7 +183,7 @@ class CONTENT_EXPORT PaymentAppDatabase {
void DidFindRegistrationToClearPaymentInstruments(
const GURL& scope,
ClearPaymentInstrumentsCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void DidGetKeysToClearPaymentInstruments(
scoped_refptr<ServiceWorkerRegistration> registration,
@@ -191,19 +191,19 @@ class CONTENT_EXPORT PaymentAppDatabase {
const std::vector<std::string>& keys,
payments::mojom::PaymentHandlerStatus status);
void DidClearPaymentInstruments(ClearPaymentInstrumentsCallback callback,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// SetPaymentAppUserHint callbacks.
void DidFindRegistrationToSetPaymentAppUserHint(
const std::string& user_hint,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void DidGetPaymentAppInfoToSetUserHint(const std::string& user_hint,
int64_t registration_id,
const GURL& pattern,
const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
- void DidSetPaymentAppUserHint(ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
+ void DidSetPaymentAppUserHint(blink::ServiceWorkerStatusCode status);
// SetPaymentAppInfoForRegisteredServiceWorker callbacks.
void DidFindRegistrationToSetPaymentApp(
@@ -212,17 +212,17 @@ class CONTENT_EXPORT PaymentAppDatabase {
const std::string& icon,
const std::string& method,
SetPaymentAppInfoCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void DidWritePaymentAppForSetPaymentApp(
const std::string& instrument_key,
const std::string& method,
SetPaymentAppInfoCallback callback,
scoped_refptr<ServiceWorkerRegistration> registration,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void DidWritePaymentInstrumentForSetPaymentApp(
SetPaymentAppInfoCallback callback,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
base::WeakPtrFactory<PaymentAppDatabase> weak_ptr_factory_;
diff --git a/chromium/content/browser/payments/payment_app_info_fetcher.cc b/chromium/content/browser/payments/payment_app_info_fetcher.cc
index 7ffe9e44457..5ba89bcdda3 100644
--- a/chromium/content/browser/payments/payment_app_info_fetcher.cc
+++ b/chromium/content/browser/payments/payment_app_info_fetcher.cc
@@ -11,8 +11,8 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/manifest_icon_downloader.h"
-#include "content/public/browser/manifest_icon_selector.h"
#include "content/public/common/console_message_level.h"
+#include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
#include "ui/gfx/image/image.h"
#include "url/origin.h"
@@ -209,9 +209,9 @@ void PaymentAppInfoFetcher::SelfDeleteFetcher::FetchPaymentAppManifestCallback(
return;
}
- icon_url_ = ManifestIconSelector::FindBestMatchingIcon(
+ icon_url_ = blink::ManifestIconSelector::FindBestMatchingIcon(
manifest.icons, kPaymentAppIdealIconSize, kPaymentAppMinimumIconSize,
- blink::Manifest::Icon::ANY);
+ blink::Manifest::ImageResource::Purpose::ANY);
if (!icon_url_.is_valid()) {
WarnIfPossible(
"No suitable payment handler icon found in the \"icons\" field defined "
@@ -233,7 +233,7 @@ void PaymentAppInfoFetcher::SelfDeleteFetcher::FetchPaymentAppManifestCallback(
return;
}
- bool can_download = content::ManifestIconDownloader::Download(
+ bool can_download = ManifestIconDownloader::Download(
web_contents_helper_->web_contents(), icon_url_, kPaymentAppIdealIconSize,
kPaymentAppMinimumIconSize,
base::Bind(&PaymentAppInfoFetcher::SelfDeleteFetcher::OnIconFetched,
diff --git a/chromium/content/browser/payments/payment_app_provider_impl.cc b/chromium/content/browser/payments/payment_app_provider_impl.cc
index db44e03f061..3cfa0bde2bc 100644
--- a/chromium/content/browser/payments/payment_app_provider_impl.cc
+++ b/chromium/content/browser/payments/payment_app_provider_impl.cc
@@ -12,14 +12,14 @@
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/storage_partition_impl.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/permission_manager.h"
+#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "mojo/public/mojom/base/time.mojom.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -30,7 +30,7 @@ namespace {
using ServiceWorkerStartCallback =
base::OnceCallback<void(scoped_refptr<ServiceWorkerVersion>,
- ServiceWorkerStatusCode)>;
+ blink::ServiceWorkerStatusCode)>;
class RespondWithCallbacks;
@@ -163,9 +163,9 @@ class RespondWithCallbacks
delete this;
}
- void OnErrorStatus(ServiceWorkerStatusCode service_worker_status) {
+ void OnErrorStatus(blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(service_worker_status != SERVICE_WORKER_OK);
+ DCHECK(service_worker_status != blink::ServiceWorkerStatusCode::kOk);
if (event_type_ == ServiceWorkerMetrics::EventType::PAYMENT_REQUEST) {
BrowserThread::PostTask(
@@ -194,7 +194,7 @@ class RespondWithCallbacks
service_worker_version_->FinishRequest(request_id_, false,
base::Time::Now());
- OnErrorStatus(SERVICE_WORKER_ERROR_ABORT);
+ OnErrorStatus(blink::ServiceWorkerStatusCode::kErrorAbort);
}
private:
@@ -249,10 +249,10 @@ void DispatchAbortPaymentEvent(
BrowserContext* browser_context,
PaymentAppProvider::PaymentEventResultCallback callback,
scoped_refptr<ServiceWorkerVersion> active_version,
- ServiceWorkerStatusCode service_worker_status) {
+ blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (service_worker_status != SERVICE_WORKER_OK) {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(callback), false));
return;
@@ -268,8 +268,7 @@ void DispatchAbortPaymentEvent(
browser_context, ServiceWorkerMetrics::EventType::ABORT_PAYMENT,
active_version, std::move(callback));
- active_version->event_dispatcher()->DispatchAbortPaymentEvent(
- invocation_callbacks->request_id(),
+ active_version->endpoint()->DispatchAbortPaymentEvent(
invocation_callbacks->CreateInterfacePtrAndBind(),
active_version->CreateSimpleEventCallback(event_finish_id));
}
@@ -279,10 +278,10 @@ void DispatchCanMakePaymentEvent(
payments::mojom::CanMakePaymentEventDataPtr event_data,
PaymentAppProvider::PaymentEventResultCallback callback,
scoped_refptr<ServiceWorkerVersion> active_version,
- ServiceWorkerStatusCode service_worker_status) {
+ blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (service_worker_status != SERVICE_WORKER_OK) {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(callback), false));
return;
@@ -298,9 +297,8 @@ void DispatchCanMakePaymentEvent(
browser_context, ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT,
active_version, std::move(callback));
- active_version->event_dispatcher()->DispatchCanMakePaymentEvent(
- invocation_callbacks->request_id(), std::move(event_data),
- invocation_callbacks->CreateInterfacePtrAndBind(),
+ active_version->endpoint()->DispatchCanMakePaymentEvent(
+ std::move(event_data), invocation_callbacks->CreateInterfacePtrAndBind(),
active_version->CreateSimpleEventCallback(event_finish_id));
}
@@ -309,10 +307,10 @@ void DispatchPaymentRequestEvent(
payments::mojom::PaymentRequestEventDataPtr event_data,
PaymentAppProvider::InvokePaymentAppCallback callback,
scoped_refptr<ServiceWorkerVersion> active_version,
- ServiceWorkerStatusCode service_worker_status) {
+ blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (service_worker_status != SERVICE_WORKER_OK) {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(callback),
@@ -330,19 +328,18 @@ void DispatchPaymentRequestEvent(
browser_context, ServiceWorkerMetrics::EventType::PAYMENT_REQUEST,
active_version, std::move(callback));
- active_version->event_dispatcher()->DispatchPaymentRequestEvent(
- invocation_callbacks->request_id(), std::move(event_data),
- invocation_callbacks->CreateInterfacePtrAndBind(),
+ active_version->endpoint()->DispatchPaymentRequestEvent(
+ std::move(event_data), invocation_callbacks->CreateInterfacePtrAndBind(),
active_version->CreateSimpleEventCallback(event_finish_id));
}
void DidFindRegistrationOnIO(
ServiceWorkerStartCallback callback,
- ServiceWorkerStatusCode service_worker_status,
+ blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (service_worker_status != SERVICE_WORKER_OK) {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(nullptr, service_worker_status);
return;
}
@@ -404,18 +401,15 @@ void CheckPermissionForPaymentApps(
PaymentAppProvider::PaymentApps apps) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- PermissionManager* permission_manager =
- browser_context->GetPermissionManager();
- if (!permission_manager) {
- std::move(callback).Run(PaymentAppProvider::PaymentApps());
- return;
- }
+ PermissionController* permission_controller =
+ BrowserContext::GetPermissionController(browser_context);
+ DCHECK(permission_controller);
PaymentAppProvider::PaymentApps permitted_apps;
for (auto& app : apps) {
GURL origin = app.second->scope.GetOrigin();
- if (permission_manager->GetPermissionStatus(PermissionType::PAYMENT_HANDLER,
- origin, origin) ==
+ if (permission_controller->GetPermissionStatus(
+ PermissionType::PAYMENT_HANDLER, origin, origin) ==
blink::mojom::PermissionStatus::GRANTED) {
permitted_apps[app.first] = std::move(app.second);
}
@@ -581,13 +575,15 @@ bool PaymentAppProviderImpl::IsValidInstallablePaymentApp(
DCHECK(manifest_url.is_valid() && sw_js_url.is_valid() &&
sw_scope.is_valid());
- // TODO(crbug.com/853924): Unify duplicated code between here and
- // ServiceWorkerProviderHost::IsValidRegisterMessage.
- if (ServiceWorkerUtils::ContainsDisallowedCharacter(sw_js_url, sw_scope,
- error_message)) {
+ // Scope will be checked against service worker js url when registering, but
+ // we check it here earlier to avoid presenting unusable payment handlers.
+ if (!ServiceWorkerUtils::IsPathRestrictionSatisfiedWithoutHeader(
+ sw_scope, sw_js_url, error_message)) {
return false;
}
+ // TODO(crbug.com/855312): Unify duplicated code between here and
+ // ServiceWorkerProviderHost::IsValidRegisterMessage.
std::vector<GURL> urls = {manifest_url, sw_js_url, sw_scope};
if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
*error_message =
diff --git a/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc b/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
index 6143488d152..4ed0f9bb1ad 100644
--- a/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
+++ b/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
@@ -65,7 +65,7 @@ class PaymentAppProviderTest : public PaymentAppContentUnitTestBase {
.WillByDefault(
testing::Return(blink::mojom::PermissionStatus::GRANTED));
static_cast<TestBrowserContext*>(browser_context())
- ->SetPermissionManager(std::move(mock_permission_manager));
+ ->SetPermissionControllerDelegate(std::move(mock_permission_manager));
}
~PaymentAppProviderTest() override {}
@@ -159,7 +159,7 @@ TEST_F(PaymentAppProviderTest, CanMakePaymentTest) {
payments::mojom::CanMakePaymentEventData::New();
payments::mojom::PaymentMethodDataPtr methodData =
payments::mojom::PaymentMethodData::New();
- methodData->supported_methods.push_back("test-method");
+ methodData->supported_method = "test-method";
event_data->method_data.push_back(std::move(methodData));
bool can_make_payment = false;
diff --git a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
index bfcb804f5d0..8ef0de4e991 100644
--- a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
+++ b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
@@ -11,7 +11,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/manifest_icon_downloader.h"
-#include "content/public/browser/manifest_icon_selector.h"
+#include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/image/image.h"
@@ -28,13 +28,13 @@ const int kPaymentAppMinimumIconSize = 0;
void DownloadBestMatchingIcon(
WebContents* web_contents,
- const std::vector<blink::Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::ImageResource>& icons,
PaymentInstrumentIconFetcher::PaymentInstrumentIconFetcherCallback
callback);
void OnIconFetched(
WebContents* web_contents,
- const std::vector<blink::Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::ImageResource>& icons,
PaymentInstrumentIconFetcher::PaymentInstrumentIconFetcherCallback callback,
const SkBitmap& bitmap) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -64,14 +64,14 @@ void OnIconFetched(
void DownloadBestMatchingIcon(
WebContents* web_contents,
- const std::vector<blink::Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::ImageResource>& icons,
PaymentInstrumentIconFetcher::PaymentInstrumentIconFetcherCallback
callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- GURL icon_url = ManifestIconSelector::FindBestMatchingIcon(
+ GURL icon_url = blink::ManifestIconSelector::FindBestMatchingIcon(
icons, kPaymentAppIdealIconSize, kPaymentAppMinimumIconSize,
- blink::Manifest::Icon::IconPurpose::ANY);
+ blink::Manifest::ImageResource::Purpose::ANY);
if (web_contents == nullptr || !icon_url.is_valid()) {
// If the icon url is invalid, it's better to give the information to
// developers in advance unlike when fetching or decoding fails. We already
@@ -82,7 +82,7 @@ void DownloadBestMatchingIcon(
return;
}
- std::vector<blink::Manifest::Icon> copy_icons;
+ std::vector<blink::Manifest::ImageResource> copy_icons;
for (const auto& icon : icons) {
if (icon.src != icon_url) {
copy_icons.emplace_back(icon);
@@ -123,7 +123,7 @@ WebContents* GetWebContentsFromProviderHostIds(
void StartOnUI(
const GURL& scope,
std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts,
- const std::vector<blink::Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::ImageResource>& icons,
PaymentInstrumentIconFetcher::PaymentInstrumentIconFetcherCallback
callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -139,7 +139,7 @@ void StartOnUI(
void PaymentInstrumentIconFetcher::Start(
const GURL& scope,
std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts,
- const std::vector<blink::Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::ImageResource>& icons,
PaymentInstrumentIconFetcherCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chromium/content/browser/payments/payment_instrument_icon_fetcher.h b/chromium/content/browser/payments/payment_instrument_icon_fetcher.h
index e3c5f8e608d..c31d531fcc7 100644
--- a/chromium/content/browser/payments/payment_instrument_icon_fetcher.h
+++ b/chromium/content/browser/payments/payment_instrument_icon_fetcher.h
@@ -25,7 +25,7 @@ class PaymentInstrumentIconFetcher {
static void Start(
const GURL& scope,
std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts,
- const std::vector<blink::Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::ImageResource>& icons,
PaymentInstrumentIconFetcherCallback callback);
private:
diff --git a/chromium/content/browser/performance_memory_browsertest.cc b/chromium/content/browser/performance_memory_browsertest.cc
new file mode 100644
index 00000000000..f4872b252b3
--- /dev/null
+++ b/chromium/content/browser/performance_memory_browsertest.cc
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/web_contents.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/test/content_browser_test_utils_internal.h"
+#include "net/dns/mock_host_resolver.h"
+
+namespace content {
+
+class PerformanceMemoryBrowserTest : public ContentBrowserTest {
+ public:
+ PerformanceMemoryBrowserTest() {}
+
+ protected:
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+};
+
+// Verify that performance.memory is not bucketized when sites are isolated for
+// testing, and that it is bucketized when they are not.
+IN_PROC_BROWSER_TEST_F(PerformanceMemoryBrowserTest, PerformanceMemory) {
+ GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ WebContents* contents = shell()->web_contents();
+ FrameTreeNode* root =
+ static_cast<WebContentsImpl*>(contents)->GetFrameTree()->root();
+ int usedJSHeapSize = -1;
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(
+ root,
+ "window.domAutomationController.send(performance.memory.usedJSHeapSize);",
+ &usedJSHeapSize));
+
+ EXPECT_GE(usedJSHeapSize, 0);
+ // There is no explicit way to check if the memory values are bucketized or
+ // not. As in third_party/blink/renderer/core/timing/memory_info_test.cc,
+ // check that the value mod 100000 is non-zero to verify that it is
+ // not bucketized. This should be the case when the renderer process is locked
+ // to a site (i.e. scheme plus eTLD+1).
+ if (AreAllSitesIsolatedForTesting())
+ EXPECT_NE(0, usedJSHeapSize % 100000);
+ else
+ EXPECT_EQ(0, usedJSHeapSize % 100000);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/permissions/permission_controller_impl.cc b/chromium/content/browser/permissions/permission_controller_impl.cc
new file mode 100644
index 00000000000..75ccdf0efb4
--- /dev/null
+++ b/chromium/content/browser/permissions/permission_controller_impl.cc
@@ -0,0 +1,126 @@
+// Copyright 2018 The Chromium Authors. All 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_PERMISSIONS_PERMISSION_CONTROLLER_IMPL_CC_
+#define CONTENT_BROWSER_PERMISSIONS_PERMISSION_CONTROLLER_IMPL_CC_
+
+#include "content/browser/permissions/permission_controller_impl.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/permission_controller_delegate.h"
+#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
+
+class GURL;
+
+namespace content {
+
+PermissionControllerImpl::PermissionControllerImpl(
+ BrowserContext* browser_context)
+ : browser_context_(browser_context) {}
+
+// static
+PermissionControllerImpl* PermissionControllerImpl::FromBrowserContext(
+ BrowserContext* browser_context) {
+ return static_cast<PermissionControllerImpl*>(
+ BrowserContext::GetPermissionController(browser_context));
+}
+
+PermissionControllerImpl::~PermissionControllerImpl() = default;
+
+int PermissionControllerImpl::RequestPermission(
+ PermissionType permission,
+ RenderFrameHost* render_frame_host,
+ const GURL& requesting_origin,
+ bool user_gesture,
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback) {
+ PermissionControllerDelegate* delegate =
+ browser_context_->GetPermissionControllerDelegate();
+ if (!delegate) {
+ callback.Run(blink::mojom::PermissionStatus::DENIED);
+ return kNoPendingOperation;
+ }
+ return delegate->RequestPermission(permission, render_frame_host,
+ requesting_origin, user_gesture, callback);
+}
+
+int PermissionControllerImpl::RequestPermissions(
+ const std::vector<PermissionType>& permissions,
+ RenderFrameHost* render_frame_host,
+ const GURL& requesting_origin,
+ bool user_gesture,
+ const base::Callback<
+ void(const std::vector<blink::mojom::PermissionStatus>&)>& callback) {
+ PermissionControllerDelegate* delegate =
+ browser_context_->GetPermissionControllerDelegate();
+ if (!delegate) {
+ std::vector<blink::mojom::PermissionStatus> result(
+ permissions.size(), blink::mojom::PermissionStatus::DENIED);
+ callback.Run(result);
+ return kNoPendingOperation;
+ }
+ return delegate->RequestPermissions(permissions, render_frame_host,
+ requesting_origin, user_gesture,
+ callback);
+}
+
+blink::mojom::PermissionStatus PermissionControllerImpl::GetPermissionStatus(
+ PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin) {
+ PermissionControllerDelegate* delegate =
+ browser_context_->GetPermissionControllerDelegate();
+ if (!delegate)
+ return blink::mojom::PermissionStatus::DENIED;
+ return delegate->GetPermissionStatus(permission, requesting_origin,
+ embedding_origin);
+}
+
+blink::mojom::PermissionStatus
+PermissionControllerImpl::GetPermissionStatusForFrame(
+ PermissionType permission,
+ RenderFrameHost* render_frame_host,
+ const GURL& requesting_origin) {
+ PermissionControllerDelegate* delegate =
+ browser_context_->GetPermissionControllerDelegate();
+ if (!delegate)
+ return blink::mojom::PermissionStatus::DENIED;
+ return delegate->GetPermissionStatusForFrame(permission, render_frame_host,
+ requesting_origin);
+}
+
+void PermissionControllerImpl::ResetPermission(PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin) {
+ PermissionControllerDelegate* delegate =
+ browser_context_->GetPermissionControllerDelegate();
+ if (!delegate)
+ return;
+ delegate->ResetPermission(permission, requesting_origin, embedding_origin);
+}
+
+int PermissionControllerImpl::SubscribePermissionStatusChange(
+ PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin,
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback) {
+ PermissionControllerDelegate* delegate =
+ browser_context_->GetPermissionControllerDelegate();
+ if (!delegate)
+ return kNoPendingOperation;
+ return delegate->SubscribePermissionStatusChange(
+ permission, requesting_origin, embedding_origin, callback);
+}
+
+void PermissionControllerImpl::UnsubscribePermissionStatusChange(
+ int subscription_id) {
+ PermissionControllerDelegate* delegate =
+ browser_context_->GetPermissionControllerDelegate();
+ if (!delegate)
+ return;
+ delegate->UnsubscribePermissionStatusChange(subscription_id);
+}
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PERMISSIONS_PERMISSION_CONTROLLER_IMPL_CC_
diff --git a/chromium/content/browser/permissions/permission_controller_impl.h b/chromium/content/browser/permissions/permission_controller_impl.h
new file mode 100644
index 00000000000..460f033513a
--- /dev/null
+++ b/chromium/content/browser/permissions/permission_controller_impl.h
@@ -0,0 +1,72 @@
+// Copyright 2018 The Chromium Authors. All 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_PERMISSIONS_PERMISSION_CONTROLLER_IMPL_H_
+#define CONTENT_BROWSER_PERMISSIONS_PERMISSION_CONTROLLER_IMPL_H_
+
+#include "content/common/content_export.h"
+#include "content/public/browser/permission_controller.h"
+
+namespace content {
+
+class BrowserContext;
+
+// Implementation of the PermissionController interface. This
+// is used by content/ layer to manage permissions.
+// There is one instance of this class per BrowserContext.
+class CONTENT_EXPORT PermissionControllerImpl : public PermissionController {
+ public:
+ explicit PermissionControllerImpl(BrowserContext* browser_context);
+ ~PermissionControllerImpl() override;
+
+ static PermissionControllerImpl* FromBrowserContext(
+ BrowserContext* browser_context);
+
+ // PermissionController implementation.
+ blink::mojom::PermissionStatus GetPermissionStatus(
+ PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin) override;
+
+ blink::mojom::PermissionStatus GetPermissionStatusForFrame(
+ PermissionType permission,
+ RenderFrameHost* render_frame_host,
+ const GURL& requesting_origin) override;
+
+ int RequestPermission(
+ PermissionType permission,
+ RenderFrameHost* render_frame_host,
+ const GURL& requesting_origin,
+ bool user_gesture,
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback);
+
+ int RequestPermissions(
+ const std::vector<PermissionType>& permission,
+ RenderFrameHost* render_frame_host,
+ const GURL& requesting_origin,
+ bool user_gesture,
+ const base::Callback<
+ void(const std::vector<blink::mojom::PermissionStatus>&)>& callback);
+
+ void ResetPermission(PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin);
+
+ int SubscribePermissionStatusChange(
+ PermissionType permission,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin,
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback);
+
+ void UnsubscribePermissionStatusChange(int subscription_id);
+
+ private:
+ BrowserContext* browser_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(PermissionControllerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PERMISSIONS_PERMISSION_CONTROLLER_IMPL_H_
diff --git a/chromium/content/browser/permissions/permission_service_context.cc b/chromium/content/browser/permissions/permission_service_context.cc
index e115a1a959d..05cd21bd9ec 100644
--- a/chromium/content/browser/permissions/permission_service_context.cc
+++ b/chromium/content/browser/permissions/permission_service_context.cc
@@ -6,10 +6,11 @@
#include <utility>
+#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/permissions/permission_service_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/permission_manager.h"
+#include "content/public/browser/permission_controller.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
@@ -30,8 +31,8 @@ class PermissionServiceContext::PermissionSubscription {
~PermissionSubscription() {
DCHECK_NE(id_, 0);
BrowserContext* browser_context = context_->GetBrowserContext();
- if (browser_context && browser_context->GetPermissionManager()) {
- browser_context->GetPermissionManager()
+ if (browser_context) {
+ PermissionControllerImpl::FromBrowserContext(browser_context)
->UnsubscribePermissionStatusChange(id_);
}
}
@@ -90,7 +91,7 @@ void PermissionServiceContext::CreateSubscription(
const url::Origin& origin,
PermissionObserverPtr observer) {
BrowserContext* browser_context = GetBrowserContext();
- if (!browser_context || !browser_context->GetPermissionManager())
+ if (!browser_context)
return;
auto subscription =
@@ -98,12 +99,15 @@ void PermissionServiceContext::CreateSubscription(
GURL requesting_origin(origin.Serialize());
GURL embedding_origin = GetEmbeddingOrigin();
int subscription_id =
- browser_context->GetPermissionManager()->SubscribePermissionStatusChange(
- permission_type, requesting_origin,
- // If the embedding_origin is empty, we'll use the |origin| instead.
- embedding_origin.is_empty() ? requesting_origin : embedding_origin,
- base::Bind(&PermissionSubscription::OnPermissionStatusChanged,
- base::Unretained(subscription.get())));
+ PermissionControllerImpl::FromBrowserContext(browser_context)
+ ->SubscribePermissionStatusChange(
+ permission_type, requesting_origin,
+ // If the embedding_origin is empty, we'll use the |origin|
+ // instead.
+ embedding_origin.is_empty() ? requesting_origin
+ : embedding_origin,
+ base::Bind(&PermissionSubscription::OnPermissionStatusChanged,
+ base::Unretained(subscription.get())));
subscription->set_id(subscription_id);
subscriptions_[subscription_id] = std::move(subscription);
}
diff --git a/chromium/content/browser/permissions/permission_service_impl.cc b/chromium/content/browser/permissions/permission_service_impl.cc
index 4c86c799dc9..f84599df41c 100644
--- a/chromium/content/browser/permissions/permission_service_impl.cc
+++ b/chromium/content/browser/permissions/permission_service_impl.cc
@@ -14,8 +14,8 @@
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
+#include "content/browser/permissions/permission_controller_impl.h"
#include "content/public/browser/browser_context.h"
-#include "content/public/browser/permission_manager.h"
#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_frame_host.h"
@@ -121,7 +121,7 @@ class PermissionServiceImpl::PendingRequest {
}
private:
- // Request ID received from the PermissionManager.
+ // Request ID received from the PermissionController.
int id_;
RequestPermissionsCallback callback_;
size_t request_size_;
@@ -159,8 +159,7 @@ void PermissionServiceImpl::RequestPermissions(
if (!browser_context)
return;
- if (!context_->render_frame_host() ||
- !browser_context->GetPermissionManager()) {
+ if (!context_->render_frame_host()) {
std::vector<PermissionStatus> result(permissions.size());
for (size_t i = 0; i < permissions.size(); ++i)
result[i] = GetPermissionStatus(permissions[i]);
@@ -187,10 +186,13 @@ void PermissionServiceImpl::RequestPermissions(
std::make_unique<PendingRequest>(types, std::move(callback));
int pending_request_id = pending_requests_.Add(std::move(pending_request));
- int id = browser_context->GetPermissionManager()->RequestPermissions(
- types, context_->render_frame_host(), origin_.GetURL(), user_gesture,
- base::Bind(&PermissionServiceImpl::OnRequestPermissionsResponse,
- weak_factory_.GetWeakPtr(), pending_request_id));
+ int id =
+ PermissionControllerImpl::FromBrowserContext(browser_context)
+ ->RequestPermissions(
+ types, context_->render_frame_host(), origin_.GetURL(),
+ user_gesture,
+ base::Bind(&PermissionServiceImpl::OnRequestPermissionsResponse,
+ weak_factory_.GetWeakPtr(), pending_request_id));
// Check if the request still exists. It may have been removed by the
// the response callback.
@@ -271,18 +273,16 @@ PermissionStatus PermissionServiceImpl::GetPermissionStatusFromType(
if (!browser_context)
return PermissionStatus::DENIED;
- if (!browser_context->GetPermissionManager())
- return PermissionStatus::DENIED;
-
GURL requesting_origin(origin_.GetURL());
if (context_->render_frame_host()) {
- return browser_context->GetPermissionManager()->GetPermissionStatusForFrame(
- type, context_->render_frame_host(), requesting_origin);
+ return BrowserContext::GetPermissionController(browser_context)
+ ->GetPermissionStatusForFrame(type, context_->render_frame_host(),
+ requesting_origin);
}
DCHECK(context_->GetEmbeddingOrigin().is_empty());
- return browser_context->GetPermissionManager()->GetPermissionStatus(
- type, requesting_origin, requesting_origin);
+ return BrowserContext::GetPermissionController(browser_context)
+ ->GetPermissionStatus(type, requesting_origin, requesting_origin);
}
void PermissionServiceImpl::ResetPermissionStatus(PermissionType type) {
@@ -290,15 +290,13 @@ void PermissionServiceImpl::ResetPermissionStatus(PermissionType type) {
if (!browser_context)
return;
- if (!browser_context->GetPermissionManager())
- return;
-
GURL requesting_origin(origin_.GetURL());
// If the embedding_origin is empty we'll use |origin_| instead.
GURL embedding_origin = context_->GetEmbeddingOrigin();
- browser_context->GetPermissionManager()->ResetPermission(
- type, requesting_origin,
- embedding_origin.is_empty() ? requesting_origin : embedding_origin);
+ PermissionControllerImpl::FromBrowserContext(browser_context)
+ ->ResetPermission(
+ type, requesting_origin,
+ embedding_origin.is_empty() ? requesting_origin : embedding_origin);
}
void PermissionServiceImpl::ReceivedBadMessage() {
diff --git a/chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc b/chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc
index 5e8617b1ddf..412d8895b63 100644
--- a/chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc
+++ b/chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc
@@ -11,6 +11,15 @@ namespace content {
OverlaySurfaceEmbedder::OverlaySurfaceEmbedder(OverlayWindow* window)
: window_(window) {
DCHECK(window_);
+ // Add window background.
+ window_background_layer_ = window_->GetWindowBackgroundLayer();
+ window_background_layer_->SetBounds(
+ gfx::Rect(gfx::Point(0, 0), window_->GetBounds().size()));
+
+ // Add |window_background_layer_| to |window_| and stack it at the bottom.
+ window_->GetLayer()->Add(window_background_layer_);
+ window_->GetLayer()->StackAtBottom(window_background_layer_);
+
video_layer_ = window_->GetVideoLayer();
video_layer_->SetMasksToBounds(true);
@@ -21,55 +30,35 @@ OverlaySurfaceEmbedder::OverlaySurfaceEmbedder(OverlayWindow* window)
// positioning of |window_| is dictated by itself.
video_layer_->SetBounds(
gfx::Rect(gfx::Point(0, 0), window_->GetBounds().size()));
- window_->GetLayer()->Add(video_layer_);
- AddControlsLayers();
+ // Add |video_layer_| to |window_| and stack it above
+ // |window_background_layer_|.
+ window_->GetLayer()->Add(video_layer_);
+ window_->GetLayer()->StackAbove(video_layer_, window_background_layer_);
}
OverlaySurfaceEmbedder::~OverlaySurfaceEmbedder() = default;
-void OverlaySurfaceEmbedder::SetPrimarySurfaceId(
- const viz::SurfaceId& surface_id) {
+void OverlaySurfaceEmbedder::SetSurfaceId(const viz::SurfaceId& surface_id) {
+ video_layer_ = window_->GetVideoLayer();
// SurfaceInfo has information about the embedded surface.
video_layer_->SetShowPrimarySurface(
surface_id, window_->GetBounds().size(), SK_ColorBLACK,
cc::DeadlinePolicy::UseDefaultDeadline(),
true /* stretch_content_to_fill_bounds */);
+ video_layer_->SetFallbackSurfaceId(surface_id);
}
void OverlaySurfaceEmbedder::UpdateLayerBounds() {
- // Update the size and position of the video to stretch on the entire window.
- gfx::Size window_size = window_->GetBounds().size();
- gfx::Rect window_bounds = gfx::Rect(gfx::Point(0, 0), window_size);
- video_layer_->SetBounds(window_bounds);
- video_layer_->SetSurfaceSize(window_size);
-
- // Update the size and position of controls.
- controls_background_layer_->SetBounds(window_bounds);
- close_controls_layer_->SetBounds(window_->GetCloseControlsBounds());
- play_pause_controls_layer_->SetBounds(window_->GetPlayPauseControlsBounds());
-}
-
-void OverlaySurfaceEmbedder::AddControlsLayers() {
- // These control layers are expected to be set up by |window_|.
- controls_background_layer_ = window_->GetControlsBackgroundLayer();
- DCHECK(controls_background_layer_);
- controls_background_layer_->SetBounds(
+ // Update the size of window background.
+ window_background_layer_ = window_->GetWindowBackgroundLayer();
+ window_background_layer_->SetBounds(
gfx::Rect(gfx::Point(0, 0), window_->GetBounds().size()));
- close_controls_layer_ = window_->GetCloseControlsLayer();
- DCHECK(close_controls_layer_);
- close_controls_layer_->SetFillsBoundsOpaquely(false);
- close_controls_layer_->SetBounds(window_->GetCloseControlsBounds());
-
- play_pause_controls_layer_ = window_->GetPlayPauseControlsLayer();
- DCHECK(play_pause_controls_layer_);
- play_pause_controls_layer_->SetFillsBoundsOpaquely(false);
- play_pause_controls_layer_->SetBounds(window_->GetPlayPauseControlsBounds());
-
- window_->GetLayer()->Add(controls_background_layer_);
- window_->GetLayer()->Add(close_controls_layer_);
- window_->GetLayer()->Add(play_pause_controls_layer_);
+ // Update the size and position of the video to stretch on the entire window.
+ video_layer_ = window_->GetVideoLayer();
+ video_layer_->SetBounds(window_->GetVideoBounds());
+ video_layer_->SetSurfaceSize(window_->GetVideoBounds().size());
}
} // namespace content
diff --git a/chromium/content/browser/picture_in_picture/overlay_surface_embedder.h b/chromium/content/browser/picture_in_picture/overlay_surface_embedder.h
index dd0f277dc6d..9307f38e8d8 100644
--- a/chromium/content/browser/picture_in_picture/overlay_surface_embedder.h
+++ b/chromium/content/browser/picture_in_picture/overlay_surface_embedder.h
@@ -23,9 +23,8 @@ class OverlaySurfaceEmbedder {
explicit OverlaySurfaceEmbedder(OverlayWindow* window);
~OverlaySurfaceEmbedder();
- void SetPrimarySurfaceId(const viz::SurfaceId& surface_id);
+ void SetSurfaceId(const viz::SurfaceId&);
void UpdateLayerBounds();
- void AddControlsLayers();
private:
// The window which embeds the client. Weak pointer since the
@@ -36,11 +35,9 @@ class OverlaySurfaceEmbedder {
std::unique_ptr<ui::Layer> surface_layer_;
// Owned by the OverlayWindow implementation.
- // These are set in AddControlsLayer(), which is called in the constructor.
+ // These are set in the constructor.
+ ui::Layer* window_background_layer_ = nullptr;
ui::Layer* video_layer_ = nullptr;
- ui::Layer* controls_background_layer_ = nullptr;
- ui::Layer* close_controls_layer_ = nullptr;
- ui::Layer* play_pause_controls_layer_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(OverlaySurfaceEmbedder);
};
diff --git a/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc b/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
index f0835214f02..fcb1e96e6cd 100644
--- a/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
+++ b/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
@@ -48,7 +48,7 @@ PictureInPictureWindowControllerImpl::~PictureInPictureWindowControllerImpl() {
return;
initiator_->SetHasPictureInPictureVideo(false);
- OnLeavingPictureInPicture();
+ OnLeavingPictureInPicture(true /* should_pause_video */);
}
PictureInPictureWindowControllerImpl::PictureInPictureWindowControllerImpl(
@@ -58,8 +58,7 @@ PictureInPictureWindowControllerImpl::PictureInPictureWindowControllerImpl(
media_web_contents_observer_ = initiator_->media_web_contents_observer();
- window_ =
- GetContentClient()->browser()->CreateWindowForPictureInPicture(this);
+ EnsureWindow();
DCHECK(window_) << "Picture in Picture requires a valid window.";
}
@@ -73,21 +72,36 @@ gfx::Size PictureInPictureWindowControllerImpl::Show() {
return window_->GetBounds().size();
}
-void PictureInPictureWindowControllerImpl::Close() {
+void PictureInPictureWindowControllerImpl::ClickCustomControl(
+ const std::string& control_id) {
DCHECK(window_);
- window_->Hide();
- initiator_->SetHasPictureInPictureVideo(false);
+ media_player_id_->render_frame_host->Send(
+ new MediaPlayerDelegateMsg_ClickPictureInPictureControl(
+ media_player_id_->render_frame_host->GetRoutingID(),
+ media_player_id_->delegate_id, control_id));
+}
- surface_id_ = viz::SurfaceId();
+void PictureInPictureWindowControllerImpl::Close(bool should_pause_video) {
+ if (!window_ || !window_->IsVisible())
+ return;
+
+ window_->Hide();
+ CloseInternal(should_pause_video);
+}
- OnLeavingPictureInPicture();
+void PictureInPictureWindowControllerImpl::OnWindowDestroyed() {
+ window_ = nullptr;
+ embedder_ = nullptr;
+ CloseInternal(true /* should_pause_video */);
}
void PictureInPictureWindowControllerImpl::EmbedSurface(
const viz::SurfaceId& surface_id,
const gfx::Size& natural_size) {
+ EnsureWindow();
DCHECK(window_);
+
DCHECK(surface_id.is_valid());
surface_id_ = surface_id;
@@ -97,12 +111,13 @@ void PictureInPictureWindowControllerImpl::EmbedSurface(
// |initiator_| enters Picture-in-Picture mode.
media_player_id_ =
media_web_contents_observer_->GetPictureInPictureVideoMediaPlayerId();
+ UpdatePlaybackState(IsPlayerActive(), !media_player_id_.has_value());
window_->UpdateVideoSize(natural_size);
if (!embedder_)
embedder_.reset(new OverlaySurfaceEmbedder(window_.get()));
- embedder_->SetPrimarySurfaceId(surface_id_);
+ embedder_->SetSurfaceId(surface_id_);
}
OverlayWindow* PictureInPictureWindowControllerImpl::GetWindowForTesting() {
@@ -110,7 +125,7 @@ OverlayWindow* PictureInPictureWindowControllerImpl::GetWindowForTesting() {
}
void PictureInPictureWindowControllerImpl::UpdateLayerBounds() {
- if (window_) {
+ if (window_ && window_->IsVisible()) {
media_web_contents_observer_->OnPictureInPictureWindowResize(
window_->GetBounds().size());
}
@@ -120,8 +135,10 @@ void PictureInPictureWindowControllerImpl::UpdateLayerBounds() {
}
bool PictureInPictureWindowControllerImpl::IsPlayerActive() {
- if (!media_player_id_.has_value())
- media_web_contents_observer_->GetPictureInPictureVideoMediaPlayerId();
+ if (!media_player_id_.has_value()) {
+ media_player_id_ =
+ media_web_contents_observer_->GetPictureInPictureVideoMediaPlayerId();
+ }
return media_player_id_.has_value() &&
media_web_contents_observer_->IsPlayerActive(*media_player_id_);
@@ -131,30 +148,72 @@ WebContents* PictureInPictureWindowControllerImpl::GetInitiatorWebContents() {
return initiator_;
}
+void PictureInPictureWindowControllerImpl::UpdatePlaybackState(
+ bool is_playing,
+ bool reached_end_of_stream) {
+ if (!window_)
+ return;
+
+ if (reached_end_of_stream) {
+ media_player_id_.reset();
+ window_->SetPlaybackState(OverlayWindow::PlaybackState::kNoVideo);
+ return;
+ }
+
+ DCHECK(media_player_id_.has_value());
+
+ window_->SetPlaybackState(is_playing ? OverlayWindow::PlaybackState::kPlaying
+ : OverlayWindow::PlaybackState::kPaused);
+}
+
bool PictureInPictureWindowControllerImpl::TogglePlayPause() {
DCHECK(window_ && window_->IsActive());
if (IsPlayerActive()) {
- media_player_id_->first->Send(new MediaPlayerDelegateMsg_Pause(
- media_player_id_->first->GetRoutingID(), media_player_id_->second));
+ media_player_id_->render_frame_host->Send(new MediaPlayerDelegateMsg_Pause(
+ media_player_id_->render_frame_host->GetRoutingID(),
+ media_player_id_->delegate_id));
return false;
}
- media_player_id_->first->Send(new MediaPlayerDelegateMsg_Play(
- media_player_id_->first->GetRoutingID(), media_player_id_->second));
+ media_player_id_->render_frame_host->Send(new MediaPlayerDelegateMsg_Play(
+ media_player_id_->render_frame_host->GetRoutingID(),
+ media_player_id_->delegate_id));
return true;
}
-void PictureInPictureWindowControllerImpl::OnLeavingPictureInPicture() {
- if (IsPlayerActive()) {
+void PictureInPictureWindowControllerImpl::OnLeavingPictureInPicture(
+ bool should_pause_video) {
+ if (IsPlayerActive() && should_pause_video) {
// Pause the current video so there is only one video playing at a time.
- media_player_id_->first->Send(new MediaPlayerDelegateMsg_Pause(
- media_player_id_->first->GetRoutingID(), media_player_id_->second));
+ media_player_id_->render_frame_host->Send(new MediaPlayerDelegateMsg_Pause(
+ media_player_id_->render_frame_host->GetRoutingID(),
+ media_player_id_->delegate_id));
}
- media_player_id_->first->Send(
- new MediaPlayerDelegateMsg_EndPictureInPictureMode(
- media_player_id_->first->GetRoutingID(), media_player_id_->second));
+ if (media_player_id_.has_value()) {
+ media_player_id_->render_frame_host->Send(
+ new MediaPlayerDelegateMsg_EndPictureInPictureMode(
+ media_player_id_->render_frame_host->GetRoutingID(),
+ media_player_id_->delegate_id));
+ }
+}
+
+void PictureInPictureWindowControllerImpl::CloseInternal(
+ bool should_pause_video) {
+ initiator_->SetHasPictureInPictureVideo(false);
+
+ surface_id_ = viz::SurfaceId();
+
+ OnLeavingPictureInPicture(should_pause_video);
+}
+
+void PictureInPictureWindowControllerImpl::EnsureWindow() {
+ if (window_)
+ return;
+
+ window_ =
+ GetContentClient()->browser()->CreateWindowForPictureInPicture(this);
}
} // namespace content
diff --git a/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h b/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
index 7a960800ec2..7ce6d853fc4 100644
--- a/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
+++ b/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
@@ -35,7 +35,10 @@ class PictureInPictureWindowControllerImpl
// PictureInPictureWindowController:
CONTENT_EXPORT gfx::Size Show() override;
- CONTENT_EXPORT void Close() override;
+ CONTENT_EXPORT void Close(bool should_pause_video) override;
+ CONTENT_EXPORT void OnWindowDestroyed() override;
+ CONTENT_EXPORT void ClickCustomControl(
+ const std::string& control_id) override;
CONTENT_EXPORT void EmbedSurface(const viz::SurfaceId& surface_id,
const gfx::Size& natural_size) override;
CONTENT_EXPORT OverlayWindow* GetWindowForTesting() override;
@@ -43,6 +46,8 @@ class PictureInPictureWindowControllerImpl
CONTENT_EXPORT bool IsPlayerActive() override;
CONTENT_EXPORT WebContents* GetInitiatorWebContents() override;
CONTENT_EXPORT bool TogglePlayPause() override;
+ CONTENT_EXPORT void UpdatePlaybackState(bool is_playing,
+ bool reached_end_of_stream) override;
private:
friend class WebContentsUserData<PictureInPictureWindowControllerImpl>;
@@ -53,7 +58,15 @@ class PictureInPictureWindowControllerImpl
WebContents* initiator);
// Signal to the media player that |this| is leaving Picture-in-Picture mode.
- void OnLeavingPictureInPicture();
+ void OnLeavingPictureInPicture(bool should_pause_video);
+
+ // Internal method to set the states after the window was closed, whether via
+ // the system or Chromium.
+ void CloseInternal(bool should_pause_video);
+
+ // Creates a new window if the previous one was destroyed. It can happen
+ // because of the system control of the window.
+ void EnsureWindow();
std::unique_ptr<OverlayWindow> window_;
std::unique_ptr<OverlaySurfaceEmbedder> embedder_;
diff --git a/chromium/content/browser/plugin_service_impl.cc b/chromium/content/browser/plugin_service_impl.cc
index dcdae19642b..e4e5a87af7e 100644
--- a/chromium/content/browser/plugin_service_impl.cc
+++ b/chromium/content/browser/plugin_service_impl.cc
@@ -25,6 +25,7 @@
#include "content/browser/ppapi_plugin_process_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/content_switches_internal.h"
#include "content/common/pepper_plugin_list.h"
#include "content/common/plugin_list.h"
@@ -65,13 +66,12 @@ void WillLoadPluginsCallback(base::SequenceChecker* sequence_checker) {
// static
void PluginServiceImpl::RecordBrokerUsage(int render_process_id,
int render_frame_id) {
- ukm::UkmRecorder* recorder = ukm::UkmRecorder::Get();
- ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
WebContents* web_contents = WebContents::FromRenderFrameHost(
RenderFrameHost::FromID(render_process_id, render_frame_id));
if (web_contents) {
- recorder->UpdateSourceURL(source_id, web_contents->GetLastCommittedURL());
- ukm::builders::Pepper_Broker(source_id).Record(recorder);
+ ukm::SourceId source_id = static_cast<WebContentsImpl*>(web_contents)
+ ->GetUkmSourceIdForLastCommittedSource();
+ ukm::builders::Pepper_Broker(source_id).Record(ukm::UkmRecorder::Get());
}
}
diff --git a/chromium/content/browser/plugin_service_impl_unittest.cc b/chromium/content/browser/plugin_service_impl_unittest.cc
index 72022dd1436..ed9ec8c472b 100644
--- a/chromium/content/browser/plugin_service_impl_unittest.cc
+++ b/chromium/content/browser/plugin_service_impl_unittest.cc
@@ -10,6 +10,7 @@
#include "components/ukm/test_ukm_recorder.h"
#include "components/ukm/ukm_source.h"
#include "content/browser/ppapi_plugin_process_host.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -50,16 +51,18 @@ class PluginServiceImplTest : public RenderViewHostTestHarness {
test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
}
- bool RecordedBrokerEvent(const GURL& url) {
+ // Check if count events were recorded and if they were all recorded with
+ // the specified source_id.
+ bool RecordedBrokerEvents(ukm::SourceId source_id, size_t count) {
RunAllPendingInMessageLoop(BrowserThread::UI);
auto entries = test_ukm_recorder_->GetEntriesByName(kPepperBrokerEvent);
+ if (entries.size() != count)
+ return false;
for (const auto* const entry : entries) {
- const ukm::UkmSource* source =
- test_ukm_recorder_->GetSourceForSourceId(entry->source_id);
- if (source && source->url() == url)
- return true;
+ if (entry->source_id != source_id)
+ return false;
}
- return false;
+ return true;
}
void ResetUKM() {
@@ -76,20 +79,21 @@ TEST_F(PluginServiceImplTest, RecordBrokerUsage) {
TestBrokerClient client;
NavigateAndCommit(GURL(kURL1));
+ ukm::SourceId source_id = static_cast<WebContentsImpl*>(web_contents())
+ ->GetUkmSourceIdForLastCommittedSource();
PluginServiceImpl* service = PluginServiceImpl::GetInstance();
// Internal usage of the broker should not record metrics. Internal usage will
// not pass a RFH.
service->OpenChannelToPpapiBroker(0, 0, base::FilePath(), &client);
- EXPECT_FALSE(RecordedBrokerEvent(GURL(kURL1)));
+ EXPECT_TRUE(RecordedBrokerEvents(source_id, 0));
// Top level frame usage should be recorded.
int render_process_id = main_rfh()->GetProcess()->GetID();
int render_frame_id = main_rfh()->GetRoutingID();
service->OpenChannelToPpapiBroker(render_process_id, render_frame_id,
base::FilePath(), &client);
- EXPECT_TRUE(RecordedBrokerEvent(GURL(kURL1)));
- EXPECT_FALSE(RecordedBrokerEvent(GURL(kURL2)));
+ EXPECT_TRUE(RecordedBrokerEvents(source_id, 1));
ResetUKM();
@@ -103,8 +107,7 @@ TEST_F(PluginServiceImplTest, RecordBrokerUsage) {
render_frame_id = child_frame->GetRoutingID();
service->OpenChannelToPpapiBroker(render_process_id, render_frame_id,
base::FilePath(), &client);
- EXPECT_TRUE(RecordedBrokerEvent(GURL(kURL1)));
- EXPECT_FALSE(RecordedBrokerEvent(GURL(kURL2)));
+ EXPECT_TRUE(RecordedBrokerEvents(source_id, 1));
}
} // namespace content
diff --git a/chromium/content/browser/pointer_lock_browsertest.cc b/chromium/content/browser/pointer_lock_browsertest.cc
index 1e547b71308..b4f10231ad3 100644
--- a/chromium/content/browser/pointer_lock_browsertest.cc
+++ b/chromium/content/browser/pointer_lock_browsertest.cc
@@ -12,6 +12,7 @@
#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/hit_test_region_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
@@ -25,32 +26,45 @@
namespace content {
-namespace {
+class MockPointerLockWebContentsDelegate : public WebContentsDelegate {
+ public:
+ MockPointerLockWebContentsDelegate() {}
+ ~MockPointerLockWebContentsDelegate() override {}
+
+ void RequestToLockMouse(WebContents* web_contents,
+ bool user_gesture,
+ bool last_unlocked_by_target) override {
+ web_contents->GotResponseToLockMouseRequest(true);
+ }
+
+ void LostMouseLock() override {}
+};
#ifdef USE_AURA
-class MockRenderWidgetHostView : public RenderWidgetHostViewAura {
+class MockPointerLockRenderWidgetHostView : public RenderWidgetHostViewAura {
public:
- MockRenderWidgetHostView(RenderWidgetHost* host, bool is_guest_view_hack)
+ MockPointerLockRenderWidgetHostView(RenderWidgetHost* host,
+ bool is_guest_view_hack)
: RenderWidgetHostViewAura(host,
is_guest_view_hack,
false /* is_mus_browser_plugin_guest */),
host_(RenderWidgetHostImpl::From(host)) {}
- ~MockRenderWidgetHostView() override {
- if (mouse_locked_)
+ ~MockPointerLockRenderWidgetHostView() override {
+ if (IsMouseLocked())
UnlockMouse();
}
bool LockMouse() override {
- mouse_locked_ = true;
+ event_handler()->mouse_locked_ = true;
return true;
}
void UnlockMouse() override {
host_->LostMouseLock();
- mouse_locked_ = false;
+ event_handler()->mouse_locked_ = false;
}
- bool IsMouseLocked() override { return mouse_locked_; }
+ bool IsMouseLocked() override { return event_handler()->mouse_locked(); }
bool HasFocus() const override { return true; }
@@ -61,30 +75,13 @@ class MockRenderWidgetHostView : public RenderWidgetHostViewAura {
RenderWidgetHostImpl* host_;
};
-#endif // USE_AURA
-
-} // namespace
-
-class MockPointerLockWebContentsDelegate : public WebContentsDelegate {
- public:
- MockPointerLockWebContentsDelegate() {}
- ~MockPointerLockWebContentsDelegate() override {}
-
- void RequestToLockMouse(WebContents* web_contents,
- bool user_gesture,
- bool last_unlocked_by_target) override {
- web_contents->GotResponseToLockMouseRequest(true);
- }
-
- void LostMouseLock() override {}
-};
-#ifdef USE_AURA
void InstallCreateHooksForPointerLockBrowserTests() {
WebContentsViewAura::InstallCreateHookForTests(
[](RenderWidgetHost* host,
bool is_guest_view_hack) -> RenderWidgetHostViewAura* {
- return new MockRenderWidgetHostView(host, is_guest_view_hack);
+ return new MockPointerLockRenderWidgetHostView(host,
+ is_guest_view_hack);
});
}
#endif // USE_AURA
@@ -179,7 +176,7 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockEventRouting) {
RenderWidgetHostViewBase* child_view = static_cast<RenderWidgetHostViewBase*>(
child->current_frame_host()->GetView());
- WaitForChildFrameSurfaceReady(child->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
// Request a pointer lock on the root frame's body.
EXPECT_TRUE(ExecuteScript(root, "document.body.requestPointerLock()"));
@@ -397,7 +394,7 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) {
RenderWidgetHostViewBase* child_view = static_cast<RenderWidgetHostViewBase*>(
child->current_frame_host()->GetView());
- WaitForChildFrameSurfaceReady(child->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
// Request a pointer lock on the root frame's body.
EXPECT_TRUE(ExecuteScript(root, "document.body.requestPointerLock()"));
@@ -431,18 +428,16 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) {
// Make sure that the renderer handled the input event.
root_observer.Wait();
- if (root_view->wheel_scroll_latching_enabled()) {
- // When wheel scroll latching is enabled all wheel events during a scroll
- // sequence will be sent to a single target. Send a wheel end event to the
- // current target before sending wheel events to a new target.
- wheel_event.delta_x = 0;
- wheel_event.delta_y = 0;
- wheel_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
- router->RouteMouseWheelEvent(root_view, &wheel_event, ui::LatencyInfo());
-
- // Make sure that the renderer handled the input event.
- root_observer.Wait();
- }
+ // All wheel events during a scroll sequence will be sent to a single target.
+ // Send a wheel end event to the current target before sending wheel events to
+ // a new target.
+ wheel_event.delta_x = 0;
+ wheel_event.delta_y = 0;
+ wheel_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ router->RouteMouseWheelEvent(root_view, &wheel_event, ui::LatencyInfo());
+
+ // Make sure that the renderer handled the input event.
+ root_observer.Wait();
int x, y, deltaX, deltaY;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
@@ -489,8 +484,7 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) {
-transformed_point.y() + 15);
wheel_event.delta_x = -16;
wheel_event.delta_y = -17;
- if (root_view->wheel_scroll_latching_enabled())
- wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
+ wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
// We use root_view intentionally as the RenderWidgetHostInputEventRouter is
// responsible for correctly routing the event to the child frame.
router->RouteMouseWheelEvent(root_view, &wheel_event, ui::LatencyInfo());
@@ -522,7 +516,7 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWidgetHidden) {
RenderWidgetHostViewBase* child_view = static_cast<RenderWidgetHostViewBase*>(
child->current_frame_host()->GetView());
- WaitForChildFrameSurfaceReady(child->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
// Request a pointer lock on the child frame's body.
EXPECT_TRUE(ExecuteScript(child, "document.body.requestPointerLock()"));
diff --git a/chromium/content/browser/pointer_lock_browsertest_mac.mm b/chromium/content/browser/pointer_lock_browsertest_mac.mm
index 26adc174a32..75c02abf8b9 100644
--- a/chromium/content/browser/pointer_lock_browsertest_mac.mm
+++ b/chromium/content/browser/pointer_lock_browsertest_mac.mm
@@ -10,13 +10,12 @@
namespace content {
-namespace {
-
-class MockRenderWidgetHostView : public RenderWidgetHostViewMac {
+class MockPointerLockRenderWidgetHostView : public RenderWidgetHostViewMac {
public:
- MockRenderWidgetHostView(RenderWidgetHost* host, bool is_guest_view_hack)
+ MockPointerLockRenderWidgetHostView(RenderWidgetHost* host,
+ bool is_guest_view_hack)
: RenderWidgetHostViewMac(host, is_guest_view_hack) {}
- ~MockRenderWidgetHostView() override {
+ ~MockPointerLockRenderWidgetHostView() override {
if (mouse_locked_)
UnlockMouse();
}
@@ -40,13 +39,12 @@ class MockRenderWidgetHostView : public RenderWidgetHostViewMac {
bool HasFocus() const override { return true; }
};
-} // namespace
-
void InstallCreateHooksForPointerLockBrowserTests() {
WebContentsViewMac::InstallCreateHookForTests(
[](RenderWidgetHost* host,
bool is_guest_view_hack) -> RenderWidgetHostViewMac* {
- return new MockRenderWidgetHostView(host, is_guest_view_hack);
+ return new MockPointerLockRenderWidgetHostView(host,
+ is_guest_view_hack);
});
}
diff --git a/chromium/content/browser/power_monitor_browsertest.cc b/chromium/content/browser/power_monitor_browsertest.cc
index 633b768ff5f..ffd7190d197 100644
--- a/chromium/content/browser/power_monitor_browsertest.cc
+++ b/chromium/content/browser/power_monitor_browsertest.cc
@@ -47,6 +47,7 @@ void StartUtilityProcessOnIOThread(mojom::PowerMonitorTestRequest request) {
UtilityProcessHost* host =
new UtilityProcessHost(/*client=*/nullptr,
/*client_task_runner=*/nullptr);
+ host->SetMetricsName("test_process");
host->SetName(base::ASCIIToUTF16("TestProcess"));
EXPECT_TRUE(host->Start());
@@ -92,17 +93,18 @@ class MockPowerMonitorMessageBroadcaster : public device::mojom::PowerMonitor {
class PowerMonitorTest : public ContentBrowserTest {
public:
- PowerMonitorTest() = default;
-
- void SetUp() override {
+ PowerMonitorTest() {
// Because Device Service also runs in this process(browser process), we can
// set our binder to intercept requests for PowerMonitor interface to it.
service_manager::ServiceContext::SetGlobalBinderForTesting(
device::mojom::kServiceName, device::mojom::PowerMonitor::Name_,
base::Bind(&PowerMonitorTest::BindPowerMonitor,
base::Unretained(this)));
+ }
- ContentBrowserTest::SetUp();
+ ~PowerMonitorTest() override {
+ service_manager::ServiceContext::ClearGlobalBindersForTesting(
+ device::mojom::kServiceName);
}
void BindPowerMonitor(const std::string& interface_name,
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index f2de22ce7fe..3cf4e5d1f53 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -29,7 +29,6 @@
#include "content/public/common/process_type.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "content/public/common/service_names.mojom.h"
-#include "mojo/edk/embedder/embedder.h"
#include "net/base/network_change_notifier.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "services/service_manager/sandbox/sandbox_type.h"
diff --git a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
index ad4ff3ef346..a635d4413a8 100644
--- a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -132,7 +132,7 @@ class MockPresentationServiceDelegate
int render_frame_id,
const std::string& presentation_id));
MOCK_METHOD3(GetMediaController,
- std::unique_ptr<content::MediaController>(
+ std::unique_ptr<media::MediaController>(
int render_process_id,
int render_frame_id,
const std::string& presentation_id));
diff --git a/chromium/content/browser/process_internals/process_internals.mojom b/chromium/content/browser/process_internals/process_internals.mojom
index da65f0ffb15..d8fe8594f2d 100644
--- a/chromium/content/browser/process_internals/process_internals.mojom
+++ b/chromium/content/browser/process_internals/process_internals.mojom
@@ -11,7 +11,6 @@ interface ProcessInternalsHandler {
// Returns a string containing the currently active isolation modes.
GetIsolationMode() => (string mode);
- // Returns a list of isolated origins in their serialized to string
- // format. This avoids duplicating serialization code to JavaScript.
- GetIsolatedOrigins() => (array<string> isolated_origins);
+ // Returns the number of isolated origins.
+ GetIsolatedOriginsSize() => (uint32 size);
};
diff --git a/chromium/content/browser/process_internals/process_internals_handler_impl.cc b/chromium/content/browser/process_internals/process_internals_handler_impl.cc
index ae4fc6d9ac6..dbd0e5792b1 100644
--- a/chromium/content/browser/process_internals/process_internals_handler_impl.cc
+++ b/chromium/content/browser/process_internals/process_internals_handler_impl.cc
@@ -30,15 +30,10 @@ void ProcessInternalsHandlerImpl::GetIsolationMode(
: base::JoinString(modes, ", "));
}
-void ProcessInternalsHandlerImpl::GetIsolatedOrigins(
- GetIsolatedOriginsCallback callback) {
- std::vector<url::Origin> origins_list =
- SiteIsolationPolicy::GetIsolatedOrigins();
- std::vector<std::string> origins;
- for (size_t i = 0; i < origins_list.size(); ++i)
- origins.push_back(origins_list[i].Serialize());
-
- std::move(callback).Run(origins);
+void ProcessInternalsHandlerImpl::GetIsolatedOriginsSize(
+ GetIsolatedOriginsSizeCallback callback) {
+ int size = SiteIsolationPolicy::GetIsolatedOrigins().size();
+ std::move(callback).Run(size);
}
} // namespace content
diff --git a/chromium/content/browser/process_internals/process_internals_handler_impl.h b/chromium/content/browser/process_internals/process_internals_handler_impl.h
index 3a8ee50a94e..54b7def12f9 100644
--- a/chromium/content/browser/process_internals/process_internals_handler_impl.h
+++ b/chromium/content/browser/process_internals/process_internals_handler_impl.h
@@ -22,7 +22,7 @@ class ProcessInternalsHandlerImpl : public ::mojom::ProcessInternalsHandler {
// mojom::ProcessInternalsHandler overrides:
void GetIsolationMode(GetIsolationModeCallback callback) override;
- void GetIsolatedOrigins(GetIsolatedOriginsCallback callback) override;
+ void GetIsolatedOriginsSize(GetIsolatedOriginsSizeCallback callback) override;
private:
mojo::Binding<::mojom::ProcessInternalsHandler> binding_;
diff --git a/chromium/content/browser/process_internals/process_internals_ui.cc b/chromium/content/browser/process_internals/process_internals_ui.cc
index f6015e79efd..8c3558c5b61 100644
--- a/chromium/content/browser/process_internals/process_internals_ui.cc
+++ b/chromium/content/browser/process_internals/process_internals_ui.cc
@@ -28,7 +28,7 @@ ProcessInternalsUI::ProcessInternalsUI(WebUI* web_ui)
: WebUIController(web_ui), WebContentsObserver(web_ui->GetWebContents()) {
// Grant only Mojo WebUI bindings, since this WebUI will not use
// chrome.send().
- web_ui->SetBindings(content::BINDINGS_POLICY_WEB_UI);
+ web_ui->SetBindings(content::BINDINGS_POLICY_MOJO_WEB_UI);
// Create a WebUIDataSource to serve the HTML/JS files to the WebUI.
WebUIDataSource* source =
diff --git a/chromium/content/browser/push_messaging/push_messaging_manager.cc b/chromium/content/browser/push_messaging/push_messaging_manager.cc
index fef1c37b56c..bc6ee59fe0c 100644
--- a/chromium/content/browser/push_messaging/push_messaging_manager.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_manager.cc
@@ -14,13 +14,13 @@
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
+#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/renderer_host/render_process_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_storage.h"
#include "content/common/push_messaging.mojom.h"
#include "content/public/browser/browser_context.h"
-#include "content/public/browser/permission_manager.h"
#include "content/public/browser/permission_type.h"
#include "content/public/browser/push_messaging_service.h"
#include "content/public/browser/render_frame_host.h"
@@ -335,12 +335,12 @@ void PushMessagingManager::Subscribe(int32_t render_frame_id,
void PushMessagingManager::DidCheckForExistingRegistration(
RegisterData data,
const std::vector<std::string>& subscription_id_and_sender_id,
- ServiceWorkerStatusCode service_worker_status) {
+ blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Validate the stored subscription against the subscription request made by
// the developer. The authorized entity must match.
- if (service_worker_status == SERVICE_WORKER_OK) {
+ if (service_worker_status == blink::ServiceWorkerStatusCode::kOk) {
DCHECK_EQ(2u, subscription_id_and_sender_id.size());
const std::string& subscription_id = subscription_id_and_sender_id[0];
@@ -363,8 +363,9 @@ void PushMessagingManager::DidCheckForExistingRegistration(
data.existing_subscription_id = subscription_id;
}
- // TODO(peter): Handle failures other than SERVICE_WORKER_ERROR_NOT_FOUND by
- // rejecting the subscription algorithm instead of trying to subscribe.
+ // TODO(peter): Handle failures other than
+ // blink::ServiceWorkerStatusCode::kErrorNotFound by rejecting
+ // the subscription algorithm instead of trying to subscribe.
if (!data.options.sender_info.empty()) {
BrowserThread::PostTask(
@@ -385,9 +386,9 @@ void PushMessagingManager::DidCheckForExistingRegistration(
void PushMessagingManager::DidGetSenderIdFromStorage(
RegisterData data,
const std::vector<std::string>& stored_sender_id,
- ServiceWorkerStatusCode service_worker_status) {
+ blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (service_worker_status != SERVICE_WORKER_OK) {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
SendSubscriptionError(std::move(data),
mojom::PushRegistrationStatus::NO_SENDER_ID);
return;
@@ -444,29 +445,17 @@ void PushMessagingManager::Core::RegisterOnUI(
BrowserContext* browser_context = web_contents->GetBrowserContext();
- // It's valid for embedders to return a null permission manager.
- // Immediately reject the permission request when this happens.
- if (!browser_context->GetPermissionManager()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PushMessagingManager::SendSubscriptionError,
- io_parent_, std::move(data),
- mojom::PushRegistrationStatus::
- INCOGNITO_PERMISSION_DENIED));
-
- return;
- }
-
// Request notifications permission (which will fail, since
// notifications aren't supported in incognito), so the website can't
// detect whether incognito is active.
- GURL requesting_origin = data.requesting_origin;
- browser_context->GetPermissionManager()->RequestPermission(
- PermissionType::NOTIFICATIONS, render_frame_host,
- requesting_origin, data.user_gesture,
- base::Bind(
- &PushMessagingManager::Core::DidRequestPermissionInIncognito,
- weak_factory_ui_to_ui_.GetWeakPtr(), base::Passed(&data)));
+ PermissionControllerImpl::FromBrowserContext(browser_context)
+ ->RequestPermission(
+ PermissionType::NOTIFICATIONS, render_frame_host,
+ data.requesting_origin, data.user_gesture,
+ base::Bind(&PushMessagingManager::Core::
+ DidRequestPermissionInIncognito,
+ weak_factory_ui_to_ui_.GetWeakPtr(),
+ base::Passed(&data)));
}
}
}
@@ -563,9 +552,9 @@ void PushMessagingManager::DidPersistRegistrationOnIO(
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth,
mojom::PushRegistrationStatus push_registration_status,
- ServiceWorkerStatusCode service_worker_status) {
+ blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (service_worker_status == SERVICE_WORKER_OK) {
+ if (service_worker_status == blink::ServiceWorkerStatusCode::kOk) {
SendSubscriptionSuccess(std::move(data), push_registration_status,
push_subscription_id, p256dh, auth);
} else {
@@ -638,11 +627,11 @@ void PushMessagingManager::UnsubscribeHavingGottenSenderId(
int64_t service_worker_registration_id,
const GURL& requesting_origin,
const std::vector<std::string>& sender_ids,
- ServiceWorkerStatusCode service_worker_status) {
+ blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::string sender_id;
- if (service_worker_status == SERVICE_WORKER_OK) {
+ if (service_worker_status == blink::ServiceWorkerStatusCode::kOk) {
DCHECK_EQ(1u, sender_ids.size());
sender_id = sender_ids[0];
}
@@ -746,12 +735,12 @@ void PushMessagingManager::DidGetSubscription(
GetSubscriptionCallback callback,
int64_t service_worker_registration_id,
const std::vector<std::string>& push_subscription_id_and_sender_info,
- ServiceWorkerStatusCode service_worker_status) {
+ blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
mojom::PushGetRegistrationStatus get_status =
mojom::PushGetRegistrationStatus::STORAGE_ERROR;
switch (service_worker_status) {
- case SERVICE_WORKER_OK: {
+ case blink::ServiceWorkerStatusCode::kOk: {
DCHECK_EQ(2u, push_subscription_id_and_sender_info.size());
const std::string& push_subscription_id =
push_subscription_id_and_sender_info[0];
@@ -794,33 +783,33 @@ void PushMessagingManager::DidGetSubscription(
return;
}
- case SERVICE_WORKER_ERROR_NOT_FOUND: {
+ case blink::ServiceWorkerStatusCode::kErrorNotFound: {
get_status = mojom::PushGetRegistrationStatus::REGISTRATION_NOT_FOUND;
break;
}
- case SERVICE_WORKER_ERROR_FAILED: {
+ case blink::ServiceWorkerStatusCode::kErrorFailed: {
get_status = mojom::PushGetRegistrationStatus::STORAGE_ERROR;
break;
}
- case SERVICE_WORKER_ERROR_ABORT:
- case SERVICE_WORKER_ERROR_START_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND:
- case SERVICE_WORKER_ERROR_EXISTS:
- case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_IPC_FAILED:
- case SERVICE_WORKER_ERROR_NETWORK:
- case SERVICE_WORKER_ERROR_SECURITY:
- case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED:
- case SERVICE_WORKER_ERROR_STATE:
- case SERVICE_WORKER_ERROR_TIMEOUT:
- case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED:
- case SERVICE_WORKER_ERROR_DISK_CACHE:
- case SERVICE_WORKER_ERROR_REDUNDANT:
- case SERVICE_WORKER_ERROR_DISALLOWED:
- case SERVICE_WORKER_ERROR_MAX_VALUE: {
- NOTREACHED() << "Got unexpected error code: " << service_worker_status
- << " " << ServiceWorkerStatusToString(service_worker_status);
+ case blink::ServiceWorkerStatusCode::kErrorAbort:
+ case blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorProcessNotFound:
+ case blink::ServiceWorkerStatusCode::kErrorExists:
+ case blink::ServiceWorkerStatusCode::kErrorInstallWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorActivateWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorIpcFailed:
+ case blink::ServiceWorkerStatusCode::kErrorNetwork:
+ case blink::ServiceWorkerStatusCode::kErrorSecurity:
+ case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
+ case blink::ServiceWorkerStatusCode::kErrorState:
+ case blink::ServiceWorkerStatusCode::kErrorTimeout:
+ case blink::ServiceWorkerStatusCode::kErrorScriptEvaluateFailed:
+ case blink::ServiceWorkerStatusCode::kErrorDiskCache:
+ case blink::ServiceWorkerStatusCode::kErrorRedundant:
+ case blink::ServiceWorkerStatusCode::kErrorDisallowed: {
+ NOTREACHED() << "Got unexpected error code: "
+ << static_cast<uint32_t>(service_worker_status) << " "
+ << blink::ServiceWorkerStatusToString(service_worker_status);
get_status = mojom::PushGetRegistrationStatus::STORAGE_ERROR;
break;
}
diff --git a/chromium/content/browser/push_messaging/push_messaging_manager.h b/chromium/content/browser/push_messaging/push_messaging_manager.h
index e064154aa01..36ce6e248b9 100644
--- a/chromium/content/browser/push_messaging/push_messaging_manager.h
+++ b/chromium/content/browser/push_messaging/push_messaging_manager.h
@@ -14,9 +14,9 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "content/common/push_messaging.mojom.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/binding_set.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
namespace content {
@@ -65,11 +65,12 @@ class PushMessagingManager : public mojom::PushMessaging {
void DidCheckForExistingRegistration(
RegisterData data,
const std::vector<std::string>& subscription_id_and_sender_id,
- ServiceWorkerStatusCode service_worker_status);
+ blink::ServiceWorkerStatusCode service_worker_status);
- void DidGetSenderIdFromStorage(RegisterData data,
- const std::vector<std::string>& sender_id,
- ServiceWorkerStatusCode service_worker_status);
+ void DidGetSenderIdFromStorage(
+ RegisterData data,
+ const std::vector<std::string>& sender_id,
+ blink::ServiceWorkerStatusCode service_worker_status);
// Called via PostTask from UI thread.
void PersistRegistrationOnIO(RegisterData data,
@@ -84,7 +85,7 @@ class PushMessagingManager : public mojom::PushMessaging {
const std::vector<uint8_t>& p256dh,
const std::vector<uint8_t>& auth,
mojom::PushRegistrationStatus push_registration_status,
- ServiceWorkerStatusCode service_worker_status);
+ blink::ServiceWorkerStatusCode service_worker_status);
// Called both from IO thread, and via PostTask from UI thread.
void SendSubscriptionError(RegisterData data,
@@ -101,7 +102,7 @@ class PushMessagingManager : public mojom::PushMessaging {
int64_t service_worker_registration_id,
const GURL& requesting_origin,
const std::vector<std::string>& sender_id,
- ServiceWorkerStatusCode service_worker_status);
+ blink::ServiceWorkerStatusCode service_worker_status);
// Called both from IO thread, and via PostTask from UI thread.
void DidUnregister(UnsubscribeCallback callback,
@@ -111,7 +112,7 @@ class PushMessagingManager : public mojom::PushMessaging {
GetSubscriptionCallback callback,
int64_t service_worker_registration_id,
const std::vector<std::string>& push_subscription_id_and_sender_info,
- ServiceWorkerStatusCode service_worker_status);
+ blink::ServiceWorkerStatusCode service_worker_status);
// Helper methods on either thread -------------------------------------------
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.cc b/chromium/content/browser/push_messaging/push_messaging_router.cc
index 05e3d73578d..a648b5d11fa 100644
--- a/chromium/content/browser/push_messaging/push_messaging_router.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_router.cc
@@ -12,12 +12,12 @@
#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"
#include "content/public/common/push_messaging_status.mojom.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
@@ -75,18 +75,17 @@ void PushMessagingRouter::FindServiceWorkerRegistration(
void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
const PushEventPayload& payload,
const DeliverMessageCallback& deliver_message_callback,
- ServiceWorkerStatusCode service_worker_status,
+ blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus.FindServiceWorker",
- service_worker_status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
- if (service_worker_status == SERVICE_WORKER_ERROR_NOT_FOUND) {
+ service_worker_status);
+ if (service_worker_status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
RunDeliverCallback(deliver_message_callback,
mojom::PushDeliveryStatus::NO_SERVICE_WORKER);
return;
}
- if (service_worker_status != SERVICE_WORKER_OK) {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
RunDeliverCallback(deliver_message_callback,
mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR);
return;
@@ -112,9 +111,9 @@ void PushMessagingRouter::DeliverMessageToWorker(
const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
const PushEventPayload& payload,
const DeliverMessageCallback& deliver_message_callback,
- ServiceWorkerStatusCode start_worker_status) {
+ blink::ServiceWorkerStatusCode start_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (start_worker_status != SERVICE_WORKER_OK) {
+ if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
DeliverMessageEnd(deliver_message_callback, service_worker_registration,
start_worker_status);
return;
@@ -127,7 +126,7 @@ void PushMessagingRouter::DeliverMessageToWorker(
base::TimeDelta::FromSeconds(mojom::kPushEventTimeoutSeconds),
ServiceWorkerVersion::KILL_ON_TIMEOUT);
- service_worker->event_dispatcher()->DispatchPushEvent(
+ service_worker->endpoint()->DispatchPushEvent(
payload, service_worker->CreateSimpleEventCallback(request_id));
}
@@ -135,44 +134,43 @@ void PushMessagingRouter::DeliverMessageToWorker(
void PushMessagingRouter::DeliverMessageEnd(
const DeliverMessageCallback& deliver_message_callback,
const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
- ServiceWorkerStatusCode service_worker_status) {
+ blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus.ServiceWorkerEvent",
- service_worker_status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
+ service_worker_status);
mojom::PushDeliveryStatus delivery_status =
mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR;
switch (service_worker_status) {
- case SERVICE_WORKER_OK:
+ case blink::ServiceWorkerStatusCode::kOk:
delivery_status = mojom::PushDeliveryStatus::SUCCESS;
break;
- case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED:
+ case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
delivery_status = mojom::PushDeliveryStatus::EVENT_WAITUNTIL_REJECTED;
break;
- case SERVICE_WORKER_ERROR_TIMEOUT:
+ case blink::ServiceWorkerStatusCode::kErrorTimeout:
delivery_status = mojom::PushDeliveryStatus::TIMEOUT;
break;
- case SERVICE_WORKER_ERROR_FAILED:
- case SERVICE_WORKER_ERROR_ABORT:
- case SERVICE_WORKER_ERROR_START_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND:
- case SERVICE_WORKER_ERROR_NOT_FOUND:
- case SERVICE_WORKER_ERROR_IPC_FAILED:
- case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED:
- case SERVICE_WORKER_ERROR_DISK_CACHE:
- case SERVICE_WORKER_ERROR_REDUNDANT:
- case SERVICE_WORKER_ERROR_DISALLOWED:
+ case blink::ServiceWorkerStatusCode::kErrorFailed:
+ case blink::ServiceWorkerStatusCode::kErrorAbort:
+ case blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorProcessNotFound:
+ case blink::ServiceWorkerStatusCode::kErrorNotFound:
+ case blink::ServiceWorkerStatusCode::kErrorIpcFailed:
+ case blink::ServiceWorkerStatusCode::kErrorScriptEvaluateFailed:
+ case blink::ServiceWorkerStatusCode::kErrorDiskCache:
+ case blink::ServiceWorkerStatusCode::kErrorRedundant:
+ case blink::ServiceWorkerStatusCode::kErrorDisallowed:
delivery_status = mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR;
break;
- case SERVICE_WORKER_ERROR_EXISTS:
- case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_NETWORK:
- case SERVICE_WORKER_ERROR_SECURITY:
- case SERVICE_WORKER_ERROR_STATE:
- case SERVICE_WORKER_ERROR_MAX_VALUE:
- NOTREACHED() << "Got unexpected error code: " << service_worker_status
- << " " << ServiceWorkerStatusToString(service_worker_status);
+ case blink::ServiceWorkerStatusCode::kErrorExists:
+ case blink::ServiceWorkerStatusCode::kErrorInstallWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorActivateWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorNetwork:
+ case blink::ServiceWorkerStatusCode::kErrorSecurity:
+ case blink::ServiceWorkerStatusCode::kErrorState:
+ NOTREACHED() << "Got unexpected error code: "
+ << static_cast<uint32_t>(service_worker_status) << " "
+ << blink::ServiceWorkerStatusToString(service_worker_status);
delivery_status = mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR;
break;
}
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.h b/chromium/content/browser/push_messaging/push_messaging_router.h
index e2ae5da2242..71bb530f425 100644
--- a/chromium/content/browser/push_messaging/push_messaging_router.h
+++ b/chromium/content/browser/push_messaging/push_messaging_router.h
@@ -10,7 +10,7 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
namespace content {
@@ -56,7 +56,7 @@ class PushMessagingRouter {
static void FindServiceWorkerRegistrationCallback(
const PushEventPayload& payload,
const DeliverMessageCallback& deliver_message_callback,
- ServiceWorkerStatusCode service_worker_status,
+ blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration);
// Delivers a push message with |data| to a specific |service_worker|.
@@ -67,7 +67,7 @@ class PushMessagingRouter {
service_worker_registration,
const PushEventPayload& payload,
const DeliverMessageCallback& deliver_message_callback,
- ServiceWorkerStatusCode start_worker_status);
+ blink::ServiceWorkerStatusCode start_worker_status);
// Gets called asynchronously after the Service Worker has dispatched the push
// event. Must be called on the IO thread.
@@ -75,7 +75,7 @@ class PushMessagingRouter {
const DeliverMessageCallback& deliver_message_callback,
const scoped_refptr<ServiceWorkerRegistration>&
service_worker_registration,
- ServiceWorkerStatusCode service_worker_status);
+ blink::ServiceWorkerStatusCode service_worker_status);
DISALLOW_IMPLICIT_CONSTRUCTORS(PushMessagingRouter);
};
diff --git a/chromium/content/browser/renderer_host/OWNERS b/chromium/content/browser/renderer_host/OWNERS
index d671fbdac2c..5108375b6e4 100644
--- a/chromium/content/browser/renderer_host/OWNERS
+++ b/chromium/content/browser/renderer_host/OWNERS
@@ -11,6 +11,10 @@ asvitkine@chromium.org
kbr@chromium.org
ccameron@chromium.org
+# for *android*
+per-file *android*=ericrk@chromium.org
+per-file *android*=khushalsagar@chromium.org
+
# For touch/gesture specific changes
rjkroege@chromium.org
sadrul@chromium.org
diff --git a/chromium/content/browser/renderer_host/browser_compositor_view_mac.h b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
index bc9eba153a6..46be85eea4b 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -20,12 +20,11 @@
namespace ui {
class AcceleratedWidgetMacNSView;
+class RecyclableCompositorMac;
}
namespace content {
-class RecyclableCompositorMac;
-
class BrowserCompositorMacClient {
public:
virtual SkColor BrowserCompositorMacGetGutterColor() const = 0;
@@ -33,7 +32,9 @@ class BrowserCompositorMacClient {
virtual void OnFrameTokenChanged(uint32_t frame_token) = 0;
virtual void DidReceiveFirstFrameAfterNavigation() = 0;
virtual void DestroyCompositorForShutdown() = 0;
- virtual bool SynchronizeVisualProperties() = 0;
+ virtual bool SynchronizeVisualProperties(
+ const base::Optional<viz::LocalSurfaceId>&
+ child_allocated_local_surface_id) = 0;
};
// This class owns a DelegatedFrameHost, and will dynamically attach and
@@ -51,7 +52,6 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view,
BrowserCompositorMacClient* client,
bool render_widget_host_is_hidden,
- bool ns_view_attached_to_window,
const display::Display& initial_display,
const viz::FrameSinkId& frame_sink_id);
~BrowserCompositorMac() override;
@@ -69,7 +69,6 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
// no valid frame is available.
const gfx::CALayerParams* GetLastCALayerParams() const;
- gfx::AcceleratedWidget GetAcceleratedWidget();
void DidCreateNewRendererCompositorFrameSink(
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink);
void OnDidNotProduceFrame(const viz::BeginFrameAck& ack);
@@ -90,6 +89,7 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
// Update the renderer's SurfaceId to reflect |new_size_in_pixels| in
// anticipation of the NSView resizing during auto-resize.
void SynchronizeVisualProperties(
+ float new_device_scale_factor,
const gfx::Size& new_size_in_pixels,
const viz::LocalSurfaceId& child_allocated_local_surface_id);
@@ -105,6 +105,9 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
// hidden (e.g, because it is occluded by another window).
void SetNSViewAttachedToWindow(bool attached);
+ // Specify if the ui::Layer should be visible or not.
+ void SetViewVisible(bool visible);
+
// Sets or clears the parent ui::Layer and updates state to reflect that
// we are now using the ui::Compositor from |parent_ui_layer| (if non-nullptr)
// or one from |recyclable_compositor_| (if a compositor is needed).
@@ -117,8 +120,10 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
viz::ScopedSurfaceIdAllocator GetScopedRendererSurfaceIdAllocator(
base::OnceCallback<void()> allocation_task);
const viz::LocalSurfaceId& GetRendererLocalSurfaceId();
+ const viz::LocalSurfaceId& AllocateNewRendererLocalSurfaceId();
bool UpdateRendererLocalSurfaceIdFromChild(
const viz::LocalSurfaceId& child_allocated_local_surface_id);
+ void TransformPointToRootSurface(gfx::PointF* point);
// Indicate that the recyclable compositor should be destroyed, and no future
// compositors should be recycled.
@@ -139,8 +144,6 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
void DidNavigate();
- void BeginPauseForFrame(bool auto_resize_enabled);
- void EndPauseForFrame();
bool ShouldContinueToPauseForFrame() const;
bool ForceNewSurfaceForTesting();
@@ -151,7 +154,7 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
// ui::LayerObserver implementation:
void LayerDestroyed(ui::Layer* layer) override;
- cc::DeadlinePolicy GetDeadlinePolicy() const;
+ cc::DeadlinePolicy GetDeadlinePolicy(bool is_resize) const;
// The state of |delegated_frame_host_| and |recyclable_compositor_| to
// manage being visible, occluded, hidden, or drawn via a ui::Layer. Note that
@@ -197,14 +200,15 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
// Weak pointer to the layer supplied and reset via SetParentUiLayer. |this|
// is an observer of |parent_ui_layer_|, to ensure that |parent_ui_layer_|
- // always be valid when non-null.
+ // always be valid when non-null. The UpdateState function will re-parent
+ // |root_layer_| to be under |parent_ui_layer_|, if needed.
ui::Layer* parent_ui_layer_ = nullptr;
bool render_widget_host_is_hidden_ = true;
bool ns_view_attached_to_window_ = false;
BrowserCompositorMacClient* client_ = nullptr;
ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view_ = nullptr;
- std::unique_ptr<RecyclableCompositorMac> recyclable_compositor_;
+ std::unique_ptr<ui::RecyclableCompositorMac> recyclable_compositor_;
std::unique_ptr<DelegatedFrameHost> delegated_frame_host_;
std::unique_ptr<ui::Layer> root_layer_;
@@ -221,18 +225,6 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
gfx::Size dfh_size_dip_;
display::Display dfh_display_;
- // Used to disable screen updates while resizing (because frames are drawn in
- // the GPU process, they can end up appearing on-screen before our window
- // resizes).
- enum class RepaintState {
- // No repaint in progress.
- None,
- // Synchronously waiting for a new frame.
- Paused,
- // Screen updates are disabled while a new frame is swapped in.
- ScreenUpdatesDisabled,
- } repaint_state_ = RepaintState::None;
- bool repaint_auto_resize_enabled_ = false;
bool is_first_navigation_ = true;
base::WeakPtrFactory<BrowserCompositorMac> weak_factory_;
diff --git a/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
index 3d12a1126a0..92afcc77910 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -20,6 +20,7 @@
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#include "ui/base/layout.h"
+#include "ui/compositor/recyclable_compositor_mac.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/dip_util.h"
@@ -37,170 +38,15 @@ namespace {
base::LazyInstance<std::set<BrowserCompositorMac*>>::Leaky
g_browser_compositors;
-// A spare RecyclableCompositorMac kept around for recycling.
-base::LazyInstance<base::circular_deque<
- std::unique_ptr<RecyclableCompositorMac>>>::DestructorAtExit
- g_spare_recyclable_compositors;
-
-void ReleaseSpareCompositors() {
- // Allow at most one spare recyclable compositor.
- while (g_spare_recyclable_compositors.Get().size() > 1)
- g_spare_recyclable_compositors.Get().pop_front();
-
- if (g_browser_compositors.Get().empty())
- g_spare_recyclable_compositors.Get().clear();
-}
-
} // namespace
////////////////////////////////////////////////////////////////////////////////
-// RecyclableCompositorMac
-
-// A ui::Compositor and a gfx::AcceleratedWidget (and helper) that it draws
-// into. This structure is used to efficiently recycle these structures across
-// tabs (because creating a new ui::Compositor for each tab would be expensive
-// in terms of time and resources).
-class RecyclableCompositorMac : public ui::CompositorObserver {
- public:
- ~RecyclableCompositorMac() override;
-
- // Create a compositor, or recycle a preexisting one.
- static std::unique_ptr<RecyclableCompositorMac> Create();
-
- // Delete a compositor, or allow it to be recycled.
- static void Recycle(std::unique_ptr<RecyclableCompositorMac> compositor);
-
- ui::Compositor* compositor() { return &compositor_; }
- ui::AcceleratedWidgetMac* accelerated_widget_mac() {
- return accelerated_widget_mac_.get();
- }
- const gfx::Size pixel_size() const { return size_pixels_; }
- float scale_factor() const { return scale_factor_; }
-
- // Suspend will prevent the compositor from producing new frames. This should
- // be called to avoid creating spurious frames while changing state.
- // Compositors are created as suspended.
- void Suspend();
- void Unsuspend();
-
- // Update the compositor's surface information, if needed.
- void UpdateSurface(const gfx::Size& size_pixels, float scale_factor);
- // Invalidate the compositor's surface information.
- void InvalidateSurface();
-
- // The viz::ParentLocalSurfaceIdAllocator for the ui::Compositor dispenses
- // viz::LocalSurfaceIds that are renderered into by the ui::Compositor.
- viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
- gfx::Size size_pixels_;
- float scale_factor_ = 1.f;
-
- private:
- RecyclableCompositorMac();
-
- // ui::CompositorObserver implementation:
- void OnCompositingDidCommit(ui::Compositor* compositor) override;
- void OnCompositingStarted(ui::Compositor* compositor,
- base::TimeTicks start_time) override {}
- void OnCompositingEnded(ui::Compositor* compositor) override {}
- void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
- void OnCompositingChildResizing(ui::Compositor* compositor) override {}
- void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
-
- std::unique_ptr<ui::AcceleratedWidgetMac> accelerated_widget_mac_;
- ui::Compositor compositor_;
- std::unique_ptr<ui::CompositorLock> compositor_suspended_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(RecyclableCompositorMac);
-};
-
-RecyclableCompositorMac::RecyclableCompositorMac()
- : accelerated_widget_mac_(new ui::AcceleratedWidgetMac()),
- compositor_(content::GetContextFactoryPrivate()->AllocateFrameSinkId(),
- content::GetContextFactory(),
- content::GetContextFactoryPrivate(),
- ui::WindowResizeHelperMac::Get()->task_runner(),
- features::IsSurfaceSynchronizationEnabled(),
- false /* enable_pixel_canvas */) {
- compositor_.SetAcceleratedWidget(
- accelerated_widget_mac_->accelerated_widget());
- Suspend();
- compositor_.AddObserver(this);
-}
-
-RecyclableCompositorMac::~RecyclableCompositorMac() {
- compositor_.RemoveObserver(this);
-}
-
-void RecyclableCompositorMac::Suspend() {
- // Requests a compositor lock without a timeout.
- compositor_suspended_lock_ =
- compositor_.GetCompositorLock(nullptr, base::TimeDelta());
-}
-
-void RecyclableCompositorMac::Unsuspend() {
- compositor_suspended_lock_ = nullptr;
-}
-
-void RecyclableCompositorMac::UpdateSurface(const gfx::Size& size_pixels,
- float scale_factor) {
- if (size_pixels != size_pixels_ || scale_factor != scale_factor_) {
- size_pixels_ = size_pixels;
- scale_factor_ = scale_factor;
- compositor()->SetScaleAndSize(scale_factor_, size_pixels_,
- local_surface_id_allocator_.GenerateId());
- }
-}
-
-void RecyclableCompositorMac::InvalidateSurface() {
- size_pixels_ = gfx::Size();
- scale_factor_ = 1.f;
- local_surface_id_allocator_.Invalidate();
- compositor()->SetScaleAndSize(
- scale_factor_, size_pixels_,
- local_surface_id_allocator_.GetCurrentLocalSurfaceId());
-}
-
-void RecyclableCompositorMac::OnCompositingDidCommit(
- ui::Compositor* compositor_that_did_commit) {
- DCHECK_EQ(compositor_that_did_commit, compositor());
- accelerated_widget_mac_->SetSuspended(false);
-}
-
-// static
-std::unique_ptr<RecyclableCompositorMac> RecyclableCompositorMac::Create() {
- DCHECK(ui::WindowResizeHelperMac::Get()->task_runner());
- if (!g_spare_recyclable_compositors.Get().empty()) {
- std::unique_ptr<RecyclableCompositorMac> result;
- result = std::move(g_spare_recyclable_compositors.Get().back());
- g_spare_recyclable_compositors.Get().pop_back();
- return result;
- }
- return std::unique_ptr<RecyclableCompositorMac>(new RecyclableCompositorMac);
-}
-
-// static
-void RecyclableCompositorMac::Recycle(
- std::unique_ptr<RecyclableCompositorMac> compositor) {
- compositor->accelerated_widget_mac_->SetSuspended(true);
-
- // Make this RecyclableCompositorMac recyclable for future instances.
- g_spare_recyclable_compositors.Get().push_back(std::move(compositor));
-
- // Post a task to free up the spare ui::Compositors when needed. Post this
- // to the browser main thread so that we won't free any compositors while
- // in a nested loop waiting to put up a new frame.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(&ReleaseSpareCompositors));
-}
-
-////////////////////////////////////////////////////////////////////////////////
// BrowserCompositorMac
BrowserCompositorMac::BrowserCompositorMac(
ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view,
BrowserCompositorMacClient* client,
bool render_widget_host_is_hidden,
- bool ns_view_attached_to_window,
const display::Display& initial_display,
const viz::FrameSinkId& frame_sink_id)
: client_(client),
@@ -219,7 +65,7 @@ BrowserCompositorMac::BrowserCompositorMac(
true /* should_register_frame_sink_id */));
SetRenderWidgetHostIsHidden(render_widget_host_is_hidden);
- SetNSViewAttachedToWindow(ns_view_attached_to_window);
+ SetNSViewAttachedToWindow(false);
}
BrowserCompositorMac::~BrowserCompositorMac() {
@@ -233,19 +79,6 @@ BrowserCompositorMac::~BrowserCompositorMac() {
size_t num_erased = g_browser_compositors.Get().erase(this);
DCHECK_EQ(1u, num_erased);
-
- // If there are no compositors allocated, destroy the recyclable
- // RecyclableCompositorMac.
- if (g_browser_compositors.Get().empty())
- g_spare_recyclable_compositors.Get().clear();
-}
-
-gfx::AcceleratedWidget BrowserCompositorMac::GetAcceleratedWidget() {
- if (recyclable_compositor_) {
- return recyclable_compositor_->accelerated_widget_mac()
- ->accelerated_widget();
- }
- return gfx::kNullAcceleratedWidget;
}
DelegatedFrameHost* BrowserCompositorMac::GetDelegatedFrameHost() {
@@ -267,16 +100,16 @@ void BrowserCompositorMac::ClearCompositorFrame() {
bool BrowserCompositorMac::RequestRepaintForTesting() {
const viz::LocalSurfaceId& new_local_surface_id =
dfh_local_surface_id_allocator_.GenerateId();
- delegated_frame_host_->SynchronizeVisualProperties(
+ delegated_frame_host_->EmbedSurface(
new_local_surface_id, dfh_size_dip_,
cc::DeadlinePolicy::UseExistingDeadline());
- return client_->SynchronizeVisualProperties();
+ return client_->SynchronizeVisualProperties(new_local_surface_id);
}
const gfx::CALayerParams* BrowserCompositorMac::GetLastCALayerParams() const {
if (!recyclable_compositor_)
return nullptr;
- return recyclable_compositor_->accelerated_widget_mac()->GetCALayerParams();
+ return recyclable_compositor_->widget()->GetCALayerParams();
}
viz::FrameSinkId BrowserCompositorMac::GetRootFrameSinkId() {
@@ -310,6 +143,8 @@ bool BrowserCompositorMac::UpdateNSViewAndDisplay(
if (new_size_dip == dfh_size_dip_ && new_display == dfh_display_)
return false;
+ bool is_resize = !dfh_size_dip_.IsEmpty() && new_size_dip != dfh_size_dip_;
+
bool needs_new_surface_id =
new_size_dip != dfh_size_dip_ ||
new_display.device_scale_factor() != dfh_display_.device_scale_factor();
@@ -323,9 +158,9 @@ bool BrowserCompositorMac::UpdateNSViewAndDisplay(
if (needs_new_surface_id) {
if (recyclable_compositor_)
recyclable_compositor_->Suspend();
- GetDelegatedFrameHost()->SynchronizeVisualProperties(
+ GetDelegatedFrameHost()->EmbedSurface(
dfh_local_surface_id_allocator_.GenerateId(), dfh_size_dip_,
- GetDeadlinePolicy());
+ GetDeadlinePolicy(is_resize));
}
if (recyclable_compositor_) {
@@ -339,10 +174,12 @@ bool BrowserCompositorMac::UpdateNSViewAndDisplay(
}
void BrowserCompositorMac::SynchronizeVisualProperties(
+ float new_device_scale_factor,
const gfx::Size& new_size_in_pixels,
const viz::LocalSurfaceId& child_allocated_local_surface_id) {
if (dfh_local_surface_id_allocator_.UpdateFromChild(
child_allocated_local_surface_id)) {
+ dfh_display_.set_device_scale_factor(new_device_scale_factor);
dfh_size_dip_ = gfx::ConvertSizeToDIP(dfh_display_.device_scale_factor(),
new_size_in_pixels);
dfh_size_pixels_ = new_size_in_pixels;
@@ -351,20 +188,29 @@ void BrowserCompositorMac::SynchronizeVisualProperties(
recyclable_compositor_->UpdateSurface(dfh_size_pixels_,
dfh_display_.device_scale_factor());
}
- GetDelegatedFrameHost()->SynchronizeVisualProperties(
+ GetDelegatedFrameHost()->EmbedSurface(
dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
- dfh_size_dip_, GetDeadlinePolicy());
+ dfh_size_dip_, GetDeadlinePolicy(true /* is_resize */));
}
- client_->SynchronizeVisualProperties();
+ client_->SynchronizeVisualProperties(child_allocated_local_surface_id);
}
void BrowserCompositorMac::UpdateVSyncParameters(
const base::TimeTicks& timebase,
const base::TimeDelta& interval) {
- if (recyclable_compositor_) {
- recyclable_compositor_->compositor()->SetDisplayVSyncParameters(
- timebase, interval);
- }
+ ui::Compositor* compositor = nullptr;
+ if (recyclable_compositor_)
+ compositor = recyclable_compositor_->compositor();
+ // TODO(ccameron): VSync parameters for a ui::Compositor should be tracked
+ // with the owner of that ui::Compositor (which, in the case of MacViews, is
+ // BridgedNativeView). For the moment, push the VSync parameters from here to
+ // the BridgedNativeView's ui::Compositor because that is a small change and
+ // is easy to merge.
+ // https://crbug.com/869129
+ if (parent_ui_layer_)
+ compositor = parent_ui_layer_->GetCompositor();
+ if (compositor)
+ compositor->SetDisplayVSyncParameters(timebase, interval);
}
void BrowserCompositorMac::SetRenderWidgetHostIsHidden(bool hidden) {
@@ -377,6 +223,10 @@ void BrowserCompositorMac::SetNSViewAttachedToWindow(bool attached) {
UpdateState();
}
+void BrowserCompositorMac::SetViewVisible(bool visible) {
+ root_layer_->SetVisible(visible);
+}
+
void BrowserCompositorMac::UpdateState() {
// Always use the parent ui::Layer's ui::Compositor if available.
if (parent_ui_layer_) {
@@ -405,9 +255,12 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
// Note that the state enum values represent the other through which
// transitions must be done (see comments in State definition).
- // Transition UseParentLayerCompositor -> HasNoCompositor.
+ // Transition UseParentLayerCompositor -> HasNoCompositor. Note that this
+ // transition will be made if we are already in UseParentLayerCompositor, but
+ // with a different parent layer.
if (state_ == UseParentLayerCompositor &&
- new_state < UseParentLayerCompositor) {
+ (new_state < UseParentLayerCompositor ||
+ parent_ui_layer_ != root_layer_->parent())) {
DCHECK(root_layer_->parent());
root_layer_->parent()->RemoveObserver(this);
root_layer_->parent()->Remove(root_layer_.get());
@@ -418,14 +271,16 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
// Transition HasNoCompositor -> HasDetachedCompositor.
if (state_ == HasNoCompositor && new_state < HasNoCompositor) {
- recyclable_compositor_ = RecyclableCompositorMac::Create();
+ recyclable_compositor_ =
+ ui::RecyclableCompositorMacFactory::Get()->CreateCompositor(
+ content::GetContextFactory(), content::GetContextFactoryPrivate());
recyclable_compositor_->UpdateSurface(dfh_size_pixels_,
dfh_display_.device_scale_factor());
recyclable_compositor_->compositor()->SetRootLayer(root_layer_.get());
recyclable_compositor_->compositor()->SetBackgroundColor(background_color_);
recyclable_compositor_->compositor()->SetDisplayColorSpace(
dfh_display_.color_space());
- recyclable_compositor_->accelerated_widget_mac()->SetNSView(
+ recyclable_compositor_->widget()->SetNSView(
accelerated_widget_mac_ns_view_);
state_ = HasDetachedCompositor;
}
@@ -434,7 +289,7 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
if (state_ == HasDetachedCompositor && new_state < HasDetachedCompositor) {
delegated_frame_host_->SetCompositor(recyclable_compositor_->compositor());
delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
- ui::LatencyInfo());
+ false /* record_presentation_time */);
// If there exists a saved frame ready to display, unsuspend the compositor
// now (if one is not ready, the compositor will unsuspend on first surface
@@ -459,10 +314,11 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
// Transition HasDetachedCompositor -> HasNoCompositor.
if (state_ == HasDetachedCompositor && new_state > HasDetachedCompositor) {
- recyclable_compositor_->accelerated_widget_mac()->ResetNSView();
+ recyclable_compositor_->widget()->ResetNSView();
recyclable_compositor_->compositor()->SetRootLayer(nullptr);
recyclable_compositor_->InvalidateSurface();
- RecyclableCompositorMac::Recycle(std::move(recyclable_compositor_));
+ ui::RecyclableCompositorMacFactory::Get()->RecycleCompositor(
+ std::move(recyclable_compositor_));
state_ = HasNoCompositor;
}
@@ -473,7 +329,7 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
DCHECK(!root_layer_->parent());
delegated_frame_host_->SetCompositor(parent_ui_layer_->GetCompositor());
delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
- ui::LatencyInfo());
+ false /* record_presentation_time */);
parent_ui_layer_->Add(root_layer_.get());
parent_ui_layer_->AddObserver(this);
state_ = UseParentLayerCompositor;
@@ -490,7 +346,8 @@ void BrowserCompositorMac::DisableRecyclingForShutdown() {
*g_browser_compositors.Get().begin();
browser_compositor->client_->DestroyCompositorForShutdown();
}
- g_spare_recyclable_compositors.Get().clear();
+
+ ui::RecyclableCompositorMacFactory::Get()->DisableRecyclingForShutdown();
}
void BrowserCompositorMac::SetNeedsBeginFrames(bool needs_begin_frames) {
@@ -534,19 +391,6 @@ void BrowserCompositorMac::OnFirstSurfaceActivation(
return;
recyclable_compositor_->Unsuspend();
-
- // Disable screen updates until the frame of the new size appears (because the
- // content is drawn in the GPU process, it may change before we want it to).
- if (repaint_state_ == RepaintState::Paused) {
- bool compositor_is_nsview_size =
- recyclable_compositor_->pixel_size() == dfh_size_pixels_ &&
- recyclable_compositor_->scale_factor() ==
- dfh_display_.device_scale_factor();
- if (compositor_is_nsview_size || repaint_auto_resize_enabled_) {
- NSDisableScreenUpdates();
- repaint_state_ = RepaintState::ScreenUpdatesDisabled;
- }
- }
}
void BrowserCompositorMac::OnBeginFrame(base::TimeTicks frame_time) {
@@ -564,10 +408,10 @@ void BrowserCompositorMac::DidNavigate() {
dfh_local_surface_id_allocator_.GenerateId();
const viz::LocalSurfaceId& local_surface_id =
dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
- delegated_frame_host_->SynchronizeVisualProperties(
+ delegated_frame_host_->EmbedSurface(
local_surface_id, dfh_size_dip_,
cc::DeadlinePolicy::UseExistingDeadline());
- client_->SynchronizeVisualProperties();
+ client_->SynchronizeVisualProperties(local_surface_id);
delegated_frame_host_->DidNavigate();
is_first_navigation_ = false;
}
@@ -576,17 +420,6 @@ void BrowserCompositorMac::DidReceiveFirstFrameAfterNavigation() {
client_->DidReceiveFirstFrameAfterNavigation();
}
-void BrowserCompositorMac::BeginPauseForFrame(bool auto_resize_enabled) {
- repaint_auto_resize_enabled_ = auto_resize_enabled;
- repaint_state_ = RepaintState::Paused;
-}
-
-void BrowserCompositorMac::EndPauseForFrame() {
- if (repaint_state_ == RepaintState::ScreenUpdatesDisabled)
- NSEnableScreenUpdates();
- repaint_state_ = RepaintState::None;
-}
-
bool BrowserCompositorMac::ShouldContinueToPauseForFrame() const {
if (state_ == UseParentLayerCompositor)
return false;
@@ -599,21 +432,20 @@ bool BrowserCompositorMac::ShouldContinueToPauseForFrame() const {
if (!recyclable_compositor_)
return false;
- return !recyclable_compositor_->accelerated_widget_mac()->HasFrameOfSize(
- dfh_size_dip_);
+ return !recyclable_compositor_->widget()->HasFrameOfSize(dfh_size_dip_);
}
void BrowserCompositorMac::SetParentUiLayer(ui::Layer* new_parent_ui_layer) {
- if (new_parent_ui_layer) {
+ if (new_parent_ui_layer)
DCHECK(new_parent_ui_layer->GetCompositor());
- DCHECK(!parent_ui_layer_);
- parent_ui_layer_ = new_parent_ui_layer;
- } else if (parent_ui_layer_) {
- DCHECK(root_layer_->parent());
- DCHECK_EQ(root_layer_->parent(), parent_ui_layer_);
- parent_ui_layer_ = nullptr;
- }
+
+ // Set |parent_ui_layer_| to the new value, which potentially not match the
+ // value of |root_layer_->parent()|. The call to UpdateState will re-parent
+ // |root_layer_|.
+ DCHECK_EQ(root_layer_->parent(), parent_ui_layer_);
+ parent_ui_layer_ = new_parent_ui_layer;
UpdateState();
+ DCHECK_EQ(root_layer_->parent(), parent_ui_layer_);
}
bool BrowserCompositorMac::ForceNewSurfaceForTesting() {
@@ -641,12 +473,24 @@ const viz::LocalSurfaceId& BrowserCompositorMac::GetRendererLocalSurfaceId() {
return dfh_local_surface_id_allocator_.GenerateId();
}
+const viz::LocalSurfaceId&
+BrowserCompositorMac::AllocateNewRendererLocalSurfaceId() {
+ return dfh_local_surface_id_allocator_.GenerateId();
+}
+
bool BrowserCompositorMac::UpdateRendererLocalSurfaceIdFromChild(
const viz::LocalSurfaceId& child_allocated_local_surface_id) {
return dfh_local_surface_id_allocator_.UpdateFromChild(
child_allocated_local_surface_id);
}
+void BrowserCompositorMac::TransformPointToRootSurface(gfx::PointF* point) {
+ gfx::Transform transform_to_root;
+ if (parent_ui_layer_)
+ parent_ui_layer_->GetTargetTransformRelativeTo(nullptr, &transform_to_root);
+ transform_to_root.TransformPoint(point);
+}
+
void BrowserCompositorMac::LayerDestroyed(ui::Layer* layer) {
DCHECK_EQ(layer, parent_ui_layer_);
SetParentUiLayer(nullptr);
@@ -658,9 +502,12 @@ ui::Compositor* BrowserCompositorMac::GetCompositorForTesting() const {
return nullptr;
}
-cc::DeadlinePolicy BrowserCompositorMac::GetDeadlinePolicy() const {
- // Determined empirically for smoothness.
- uint32_t frames_to_wait = 8;
+cc::DeadlinePolicy BrowserCompositorMac::GetDeadlinePolicy(
+ bool is_resize) const {
+ // Determined empirically for smoothness. Don't wait for non-resize frames,
+ // as it can cause jank at new tab creation.
+ // https://crbug.com/855364
+ uint32_t frames_to_wait = is_resize ? 8 : 0;
// When using the RecyclableCompositor, never wait for frames to arrive
// (surface sync is managed by the Suspend/Unsuspend lock).
diff --git a/chromium/content/browser/renderer_host/clipboard_host_impl.cc b/chromium/content/browser/renderer_host/clipboard_host_impl.cc
index a951584df7c..60928166661 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl.cc
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl.cc
@@ -4,100 +4,30 @@
#include "content/browser/renderer_host/clipboard_host_impl.h"
-#include <limits>
#include <utility>
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/public/browser/blob_handle.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "ipc/ipc_message_macros.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
-#include "ui/gfx/codec/png_codec.h"
-#include "ui/gfx/geometry/size.h"
#include "url/gurl.h"
namespace content {
-namespace {
-void ReleaseSharedMemoryPixels(void* addr, void* context) {
- MojoResult result = MojoUnmapBuffer(context);
- DCHECK_EQ(MOJO_RESULT_OK, result);
-}
-
-void OnReadAndEncodeImageFinished(
- scoped_refptr<ChromeBlobStorageContext> blob_storage_context,
- std::vector<uint8_t> png_data,
- ClipboardHostImpl::ReadImageCallback callback) {
- // |blob_storage_context| must be accessed only on the IO thread.
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- blink::mojom::SerializedBlobPtr blob;
- if (png_data.size() < std::numeric_limits<uint32_t>::max()) {
- std::unique_ptr<content::BlobHandle> blob_handle =
- blob_storage_context->CreateMemoryBackedBlob(
- reinterpret_cast<char*>(png_data.data()), png_data.size(), "");
- if (blob_handle) {
- std::string blob_uuid = blob_handle->GetUUID();
- blob = blink::mojom::SerializedBlob::New(
- blob_uuid, ui::Clipboard::kMimeTypePNG,
- static_cast<int64_t>(png_data.size()),
- blob_handle->PassBlob().PassInterface());
- }
- }
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), std::move(blob)));
-}
-
-void ReadAndEncodeImage(
- scoped_refptr<ChromeBlobStorageContext> blob_storage_context,
- const SkBitmap& bitmap,
- ClipboardHostImpl::ReadImageCallback callback) {
- std::vector<uint8_t> png_data;
- if (!gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, &png_data)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), nullptr));
- return;
- }
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&OnReadAndEncodeImageFinished,
- std::move(blob_storage_context), std::move(png_data),
- std::move(callback)));
-}
-
-} // namespace
-
-ClipboardHostImpl::ClipboardHostImpl(
- scoped_refptr<ChromeBlobStorageContext> blob_storage_context)
+ClipboardHostImpl::ClipboardHostImpl()
: clipboard_(ui::Clipboard::GetForCurrentThread()),
- blob_storage_context_(std::move(blob_storage_context)),
clipboard_writer_(
- new ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
+ new ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)) {}
-void ClipboardHostImpl::Create(
- scoped_refptr<ChromeBlobStorageContext> blob_storage_context,
- blink::mojom::ClipboardHostRequest request) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+void ClipboardHostImpl::Create(blink::mojom::ClipboardHostRequest request) {
mojo::MakeStrongBinding(
- base::WrapUnique<ClipboardHostImpl>(
- new ClipboardHostImpl(std::move(blob_storage_context))),
+ base::WrapUnique<ClipboardHostImpl>(new ClipboardHostImpl()),
std::move(request));
}
@@ -107,14 +37,12 @@ ClipboardHostImpl::~ClipboardHostImpl() {
void ClipboardHostImpl::GetSequenceNumber(ui::ClipboardType clipboard_type,
GetSequenceNumberCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::move(callback).Run(clipboard_->GetSequenceNumber(clipboard_type));
}
void ClipboardHostImpl::ReadAvailableTypes(
ui::ClipboardType clipboard_type,
ReadAvailableTypesCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::vector<base::string16> types;
bool contains_filenames;
clipboard_->ReadAvailableTypes(clipboard_type, &types, &contains_filenames);
@@ -124,7 +52,6 @@ void ClipboardHostImpl::ReadAvailableTypes(
void ClipboardHostImpl::IsFormatAvailable(blink::mojom::ClipboardFormat format,
ui::ClipboardType clipboard_type,
IsFormatAvailableCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
bool result = false;
switch (format) {
case blink::mojom::ClipboardFormat::kPlaintext:
@@ -155,8 +82,6 @@ void ClipboardHostImpl::IsFormatAvailable(blink::mojom::ClipboardFormat format,
void ClipboardHostImpl::ReadText(ui::ClipboardType clipboard_type,
ReadTextCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
base::string16 result;
if (clipboard_->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
clipboard_type)) {
@@ -172,8 +97,6 @@ void ClipboardHostImpl::ReadText(ui::ClipboardType clipboard_type,
void ClipboardHostImpl::ReadHtml(ui::ClipboardType clipboard_type,
ReadHtmlCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
base::string16 markup;
std::string src_url_str;
uint32_t fragment_start = 0;
@@ -186,8 +109,6 @@ void ClipboardHostImpl::ReadHtml(ui::ClipboardType clipboard_type,
void ClipboardHostImpl::ReadRtf(ui::ClipboardType clipboard_type,
ReadRtfCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
std::string result;
clipboard_->ReadRTF(clipboard_type, &result);
std::move(callback).Run(result);
@@ -195,27 +116,13 @@ void ClipboardHostImpl::ReadRtf(ui::ClipboardType clipboard_type,
void ClipboardHostImpl::ReadImage(ui::ClipboardType clipboard_type,
ReadImageCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- SkBitmap bitmap = clipboard_->ReadImage(clipboard_type);
-
- if (bitmap.isNull()) {
- std::move(callback).Run(nullptr);
- return;
- }
- base::PostTaskWithTraits(
- FROM_HERE,
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
- base::BindOnce(&ReadAndEncodeImage, blob_storage_context_,
- std::move(bitmap), std::move(callback)));
+ SkBitmap result = clipboard_->ReadImage(clipboard_type);
+ std::move(callback).Run(result);
}
void ClipboardHostImpl::ReadCustomData(ui::ClipboardType clipboard_type,
const base::string16& type,
ReadCustomDataCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
base::string16 result;
clipboard_->ReadCustomData(clipboard_type, type, &result);
std::move(callback).Run(result);
@@ -223,26 +130,22 @@ void ClipboardHostImpl::ReadCustomData(ui::ClipboardType clipboard_type,
void ClipboardHostImpl::WriteText(ui::ClipboardType,
const base::string16& text) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
clipboard_writer_->WriteText(text);
}
void ClipboardHostImpl::WriteHtml(ui::ClipboardType,
const base::string16& markup,
const GURL& url) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
clipboard_writer_->WriteHTML(markup, url.spec());
}
void ClipboardHostImpl::WriteSmartPasteMarker(ui::ClipboardType) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
clipboard_writer_->WriteWebSmartPaste();
}
void ClipboardHostImpl::WriteCustomData(
ui::ClipboardType,
const base::flat_map<base::string16, base::string16>& data) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::Pickle pickle;
ui::WriteCustomDataToPickle(data, &pickle);
clipboard_writer_->WritePickledData(
@@ -252,41 +155,14 @@ void ClipboardHostImpl::WriteCustomData(
void ClipboardHostImpl::WriteBookmark(ui::ClipboardType,
const std::string& url,
const base::string16& title) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
clipboard_writer_->WriteBookmark(title, url);
}
-void ClipboardHostImpl::WriteImage(
- ui::ClipboardType,
- const gfx::Size& size,
- mojo::ScopedSharedBufferHandle shared_buffer_handle) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- SkBitmap bitmap;
- // Let Skia do some sanity checking for (no negative widths/heights, no
- // overflows while calculating bytes per row, etc).
- if (!bitmap.setInfo(
- SkImageInfo::MakeN32Premul(size.width(), size.height()))) {
- return;
- }
-
- auto mapped = shared_buffer_handle->Map(bitmap.computeByteSize());
- if (!mapped) {
- return;
- }
-
- if (!bitmap.installPixels(bitmap.info(), mapped.get(), bitmap.rowBytes(),
- &ReleaseSharedMemoryPixels, mapped.get())) {
- return;
- }
-
- // On success, SkBitmap now owns the SharedMemory.
- mapped.release();
+void ClipboardHostImpl::WriteImage(ui::ClipboardType, const SkBitmap& bitmap) {
clipboard_writer_->WriteImage(bitmap);
}
void ClipboardHostImpl::CommitWrite(ui::ClipboardType) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
clipboard_writer_.reset(
new ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE));
}
diff --git a/chromium/content/browser/renderer_host/clipboard_host_impl.h b/chromium/content/browser/renderer_host/clipboard_host_impl.h
index 7199ebced1b..f9c6a3db4af 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl.h
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl.h
@@ -5,50 +5,35 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_CLIPBOARD_HOST_IMPL_H_
#define CONTENT_BROWSER_RENDERER_HOST_CLIPBOARD_HOST_IMPL_H_
-#include <stdint.h>
-
#include <memory>
#include <string>
-#include <vector>
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/shared_memory.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
-#include "content/public/browser/browser_associated_interface.h"
-#include "content/public/browser/browser_message_filter.h"
#include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
#include "ui/base/clipboard/clipboard.h"
class GURL;
-namespace gfx {
-class Size;
-}
-
namespace ui {
class ScopedClipboardWriter;
} // namespace ui
namespace content {
-class ChromeBlobStorageContext;
class ClipboardHostImplTest;
class CONTENT_EXPORT ClipboardHostImpl : public blink::mojom::ClipboardHost {
public:
~ClipboardHostImpl() override;
- static void Create(
- scoped_refptr<ChromeBlobStorageContext> blob_storage_context,
- blink::mojom::ClipboardHostRequest request);
+ static void Create(blink::mojom::ClipboardHostRequest request);
private:
friend class ClipboardHostImplTest;
- explicit ClipboardHostImpl(
- scoped_refptr<ChromeBlobStorageContext> blob_storage_context);
+ ClipboardHostImpl();
// content::mojom::ClipboardHost
void GetSequenceNumber(ui::ClipboardType clipboard_type,
@@ -82,15 +67,13 @@ class CONTENT_EXPORT ClipboardHostImpl : public blink::mojom::ClipboardHost {
const std::string& url,
const base::string16& title) override;
void WriteImage(ui::ClipboardType clipboard_type,
- const gfx::Size& size_in_pixels,
- mojo::ScopedSharedBufferHandle shared_buffer_handle) override;
+ const SkBitmap& bitmap) override;
void CommitWrite(ui::ClipboardType clipboard_type) override;
#if defined(OS_MACOSX)
void WriteStringToFindPboard(const base::string16& text) override;
#endif
ui::Clipboard* clipboard_; // Not owned
- scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
std::unique_ptr<ui::ScopedClipboardWriter> clipboard_writer_;
};
diff --git a/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc b/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc
index 704acc6673d..a3a0e92ec35 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc
@@ -6,41 +6,31 @@
#include <stddef.h>
#include <stdint.h>
-#include <string.h>
-#include "base/memory/ref_counted.h"
-#include "base/process/process_handle.h"
#include "base/run_loop.h"
-#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
-#include "mojo/public/cpp/system/platform_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/test/test_clipboard.h"
-#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/skia_util.h"
namespace content {
class ClipboardHostImplTest : public ::testing::Test {
protected:
ClipboardHostImplTest()
- : host_(new ClipboardHostImpl(nullptr)),
- clipboard_(ui::TestClipboard::CreateForCurrentThread()) {}
+ : clipboard_(ui::TestClipboard::CreateForCurrentThread()) {}
~ClipboardHostImplTest() override {
ui::Clipboard::DestroyClipboardForCurrentThread();
}
- void CallWriteImage(const gfx::Size& size,
- mojo::ScopedSharedBufferHandle shared_memory,
- size_t shared_memory_size) {
- host_->WriteImage(
- ui::CLIPBOARD_TYPE_COPY_PASTE, size,
- shared_memory->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY));
+ void CallWriteImage(const SkBitmap& bitmap) {
+ host_.WriteImage(ui::CLIPBOARD_TYPE_COPY_PASTE, bitmap);
}
void CallCommitWrite() {
- host_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ host_.CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
base::RunLoop().RunUntilIdle();
}
@@ -48,27 +38,16 @@ class ClipboardHostImplTest : public ::testing::Test {
private:
const TestBrowserThreadBundle thread_bundle_;
- const std::unique_ptr<ClipboardHostImpl> host_;
+ ClipboardHostImpl host_;
ui::Clipboard* const clipboard_;
};
// Test that it actually works.
TEST_F(ClipboardHostImplTest, SimpleImage) {
- static const uint32_t bitmap_data[] = {
- 0x33333333, 0xdddddddd, 0xeeeeeeee, 0x00000000, 0x88888888, 0x66666666,
- 0x55555555, 0xbbbbbbbb, 0x44444444, 0xaaaaaaaa, 0x99999999, 0x77777777,
- 0xffffffff, 0x11111111, 0x22222222, 0xcccccccc,
- };
-
- mojo::ScopedSharedBufferHandle shared_memory =
- mojo::SharedBufferHandle::Create(sizeof(bitmap_data));
- mojo::ScopedSharedBufferMapping mapping =
- shared_memory->Map(sizeof(bitmap_data));
-
- memcpy(mapping.get(), bitmap_data, sizeof(bitmap_data));
-
- CallWriteImage(gfx::Size(4, 4), std::move(shared_memory),
- sizeof(bitmap_data));
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(3, 2);
+ bitmap.eraseARGB(255, 0, 255, 0);
+ CallWriteImage(bitmap);
uint64_t sequence_number =
clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE);
CallCommitWrite();
@@ -81,26 +60,7 @@ TEST_F(ClipboardHostImplTest, SimpleImage) {
ui::Clipboard::GetBitmapFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
SkBitmap actual = clipboard()->ReadImage(ui::CLIPBOARD_TYPE_COPY_PASTE);
- EXPECT_EQ(sizeof(bitmap_data), actual.computeByteSize());
- EXPECT_EQ(0,
- memcmp(bitmap_data, actual.getAddr32(0, 0), sizeof(bitmap_data)));
-}
-
-// Test with a size that would overflow a naive 32-bit row bytes calculation.
-TEST_F(ClipboardHostImplTest, ImageSizeOverflows32BitRowBytes) {
- mojo::ScopedSharedBufferHandle shared_memory =
- mojo::SharedBufferHandle::Create(0x20000000);
-
- mojo::ScopedSharedBufferMapping mapping = shared_memory->Map(0x20000000);
-
- CallWriteImage(gfx::Size(0x20000000, 1), std::move(shared_memory),
- 0x20000000);
- uint64_t sequence_number =
- clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE);
- CallCommitWrite();
-
- EXPECT_EQ(sequence_number,
- clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_TRUE(gfx::BitmapsAreEqual(bitmap, actual));
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index 12b20bd638a..454ebcafa7a 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -34,11 +34,11 @@
#include "cc/base/switches.h"
#include "cc/input/input_handler.h"
#include "cc/layers/layer.h"
+#include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
#include "cc/raster/single_thread_task_graph_runner.h"
#include "cc/resources/ui_resource_manager.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_settings.h"
-#include "components/viz/client/client_layer_tree_frame_sink.h"
#include "components/viz/client/frame_eviction_manager.h"
#include "components/viz/client/hit_test_data_provider_draw_quad.h"
#include "components/viz/client/local_surface_id_provider.h"
@@ -48,6 +48,7 @@
#include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/surfaces/frame_sink_id_allocator.h"
+#include "components/viz/host/host_display_client.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/display/display.h"
#include "components/viz/service/display/display_scheduler.h"
@@ -59,15 +60,16 @@
#include "components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "content/browser/browser_main_loop.h"
-#include "content/browser/compositor/in_process_display_client.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/gpu/compositor_util.h"
+#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/gpu_stream_constants.h"
#include "content/public/browser/android/compositor.h"
#include "content/public/browser/android/compositor_client.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
@@ -76,6 +78,8 @@
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/gpu_surface_tracker.h"
#include "gpu/vulkan/buildflags.h"
+#include "gpu/vulkan/init/vulkan_factory.h"
+#include "gpu/vulkan/vulkan_implementation.h"
#include "gpu/vulkan/vulkan_surface.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
@@ -84,6 +88,7 @@
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkMallocPixelRef.h"
#include "ui/android/window_android.h"
+#include "ui/compositor/host/external_begin_frame_controller_client_impl.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/ca_layer_params.h"
@@ -112,6 +117,24 @@ class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner {
~SingleThreadTaskGraphRunner() override { Shutdown(); }
};
+// An implementation of HostDisplayClient which handles swap callbacks.
+class AndroidHostDisplayClient : public viz::HostDisplayClient {
+ public:
+ explicit AndroidHostDisplayClient(
+ base::RepeatingCallback<void(const gfx::Size&)> on_swap)
+ : HostDisplayClient(gfx::kNullAcceleratedWidget),
+ on_swap_(std::move(on_swap)) {}
+
+ // viz::mojom::DisplayClient implementation:
+ void DidCompleteSwapWithSize(const gfx::Size& pixel_size) override {
+ if (on_swap_)
+ on_swap_.Run(pixel_size);
+ }
+
+ private:
+ base::RepeatingCallback<void(const gfx::Size&)> on_swap_;
+};
+
class CompositorDependencies {
public:
static CompositorDependencies& Get() {
@@ -129,13 +152,13 @@ class CompositorDependencies {
mojo::MakeRequest(&frame_sink_manager_client);
// Setup HostFrameSinkManager with interface endpoints.
- GetHostFrameSinkManager()->BindAndSetManager(
+ host_frame_sink_manager.BindAndSetManager(
std::move(frame_sink_manager_client_request),
base::ThreadTaskRunnerHandle::Get(), std::move(frame_sink_manager));
// Set up a callback to automatically re-connect if we lose our
// connection.
- GetHostFrameSinkManager()->SetConnectionLostCallback(base::BindRepeating(
+ host_frame_sink_manager.SetConnectionLostCallback(base::BindRepeating(
[]() { CompositorDependencies::Get().CreateVizFrameSinkManager(); }));
BrowserMainLoop::GetInstance()
@@ -160,11 +183,8 @@ class CompositorDependencies {
// http://crbug.com/657959.
std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_impl;
- // Viz-only members:
- viz::mojom::DisplayPrivateAssociatedPtr display_private;
- std::unique_ptr<InProcessDisplayClient> display_client;
-
#if BUILDFLAG(ENABLE_VULKAN)
+ std::unique_ptr<gpu::VulkanImplementation> vulkan_implementation;
scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider;
#endif
private:
@@ -174,9 +194,14 @@ class CompositorDependencies {
bool enable_viz =
base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
if (!enable_viz) {
- frame_sink_manager_impl = std::make_unique<viz::FrameSinkManagerImpl>();
+ // The SharedBitmapManager can be null as software compositing is not
+ // supported or used on Android.
+ frame_sink_manager_impl = std::make_unique<viz::FrameSinkManagerImpl>(
+ /*shared_bitmap_manager=*/nullptr);
surface_utils::ConnectWithLocalFrameSinkManager(
&host_frame_sink_manager, frame_sink_manager_impl.get());
+ } else {
+ CreateVizFrameSinkManager();
}
}
@@ -219,15 +244,21 @@ const unsigned int kMaxDisplaySwapBuffers = 1U;
#if BUILDFLAG(ENABLE_VULKAN)
scoped_refptr<viz::VulkanContextProvider> GetSharedVulkanContextProvider() {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableVulkan)) {
- scoped_refptr<viz::VulkanContextProvider> context_provider =
- CompositorDependencies::Get().vulkan_context_provider;
- if (!*context_provider)
- *context_provider = viz::VulkanInProcessContextProvider::Create();
- return *context_provider;
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableVulkan))
+ return nullptr;
+
+ scoped_refptr<viz::VulkanContextProvider>& context_provider =
+ CompositorDependencies::Get().vulkan_context_provider;
+ if (!context_provider) {
+ std::unique_ptr<gpu::VulkanImplementation>& vulkan_implementation =
+ CompositorDependencies::Get().vulkan_implementation;
+ DCHECK(!vulkan_implementation);
+ vulkan_implementation = gpu::CreateVulkanImplementation();
+ context_provider = viz::VulkanInProcessContextProvider::Create(
+ vulkan_implementation.get());
}
- return nullptr;
+ return context_provider;
}
#endif
@@ -336,7 +367,7 @@ void CreateContextProviderAfterGpuChannelEstablished(
GURL(std::string("chrome://gpu/Compositor::CreateContextProvider")),
automatic_flushes, support_locking, support_grcontext,
shared_memory_limits, attributes,
- ui::command_buffer_metrics::CONTEXT_TYPE_UNKNOWN);
+ ui::command_buffer_metrics::ContextType::UNKNOWN);
callback.Run(std::move(context_provider));
}
@@ -344,7 +375,7 @@ class AndroidOutputSurface : public viz::OutputSurface {
public:
AndroidOutputSurface(
scoped_refptr<ui::ContextProviderCommandBuffer> context_provider,
- base::RepeatingCallback<void(gfx::Size)> swap_buffers_callback)
+ base::RepeatingCallback<void(const gfx::Size&)> swap_buffers_callback)
: viz::OutputSurface(std::move(context_provider)),
swap_buffers_callback_(std::move(swap_buffers_callback)),
overlay_candidate_validator_(
@@ -356,9 +387,6 @@ class AndroidOutputSurface : public viz::OutputSurface {
~AndroidOutputSurface() override = default;
void SwapBuffers(viz::OutputSurfaceFrame frame) override {
- if (LatencyInfoHasSnapshotRequest(frame.latency_info))
- GetCommandBufferProxy()->SetSnapshotRequested();
-
auto callback =
base::BindOnce(&AndroidOutputSurface::OnSwapBuffersCompleted,
weak_ptr_factory_.GetWeakPtr(),
@@ -381,6 +409,13 @@ class AndroidOutputSurface : public viz::OutputSurface {
}
}
+#if BUILDFLAG(ENABLE_VULKAN)
+ gpu::VulkanSurface* GetVulkanSurface() override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+#endif
+
void BindToClient(viz::OutputSurfaceClient* client) override {
DCHECK(client);
DCHECK(!client_);
@@ -446,7 +481,6 @@ class AndroidOutputSurface : public viz::OutputSurface {
client_->DidReceiveSwapBuffersAck();
swap_buffers_callback_.Run(swap_size);
UpdateLatencyInfoOnSwap(params.swap_response, &latency_info);
- RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info);
latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
}
@@ -456,7 +490,7 @@ class AndroidOutputSurface : public viz::OutputSurface {
private:
viz::OutputSurfaceClient* client_ = nullptr;
- base::RepeatingCallback<void(gfx::Size)> swap_buffers_callback_;
+ base::RepeatingCallback<void(const gfx::Size&)> swap_buffers_callback_;
std::unique_ptr<viz::OverlayCandidateValidator> overlay_candidate_validator_;
ui::LatencyTracker latency_tracker_;
@@ -478,7 +512,8 @@ class VulkanOutputSurface : public viz::OutputSurface {
bool Initialize(gfx::AcceleratedWidget widget) {
DCHECK(!surface_);
std::unique_ptr<gpu::VulkanSurface> surface(
- gpu::VulkanSurface::CreateViewSurface(widget));
+ vulkan_context_provider()->GetVulkanImplementation()->CreateViewSurface(
+ widget));
if (!surface->Initialize(vulkan_context_provider()->GetDeviceQueue(),
gpu::VulkanSurface::DEFAULT_SURFACE_FORMAT)) {
return false;
@@ -488,19 +523,73 @@ class VulkanOutputSurface : public viz::OutputSurface {
return true;
}
- bool BindToClient(viz::OutputSurfaceClient* client) override {
- if (!OutputSurface::BindToClient(client))
- return false;
- return true;
+ void BindToClient(viz::OutputSurfaceClient* client) override {
+ client_ = client;
}
- void SwapBuffers(viz::CompositorFrame frame) override {
+ void EnsureBackbuffer() override { NOTIMPLEMENTED(); }
+
+ void DiscardBackbuffer() override { NOTIMPLEMENTED(); }
+
+ void BindFramebuffer() override { NOTIMPLEMENTED(); }
+
+ void SetDrawRectangle(const gfx::Rect& rect) override { NOTIMPLEMENTED(); }
+
+ viz::OverlayCandidateValidator* GetOverlayCandidateValidator()
+ const override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+
+ bool IsDisplayedAsOverlayPlane() const override {
+ NOTIMPLEMENTED();
+ return false;
+ }
+
+ unsigned GetOverlayTextureId() const override {
+ NOTIMPLEMENTED();
+ return 0;
+ }
+
+ gfx::BufferFormat GetOverlayBufferFormat() const override {
+ NOTIMPLEMENTED();
+ return gfx::BufferFormat::BGRA_8888;
+ }
+
+ void Reshape(const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha,
+ bool use_stencil) override {
+ NOTIMPLEMENTED();
+ }
+
+ bool HasExternalStencilTest() const override {
+ NOTIMPLEMENTED();
+ return false;
+ }
+
+ void ApplyExternalStencil() override { NOTIMPLEMENTED(); }
+
+ uint32_t GetFramebufferCopyTextureFormat() override {
+ NOTIMPLEMENTED();
+ return 0;
+ }
+
+ void SwapBuffers(viz::OutputSurfaceFrame frame) override {
surface_->SwapBuffers();
task_runner_->PostTask(FROM_HERE,
base::Bind(&VulkanOutputSurface::SwapBuffersAck,
weak_ptr_factory_.GetWeakPtr()));
}
+ gpu::VulkanSurface* GetVulkanSurface() override { return surface_.get(); }
+
+ unsigned UpdateGpuFence() override {
+ NOTIMPLEMENTED();
+ return 0;
+ }
+
void Destroy() {
if (surface_) {
surface_->Destroy();
@@ -511,9 +600,8 @@ class VulkanOutputSurface : public viz::OutputSurface {
private:
void SwapBuffersAck() { client_->DidReceiveSwapBuffersAck(); }
-#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanSurface> surface_;
-#endif
+ viz::OutputSurfaceClient* client_ = nullptr;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::WeakPtrFactory<VulkanOutputSurface> weak_ptr_factory_;
@@ -521,6 +609,11 @@ class VulkanOutputSurface : public viz::OutputSurface {
};
#endif
+// TODO(khushalsagar): These are being sent based on the CompositorImpl
+// visiblity which bakes in the assumption that there is a single CompositorImpl
+// instance per application, while the embedder could potentially create
+// multiple compositor instances. We should use the ApplicationStateListener to
+// send these notifications to the GPU instead. See crbug.com/859723.
void SendOnBackgroundedToGpuService() {
content::GpuProcessHost::CallOnIO(
content::GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
@@ -610,12 +703,6 @@ CompositorImpl::CompositorImpl(CompositorClient* client,
enable_viz_(
base::FeatureList::IsEnabled(features::kVizDisplayCompositor)),
weak_factory_(this) {
- // In Viz mode, we create the frame sink manager here. For some reason we
- // can't do this in the CompositorDependencies constructor.
- // TODO(ericrk): Investigate this.
- if (enable_viz_)
- CompositorDependencies::Get().CreateVizFrameSinkManager();
-
GetHostFrameSinkManager()->RegisterFrameSinkId(frame_sink_id_, this);
GetHostFrameSinkManager()->SetFrameSinkDebugLabel(frame_sink_id_,
"CompositorImpl");
@@ -641,10 +728,6 @@ void CompositorImpl::DetachRootWindow() {
root_window_->SetLayer(nullptr);
}
-bool CompositorImpl::IsForSubframe() {
- return false;
-}
-
ui::UIResourceProvider& CompositorImpl::GetUIResourceProvider() {
return *this;
}
@@ -751,6 +834,8 @@ void CompositorImpl::CreateLayerTreeHost() {
command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking));
settings.initial_debug_state.show_fps_counter =
command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
+ if (command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders))
+ settings.initial_debug_state.show_debug_borders.set();
settings.single_thread_proxy_scheduler = true;
settings.use_painted_device_scale_factor = true;
@@ -791,6 +876,7 @@ void CompositorImpl::SetVisible(bool visible) {
root_window_->GetBeginFrameSource());
}
display_.reset();
+ GpuDataManagerImpl::GetInstance()->SetApplicationVisible(false);
SendOnBackgroundedToGpuService();
EnqueueLowEndBackgroundCleanup();
} else {
@@ -798,11 +884,12 @@ void CompositorImpl::SetVisible(bool visible) {
has_submitted_frame_since_became_visible_ = false;
if (layer_tree_frame_sink_request_pending_)
HandlePendingLayerTreeFrameSinkRequest();
+ GpuDataManagerImpl::GetInstance()->SetApplicationVisible(true);
SendOnForegroundedToGpuService();
low_end_background_cleanup_task_.Cancel();
}
- if (CompositorDependencies::Get().display_private)
- CompositorDependencies::Get().display_private->SetDisplayVisible(visible);
+ if (display_private_)
+ display_private_->SetDisplayVisible(visible);
}
void CompositorImpl::SetWindowBounds(const gfx::Size& size) {
@@ -817,6 +904,10 @@ void CompositorImpl::SetWindowBounds(const gfx::Size& size) {
}
if (display_)
display_->Resize(size);
+
+ if (display_private_)
+ display_private_->Resize(size);
+
root_window_->GetLayer()->SetBounds(size);
}
@@ -872,8 +963,7 @@ void CompositorImpl::HandlePendingLayerTreeFrameSinkRequest() {
return;
#if BUILDFLAG(ENABLE_VULKAN)
- CreateVulkanOutputSurface()
- if (display_)
+ if (CreateVulkanOutputSurface())
return;
#endif
@@ -886,23 +976,25 @@ void CompositorImpl::HandlePendingLayerTreeFrameSinkRequest() {
}
#if BUILDFLAG(ENABLE_VULKAN)
-void CompositorImpl::CreateVulkanOutputSurface() {
+bool CompositorImpl::CreateVulkanOutputSurface() {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableVulkan))
- return;
+ return false;
scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider =
GetSharedVulkanContextProvider();
if (!vulkan_context_provider)
- return;
+ return false;
// TODO(crbug.com/582558): Need to match GL and implement DidSwapBuffers.
auto vulkan_surface = std::make_unique<VulkanOutputSurface>(
vulkan_context_provider, base::ThreadTaskRunnerHandle::Get());
if (!vulkan_surface->Initialize(window_))
- return;
+ return false;
InitializeDisplay(std::move(vulkan_surface), nullptr);
+
+ return !!display_;
}
#endif
@@ -953,7 +1045,7 @@ void CompositorImpl::OnGpuChannelEstablished(
GetCompositorContextSharedMemoryLimits(root_window_),
GetCompositorContextAttributes(display_color_space_,
requires_alpha_channel_),
- ui::command_buffer_metrics::DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT);
+ ui::command_buffer_metrics::ContextType::BROWSER_COMPOSITOR);
auto result = context_provider->BindToCurrentThread();
LOG_IF(FATAL, result == gpu::ContextResult::kFatalFailure)
<< "Fatal error making Gpu context";
@@ -1006,9 +1098,8 @@ void CompositorImpl::InitializeDisplay(
const bool should_register_begin_frame_source = !display_;
display_ = std::make_unique<viz::Display>(
- viz::ServerSharedBitmapManager::current(), renderer_settings,
- frame_sink_id_, std::move(display_output_surface), std::move(scheduler),
- task_runner);
+ nullptr, renderer_settings, frame_sink_id_,
+ std::move(display_output_surface), std::move(scheduler), task_runner);
auto layer_tree_frame_sink = std::make_unique<viz::DirectLayerTreeFrameSink>(
frame_sink_id_, GetHostFrameSinkManager(), manager, display_.get(),
@@ -1026,8 +1117,11 @@ void CompositorImpl::InitializeDisplay(
host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink));
}
-void CompositorImpl::DidSwapBuffers(gfx::Size swap_size) {
+void CompositorImpl::DidSwapBuffers(const gfx::Size& swap_size) {
client_->DidSwapBuffers(swap_size);
+
+ if (swap_completed_with_size_for_testing_)
+ swap_completed_with_size_for_testing_.Run(swap_size);
}
cc::UIResourceId CompositorImpl::CreateUIResource(
@@ -1049,12 +1143,6 @@ void CompositorImpl::DidSubmitCompositorFrame() {
TRACE_EVENT0("compositor", "CompositorImpl::DidSubmitCompositorFrame");
pending_frames_++;
has_submitted_frame_since_became_visible_ = true;
-
- if (enable_viz_) {
- // TODO(ericrk): Viz should use the actual swap callback from the Viz
- // process. This is just a workaround until we wire that up.
- DidSwapBuffers(size_);
- }
}
void CompositorImpl::DidReceiveCompositorFrameAck() {
@@ -1116,19 +1204,6 @@ void CompositorImpl::RemoveChildFrameSink(
frame_sink_id);
}
-void CompositorImpl::OnFirstSurfaceActivation(
- const viz::SurfaceInfo& surface_info) {
- if (enable_viz_) {
- // Force a new surface to be generated.
- // TODO(ericrk): Remove this once we correctly set up fallback surfaces.
- host_->SetViewportSizeAndScale(size_, root_window_->GetDipScale(),
- GenerateLocalSurfaceId());
- }
-
- // TODO(fsamuel): Once surface synchronization is turned on, the fallback
- // surface should be set here.
-}
-
void CompositorImpl::OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) {
if (changed_metrics & display::DisplayObserver::DisplayMetric::
@@ -1197,7 +1272,6 @@ void CompositorImpl::InitializeVizLayerTreeFrameSink(
scoped_refptr<ui::ContextProviderCommandBuffer> context_provider) {
DCHECK(enable_viz_);
- auto& deps = CompositorDependencies::Get();
pending_frames_ = 0;
gpu_capabilities_ = context_provider->ContextCapabilities();
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
@@ -1205,15 +1279,20 @@ void CompositorImpl::InitializeVizLayerTreeFrameSink(
auto root_params = viz::mojom::RootCompositorFrameSinkParams::New();
+ // Android requires swap size notifications.
+ root_params->send_swap_size_notifications = true;
+
// Create interfaces for a root CompositorFrameSink.
viz::mojom::CompositorFrameSinkAssociatedPtrInfo sink_info;
root_params->compositor_frame_sink = mojo::MakeRequest(&sink_info);
viz::mojom::CompositorFrameSinkClientRequest client_request =
mojo::MakeRequest(&root_params->compositor_frame_sink_client);
- root_params->display_private = mojo::MakeRequest(&deps.display_private);
- deps.display_client = std::make_unique<InProcessDisplayClient>(window_);
+ root_params->display_private = mojo::MakeRequest(&display_private_);
+ display_client_ =
+ std::make_unique<AndroidHostDisplayClient>(base::BindRepeating(
+ &CompositorImpl::DidSwapBuffers, weak_factory_.GetWeakPtr()));
root_params->display_client =
- deps.display_client->GetBoundPtr(task_runner).PassInterface();
+ display_client_->GetBoundPtr(task_runner).PassInterface();
viz::RendererSettings renderer_settings;
renderer_settings.allow_antialiasing = false;
@@ -1227,7 +1306,7 @@ void CompositorImpl::InitializeVizLayerTreeFrameSink(
std::move(root_params));
// Create LayerTreeFrameSink with the browser end of CompositorFrameSink.
- viz::ClientLayerTreeFrameSink::InitParams params;
+ cc::mojo_embedder::AsyncLayerTreeFrameSink::InitParams params;
params.compositor_task_runner = task_runner;
params.gpu_memory_buffer_manager = BrowserMainLoop::GetInstance()
->gpu_channel_establish_factory()
@@ -1240,10 +1319,12 @@ void CompositorImpl::InitializeVizLayerTreeFrameSink(
params.hit_test_data_provider =
std::make_unique<viz::HitTestDataProviderDrawQuad>(
/*should_ask_for_child_region=*/false);
- auto layer_tree_frame_sink = std::make_unique<viz::ClientLayerTreeFrameSink>(
- std::move(context_provider), nullptr, &params);
+ auto layer_tree_frame_sink =
+ std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>(
+ std::move(context_provider), nullptr, &params);
host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink));
- CompositorDependencies::Get().display_private->SetDisplayVisible(true);
+ display_private_->SetDisplayVisible(true);
+ display_private_->Resize(size_);
}
viz::LocalSurfaceId CompositorImpl::GenerateLocalSurfaceId() const {
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index c55917e4a60..ad8f0ea0358 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -16,6 +16,7 @@
#include "base/observer_list.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_single_thread_client.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/host/host_frame_sink_client.h"
@@ -25,11 +26,13 @@
#include "gpu/ipc/common/surface_handle.h"
#include "gpu/vulkan/buildflags.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/android/resources/resource_manager_impl.h"
#include "ui/android/resources/ui_resource_provider.h"
#include "ui/android/window_android_compositor.h"
#include "ui/compositor/compositor_lock.h"
+#include "ui/compositor/external_begin_frame_client.h"
#include "ui/display/display_observer.h"
struct ANativeWindow;
@@ -40,10 +43,15 @@ class Layer;
class LayerTreeHost;
}
+namespace ui {
+class ExternalBeginFrameControllerClientImpl;
+}
+
namespace viz {
class Display;
class FrameSinkId;
class FrameSinkManagerImpl;
+class HostDisplayClient;
class HostFrameSinkManager;
class OutputSurface;
}
@@ -81,6 +89,10 @@ class CONTENT_EXPORT CompositorImpl
// Test functions:
bool IsLockedForTesting() const { return lock_manager_.IsLocked(); }
void SetVisibleForTesting(bool visible) { SetVisible(visible); }
+ void SetSwapCompletedWithSizeCallbackForTesting(
+ base::RepeatingCallback<void(const gfx::Size&)> cb) {
+ swap_completed_with_size_for_testing_ = std::move(cb);
+ }
private:
// Compositor implementation.
@@ -116,7 +128,9 @@ class CONTENT_EXPORT CompositorImpl
void DidCommitAndDrawFrame() override {}
void DidReceiveCompositorFrameAck() override;
void DidCompletePageScaleAnimation() override {}
- bool IsForSubframe() override;
+ void DidPresentCompositorFrame(
+ uint32_t frame_token,
+ const gfx::PresentationFeedback& feedback) override {}
// LayerTreeHostSingleThreadClient implementation.
void DidSubmitCompositorFrame() override;
@@ -136,7 +150,8 @@ class CONTENT_EXPORT CompositorImpl
bool IsDrawingFirstVisibleFrame() const override;
// viz::HostFrameSinkClient implementation.
- void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
+ void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override {
+ }
void OnFrameTokenChanged(uint32_t frame_token) override {}
// display::DisplayObserver implementation.
@@ -152,14 +167,14 @@ class CONTENT_EXPORT CompositorImpl
void HandlePendingLayerTreeFrameSinkRequest();
#if BUILDFLAG(ENABLE_VULKAN)
- void CreateVulkanOutputSurface();
+ bool CreateVulkanOutputSurface();
#endif
void OnGpuChannelEstablished(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host);
void InitializeDisplay(
std::unique_ptr<viz::OutputSurface> display_output_surface,
scoped_refptr<viz::ContextProvider> context_provider);
- void DidSwapBuffers(gfx::Size swap_size);
+ void DidSwapBuffers(const gfx::Size& swap_size);
bool HavePendingReadbacks();
@@ -235,6 +250,14 @@ class CONTENT_EXPORT CompositorImpl
// If true, we are using a Viz process.
const bool enable_viz_;
+ // Viz-specific members for communicating with the display.
+ viz::mojom::DisplayPrivateAssociatedPtr display_private_;
+ std::unique_ptr<viz::HostDisplayClient> display_client_;
+
+ // Test-only. Called when we are notified of a swap.
+ base::RepeatingCallback<void(const gfx::Size&)>
+ swap_completed_with_size_for_testing_;
+
base::WeakPtrFactory<CompositorImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CompositorImpl);
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc b/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc
index bfaadc54359..a2b349b0a46 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "base/base_switches.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/viz/common/features.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/renderer_host/compositor_impl_android.h"
@@ -26,13 +28,35 @@ namespace content {
namespace {
-class CompositorImplLowEndBrowserTest : public ContentBrowserTest {
+enum class CompositorImplMode {
+ kNormal,
+ kViz,
+ kVizSkDDL,
+};
+
+class CompositorImplBrowserTest
+ : public testing::WithParamInterface<CompositorImplMode>,
+ public ContentBrowserTest {
public:
- CompositorImplLowEndBrowserTest() {}
- void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitch(switches::kEnableLowEndDeviceMode);
- command_line->AppendSwitch(switches::kInProcessGPU);
- content::ContentBrowserTest::SetUpCommandLine(command_line);
+ CompositorImplBrowserTest() {}
+
+ void SetUp() override {
+ switch (GetParam()) {
+ case CompositorImplMode::kNormal:
+ break;
+ case CompositorImplMode::kViz:
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kVizDisplayCompositor);
+ break;
+ case CompositorImplMode::kVizSkDDL:
+ scoped_feature_list_.InitWithFeatures(
+ {features::kVizDisplayCompositor,
+ features::kUseSkiaDeferredDisplayList, features::kUseSkiaRenderer},
+ {});
+ break;
+ }
+
+ ContentBrowserTest::SetUp();
}
protected:
@@ -63,9 +87,33 @@ class CompositorImplLowEndBrowserTest : public ContentBrowserTest {
}
private:
- DISALLOW_COPY_AND_ASSIGN(CompositorImplLowEndBrowserTest);
+ base::test::ScopedFeatureList scoped_feature_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompositorImplBrowserTest);
+};
+
+INSTANTIATE_TEST_CASE_P(P,
+ CompositorImplBrowserTest,
+ ::testing::Values(CompositorImplMode::kNormal,
+ CompositorImplMode::kViz,
+ CompositorImplMode::kVizSkDDL));
+
+class CompositorImplLowEndBrowserTest : public CompositorImplBrowserTest {
+ public:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(switches::kEnableLowEndDeviceMode);
+ command_line->AppendSwitch(switches::kInProcessGPU);
+ content::ContentBrowserTest::SetUpCommandLine(command_line);
+ }
};
+// Viz on android is not yet compatible with in-process GPU. Only run in
+// kNormal mode.
+// TODO(ericrk): Make this work everywhere. https://crbug.com/851643
+INSTANTIATE_TEST_CASE_P(P,
+ CompositorImplLowEndBrowserTest,
+ ::testing::Values(CompositorImplMode::kNormal));
+
// RunLoop implementation that calls glFlush() every second until it observes
// OnContextLost().
class ContextLostRunLoop : public viz::ContextLostObserver {
@@ -130,8 +178,15 @@ class CompositorFrameRunLoop : public ui::WindowAndroidObserver {
DISALLOW_COPY_AND_ASSIGN(CompositorFrameRunLoop);
};
-IN_PROC_BROWSER_TEST_F(CompositorImplLowEndBrowserTest,
+IN_PROC_BROWSER_TEST_P(CompositorImplLowEndBrowserTest,
CompositorImplDropsResourcesOnBackground) {
+ // This test makes invalid assumptions when surface synchronization is
+ // enabled. The compositor lock is obsolete, and inspecting frames
+ // from the CompositorImpl does not guarantee renderer CompositorFrames
+ // are ready.
+ if (features::IsSurfaceSynchronizationEnabled())
+ return;
+
auto* rwhva = render_widget_host_view_android();
auto* compositor = compositor_impl();
auto context = GpuBrowsertestCreateContext(
@@ -166,5 +221,35 @@ IN_PROC_BROWSER_TEST_F(CompositorImplLowEndBrowserTest,
EXPECT_TRUE(rwhva->HasValidFrame());
}
+// RunLoop implementation that runs until it observes a swap with size.
+class CompositorSwapRunLoop {
+ public:
+ CompositorSwapRunLoop(CompositorImpl* compositor) : compositor_(compositor) {
+ compositor_->SetSwapCompletedWithSizeCallbackForTesting(base::BindRepeating(
+ &CompositorSwapRunLoop::DidSwap, base::Unretained(this)));
+ }
+ ~CompositorSwapRunLoop() {
+ compositor_->SetSwapCompletedWithSizeCallbackForTesting(base::DoNothing());
+ }
+
+ void RunUntilSwap() { run_loop_.Run(); }
+
+ private:
+ void DidSwap(const gfx::Size& pixel_size) {
+ EXPECT_FALSE(pixel_size.IsEmpty());
+ run_loop_.Quit();
+ }
+
+ CompositorImpl* compositor_;
+ base::RunLoop run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompositorSwapRunLoop);
+};
+
+IN_PROC_BROWSER_TEST_P(CompositorImplBrowserTest,
+ CompositorImplReceivesSwapCallbacks) {
+ CompositorSwapRunLoop(compositor_impl()).RunUntilSwap();
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.cc b/chromium/content/browser/renderer_host/delegated_frame_host.cc
index 47455e4a512..8b8bc279ccf 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.cc
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.cc
@@ -11,6 +11,8 @@
#include "base/callback_helpers.h"
#include "base/command_line.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
@@ -23,6 +25,7 @@
#include "components/viz/service/surfaces/surface_hittest.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/gpu/compositor_util.h"
+#include "content/common/tab_switching_time_callback.h"
#include "content/public/common/content_switches.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/dip_util.h"
@@ -68,17 +71,17 @@ DelegatedFrameHost::~DelegatedFrameHost() {
void DelegatedFrameHost::WasShown(
const viz::LocalSurfaceId& new_pending_local_surface_id,
const gfx::Size& new_pending_dip_size,
- const ui::LatencyInfo& latency_info) {
+ bool record_presentation_time) {
frame_evictor_->SetVisible(true);
-
- if (compositor_)
- compositor_->SetLatencyInfo(latency_info);
+ if (record_presentation_time && compositor_) {
+ compositor_->RequestPresentationTimeForNextFrame(
+ CreateTabSwitchingTimeRecorder(base::TimeTicks::Now()));
+ }
// Use the default deadline to synchronize web content with browser UI.
// TODO(fsamuel): Investigate if there is a better deadline to use here.
- SynchronizeVisualProperties(new_pending_local_surface_id,
- new_pending_dip_size,
- cc::DeadlinePolicy::UseDefaultDeadline());
+ EmbedSurface(new_pending_local_surface_id, new_pending_dip_size,
+ cc::DeadlinePolicy::UseDefaultDeadline());
}
bool DelegatedFrameHost::HasSavedFrame() const {
@@ -111,7 +114,8 @@ void DelegatedFrameHost::CopyFromCompositingSurface(
// If there is enough information to populate the copy output request fields,
// then process it now. Otherwise, wait until the information becomes
// available.
- if (CanCopyFromCompositingSurface())
+ if (CanCopyFromCompositingSurface() &&
+ active_local_surface_id_ == pending_local_surface_id_)
ProcessCopyOutputRequest(std::move(request));
else
pending_first_frame_requests_.push_back(std::move(request));
@@ -122,14 +126,18 @@ void DelegatedFrameHost::ProcessCopyOutputRequest(
if (!request->has_area())
request->set_area(gfx::Rect(pending_surface_dip_size_));
- // TODO(vmpstr): Should use pending device scale factor. We need to plumb
- // it here.
request->set_area(
gfx::ScaleToRoundedRect(request->area(), active_device_scale_factor_));
if (request->has_result_selection()) {
const gfx::Rect& area = request->area();
const gfx::Rect& result_selection = request->result_selection();
+ if (area.IsEmpty() || result_selection.IsEmpty()) {
+ // Viz would normally return an empty result for an empty selection.
+ // However, this guard here is still necessary to protect against setting
+ // an illegal scaling ratio.
+ return;
+ }
request->SetScaleRatio(
gfx::Vector2d(area.width(), area.height()),
gfx::Vector2d(result_selection.width(), result_selection.height()));
@@ -216,7 +224,7 @@ bool DelegatedFrameHost::HasFallbackSurface() const {
return fallback_surface_id && fallback_surface_id->is_valid();
}
-void DelegatedFrameHost::SynchronizeVisualProperties(
+void DelegatedFrameHost::EmbedSurface(
const viz::LocalSurfaceId& new_pending_local_surface_id,
const gfx::Size& new_pending_dip_size,
cc::DeadlinePolicy deadline_policy) {
@@ -238,8 +246,7 @@ void DelegatedFrameHost::SynchronizeVisualProperties(
}
// Don't update the SurfaceLayer when invisible to avoid blocking on
// renderers that do not submit CompositorFrames. Next time the renderer
- // is visible, SynchronizeVisualProperties will be called again. See
- // WasShown.
+ // is visible, EmbedSurface will be called again. See WasShown.
return;
}
@@ -278,10 +285,6 @@ SkColor DelegatedFrameHost::GetGutterColor() const {
return client_->DelegatedFrameHostGetGutterColor();
}
-gfx::Size DelegatedFrameHost::GetRequestedRendererSize() const {
- return pending_surface_dip_size_;
-}
-
void DelegatedFrameHost::DidCreateNewRendererCompositorFrameSink(
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
ResetCompositorFrameSinkSupport();
@@ -312,18 +315,11 @@ void DelegatedFrameHost::DidReceiveCompositorFrameAck(
renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
}
-void DelegatedFrameHost::DidPresentCompositorFrame(uint32_t presentation_token,
- base::TimeTicks time,
- base::TimeDelta refresh,
- uint32_t flags) {
- renderer_compositor_frame_sink_->DidPresentCompositorFrame(
- presentation_token, time, refresh, flags);
-}
-
-void DelegatedFrameHost::DidDiscardCompositorFrame(
- uint32_t presentation_token) {
- renderer_compositor_frame_sink_->DidDiscardCompositorFrame(
- presentation_token);
+void DelegatedFrameHost::DidPresentCompositorFrame(
+ uint32_t presentation_token,
+ const gfx::PresentationFeedback& feedback) {
+ renderer_compositor_frame_sink_->DidPresentCompositorFrame(presentation_token,
+ feedback);
}
void DelegatedFrameHost::ReclaimResources(
@@ -406,13 +402,8 @@ void DelegatedFrameHost::OnBeginFrame(const viz::BeginFrameArgs& args) {
}
void DelegatedFrameHost::EvictDelegatedFrame() {
- // It is possible that we are embedding the contents of previous
- // DelegatedFrameHost. In this case, HasSavedFrame() will return false but we
- // still need to clear the layer.
- if (HasFallbackSurface()) {
- client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
- viz::SurfaceId());
- }
+ // Replaces the SurfaceLayer with a SolidColorLayer.
+ client_->DelegatedFrameHostGetLayer()->SetShowSolidColorContent();
if (!HasSavedFrame())
return;
@@ -446,10 +437,21 @@ void DelegatedFrameHost::OnCompositingShuttingDown(ui::Compositor* compositor) {
}
////////////////////////////////////////////////////////////////////////////////
-// DelegatedFrameHost, ImageTransportFactoryObserver implementation:
+// DelegatedFrameHost, ContextFactoryObserver implementation:
-void DelegatedFrameHost::OnLostResources() {
- EvictDelegatedFrame();
+void DelegatedFrameHost::OnLostSharedContext() {}
+
+void DelegatedFrameHost::OnLostVizProcess() {
+ // With OOP-D renderer surface was destroyed if the GPU process crashed. Reset
+ // the fallback Surface but leave the primary so we embed the renderer surface
+ // again.
+ if (HasFallbackSurface()) {
+ client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
+ viz::SurfaceId());
+ }
+
+ if (HasSavedFrame())
+ frame_evictor_->DiscardedFrame();
}
////////////////////////////////////////////////////////////////////////////////
@@ -529,10 +531,9 @@ void DelegatedFrameHost::WindowTitleChanged(const std::string& title) {
}
void DelegatedFrameHost::TakeFallbackContentFrom(DelegatedFrameHost* other) {
- if (!other->HasFallbackSurface())
- return;
- if (HasFallbackSurface())
+ if (!other->HasFallbackSurface() || HasFallbackSurface())
return;
+
if (!HasPrimarySurface()) {
client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface(
*other->client_->DelegatedFrameHostGetLayer()->GetFallbackSurfaceId(),
@@ -541,6 +542,7 @@ void DelegatedFrameHost::TakeFallbackContentFrom(DelegatedFrameHost* other) {
cc::DeadlinePolicy::UseDefaultDeadline(),
false /* stretch_content_to_fill_bounds */);
}
+
client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
*other->client_->DelegatedFrameHostGetLayer()->GetFallbackSurfaceId());
}
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.h b/chromium/content/browser/renderer_host/delegated_frame_host.h
index 98f59da7af8..d8f5261cc35 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.h
@@ -87,7 +87,8 @@ class CONTENT_EXPORT DelegatedFrameHost
void OnCompositingShuttingDown(ui::Compositor* compositor) override;
// ui::ContextFactoryObserver implementation.
- void OnLostResources() override;
+ void OnLostSharedContext() override;
+ void OnLostVizProcess() override;
// FrameEvictorClient implementation.
void EvictDelegatedFrame() override;
@@ -95,11 +96,9 @@ class CONTENT_EXPORT DelegatedFrameHost
// viz::mojom::CompositorFrameSinkClient implementation.
void DidReceiveCompositorFrameAck(
const std::vector<viz::ReturnedResource>& resources) override;
- void DidPresentCompositorFrame(uint32_t presentation_token,
- base::TimeTicks time,
- base::TimeDelta refresh,
- uint32_t flags) override;
- void DidDiscardCompositorFrame(uint32_t presentation_token) override;
+ void DidPresentCompositorFrame(
+ uint32_t presentation_token,
+ const gfx::PresentationFeedback& feedback) override;
void OnBeginFrame(const viz::BeginFrameArgs& args) override;
void ReclaimResources(
const std::vector<viz::ReturnedResource>& resources) override;
@@ -122,12 +121,11 @@ class CONTENT_EXPORT DelegatedFrameHost
// TODO(ccameron): Include device scale factor here.
void WasShown(const viz::LocalSurfaceId& local_surface_id,
const gfx::Size& dip_size,
- const ui::LatencyInfo& latency_info);
- void SynchronizeVisualProperties(const viz::LocalSurfaceId& local_surface_id,
- const gfx::Size& dip_size,
- cc::DeadlinePolicy deadline_policy);
+ bool record_presentation_time);
+ void EmbedSurface(const viz::LocalSurfaceId& local_surface_id,
+ const gfx::Size& dip_size,
+ cc::DeadlinePolicy deadline_policy);
bool HasSavedFrame() const;
- gfx::Size GetRequestedRendererSize() const;
void SetCompositor(ui::Compositor* compositor);
void ResetCompositor();
// Note: |src_subrect| is specified in DIP dimensions while |output_size|
@@ -226,7 +224,7 @@ class CONTENT_EXPORT DelegatedFrameHost
float active_device_scale_factor_ = 0.f;
// The local surface id as of the most recent call to
- // SynchronizeVisualProperties or WasShown. This is the surface that we expect
+ // EmbedSurface or WasShown. This is the surface that we expect
// future frames to reference. This will eventually equal the active surface.
viz::LocalSurfaceId pending_local_surface_id_;
// The size of the above surface (updated at the same time).
@@ -234,7 +232,7 @@ class CONTENT_EXPORT DelegatedFrameHost
// In non-surface sync, this is the size of the most recently activated
// surface (which is suitable for calculating gutter size). In surface sync,
- // this is most recent size set in SynchronizeVisualProperties.
+ // this is most recent size set in EmbedSurface.
// TODO(ccameron): The meaning of "current" should be made more clear here.
gfx::Size current_frame_size_in_dip_;
@@ -256,6 +254,8 @@ class CONTENT_EXPORT DelegatedFrameHost
std::vector<std::unique_ptr<viz::CopyOutputRequest>>
pending_first_frame_requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(DelegatedFrameHost);
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/display_util.cc b/chromium/content/browser/renderer_host/display_util.cc
index 204211f7404..7d0d3d89f5d 100644
--- a/chromium/content/browser/renderer_host/display_util.cc
+++ b/chromium/content/browser/renderer_host/display_util.cc
@@ -21,10 +21,6 @@ void DisplayUtil::DisplayToScreenInfo(ScreenInfo* screen_info,
screen_info->available_rect = display.work_area();
screen_info->device_scale_factor = display.device_scale_factor();
screen_info->color_space = display.color_space();
-#if defined(OS_MACOSX)
- screen_info->icc_profile =
- gfx::ICCProfile::FromCacheMac(display.color_space());
-#endif
screen_info->depth = display.color_depth();
screen_info->depth_per_component = display.depth_per_component();
screen_info->is_monochrome = display.is_monochrome();
diff --git a/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc b/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc
index 02999045b0b..71073a5ff02 100644
--- a/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc
@@ -13,6 +13,7 @@
#include "build/build_config.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/host/host_frame_sink_manager.h"
+#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/test/compositor_frame_helpers.h"
#include "components/viz/test/fake_host_frame_sink_client.h"
@@ -119,7 +120,8 @@ class EmbeddedFrameSinkProviderImplTest : public testing::Test {
host_frame_sink_manager_ = std::make_unique<viz::HostFrameSinkManager>();
// The FrameSinkManagerImpl implementation is in-process here for tests.
- frame_sink_manager_ = std::make_unique<viz::FrameSinkManagerImpl>();
+ frame_sink_manager_ =
+ std::make_unique<viz::FrameSinkManagerImpl>(&shared_bitmap_manager_);
surface_utils::ConnectWithLocalFrameSinkManager(
host_frame_sink_manager_.get(), frame_sink_manager_.get());
@@ -140,6 +142,7 @@ class EmbeddedFrameSinkProviderImplTest : public testing::Test {
// A MessageLoop is required for mojo bindings which are used to
// connect to graphics services.
base::MessageLoop message_loop_;
+ viz::ServerSharedBitmapManager shared_bitmap_manager_;
viz::FakeHostFrameSinkClient host_frame_sink_client_;
std::unique_ptr<viz::HostFrameSinkManager> host_frame_sink_manager_;
std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_;
diff --git a/chromium/content/browser/renderer_host/font_utils_linux.cc b/chromium/content/browser/renderer_host/font_utils_linux.cc
deleted file mode 100644
index e5fd81a17d8..00000000000
--- a/chromium/content/browser/renderer_host/font_utils_linux.cc
+++ /dev/null
@@ -1,265 +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 <fcntl.h>
-#include <fontconfig/fontconfig.h>
-#include <stddef.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <string>
-
-#include "base/posix/eintr_wrapper.h"
-
-// TODO(crbug/685022): Guard the inclusion of ppapi headers with
-// BUILDFLAG(ENABLE_PLUGINS).
-#include "ppapi/c/private/pp_private_font_charset.h" // nogncheck
-#include "ppapi/c/trusted/ppb_browser_font_trusted.h" // nogncheck
-
-namespace {
-
-// MSCharSetToFontconfig translates a Microsoft charset identifier to a
-// fontconfig language set by appending to |langset|.
-// Returns true if |langset| is Latin/Greek/Cyrillic.
-bool MSCharSetToFontconfig(FcLangSet* langset, unsigned fdwCharSet) {
- // We have need to translate raw fdwCharSet values into terms that
- // fontconfig can understand. (See the description of fdwCharSet in the MSDN
- // documentation for CreateFont:
- // http://msdn.microsoft.com/en-us/library/dd183499(VS.85).aspx )
- //
- // Although the argument is /called/ 'charset', the actual values conflate
- // character sets (which are sets of Unicode code points) and character
- // encodings (which are algorithms for turning a series of bits into a
- // series of code points.) Sometimes the values will name a language,
- // sometimes they'll name an encoding. In the latter case I'm assuming that
- // they mean the set of code points in the domain of that encoding.
- //
- // fontconfig deals with ISO 639-1 language codes:
- // http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
- //
- // So, for each of the documented fdwCharSet values I've had to take a
- // guess at the set of ISO 639-1 languages intended.
-
- bool is_lgc = false;
- switch (fdwCharSet) {
- 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 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 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 PP_PRIVATEFONTCHARSET_CHINESEBIG5:
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-tw"));
- break;
- case PP_PRIVATEFONTCHARSET_GB2312:
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-cn"));
- break;
- case PP_PRIVATEFONTCHARSET_EASTEUROPE:
- // A scattering of eastern European languages.
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("pl"));
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("cs"));
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("sk"));
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hu"));
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hr"));
- break;
- case PP_PRIVATEFONTCHARSET_GREEK:
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("el"));
- break;
- case PP_PRIVATEFONTCHARSET_HANGUL:
- case PP_PRIVATEFONTCHARSET_JOHAB:
- // Korean
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ko"));
- break;
- case PP_PRIVATEFONTCHARSET_RUSSIAN:
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ru"));
- break;
- case PP_PRIVATEFONTCHARSET_SHIFTJIS:
- // Japanese
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ja"));
- break;
- case PP_PRIVATEFONTCHARSET_TURKISH:
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("tr"));
- break;
- case PP_PRIVATEFONTCHARSET_VIETNAMESE:
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("vi"));
- break;
- case PP_PRIVATEFONTCHARSET_ARABIC:
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ar"));
- break;
- case PP_PRIVATEFONTCHARSET_HEBREW:
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("he"));
- break;
- case PP_PRIVATEFONTCHARSET_THAI:
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("th"));
- break;
- // default:
- // Don't add any languages in that case that we don't recognise the
- // constant.
- }
- return is_lgc;
-}
-
-} // namespace
-
-namespace content {
-
-int MatchFontFaceWithFallback(const std::string& face,
- bool is_bold,
- bool is_italic,
- uint32_t charset,
- uint32_t fallback_family) {
- FcLangSet* langset = FcLangSetCreate();
- bool is_lgc = MSCharSetToFontconfig(langset, charset);
- FcPattern* pattern = FcPatternCreate();
- FcPatternAddString(
- pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(face.c_str()));
-
- // TODO(thestig) Check if we can access Chrome's per-script font preference
- // here and select better default fonts for non-LGC case.
- std::string generic_font_name;
- if (is_lgc) {
- switch (fallback_family) {
- case PP_BROWSERFONT_TRUSTED_FAMILY_SERIF:
- generic_font_name = "Times New Roman";
- break;
- case PP_BROWSERFONT_TRUSTED_FAMILY_SANSSERIF:
- generic_font_name = "Arial";
- break;
- case PP_BROWSERFONT_TRUSTED_FAMILY_MONOSPACE:
- generic_font_name = "Courier New";
- break;
- }
- }
- if (!generic_font_name.empty()) {
- const FcChar8* fc_generic_font_name =
- reinterpret_cast<const FcChar8*>(generic_font_name.c_str());
- FcPatternAddString(pattern, FC_FAMILY, fc_generic_font_name);
- }
-
- if (is_bold)
- FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
- if (is_italic)
- FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
- FcPatternAddLangSet(pattern, FC_LANG, langset);
- FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
- FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
- FcDefaultSubstitute(pattern);
-
- FcResult result;
- FcFontSet* font_set = FcFontSort(nullptr, pattern, 0, nullptr, &result);
- int font_fd = -1;
- int good_enough_index = -1;
- bool good_enough_index_set = false;
-
- if (font_set) {
- for (int i = 0; i < font_set->nfont; ++i) {
- FcPattern* current = font_set->fonts[i];
-
- // Older versions of fontconfig have a bug where they cannot select
- // only scalable fonts so we have to manually filter the results.
- FcBool is_scalable;
- if (FcPatternGetBool(current, FC_SCALABLE, 0, &is_scalable) !=
- FcResultMatch ||
- !is_scalable) {
- continue;
- }
-
- FcChar8* c_filename;
- if (FcPatternGetString(current, FC_FILE, 0, &c_filename) !=
- FcResultMatch) {
- continue;
- }
-
- // We only want to return sfnt (TrueType) based fonts. We don't have a
- // very good way of detecting this so we'll filter based on the
- // filename.
- bool is_sfnt = false;
- static const char kSFNTExtensions[][5] = {".ttf", ".otc", ".TTF", ".ttc",
- ""};
- const size_t filename_len = strlen(reinterpret_cast<char*>(c_filename));
- for (unsigned j = 0;; j++) {
- if (kSFNTExtensions[j][0] == 0) {
- // None of the extensions matched.
- break;
- }
- const size_t ext_len = strlen(kSFNTExtensions[j]);
- if (filename_len > ext_len &&
- memcmp(c_filename + filename_len - ext_len,
- kSFNTExtensions[j],
- ext_len) == 0) {
- is_sfnt = true;
- break;
- }
- }
-
- if (!is_sfnt)
- continue;
-
- // This font is good enough to pass muster, but we might be able to do
- // better with subsequent ones.
- if (!good_enough_index_set) {
- good_enough_index = i;
- good_enough_index_set = true;
- }
-
- FcValue matrix;
- bool have_matrix = FcPatternGet(current, FC_MATRIX, 0, &matrix) == 0;
-
- if (is_italic && have_matrix) {
- // we asked for an italic font, but fontconfig is giving us a
- // non-italic font with a transformation matrix.
- continue;
- }
-
- FcValue embolden;
- const bool have_embolden =
- FcPatternGet(current, FC_EMBOLDEN, 0, &embolden) == 0;
-
- if (is_bold && have_embolden) {
- // we asked for a bold font, but fontconfig gave us a non-bold font
- // and asked us to apply fake bolding.
- continue;
- }
-
- font_fd =
- HANDLE_EINTR(open(reinterpret_cast<char*>(c_filename), O_RDONLY));
- if (font_fd >= 0)
- break;
- }
- }
-
- if (font_fd == -1 && good_enough_index_set) {
- // We didn't find a font that we liked, so we fallback to something
- // acceptable.
- FcPattern* current = font_set->fonts[good_enough_index];
- FcChar8* c_filename;
- FcPatternGetString(current, FC_FILE, 0, &c_filename);
- font_fd = HANDLE_EINTR(open(reinterpret_cast<char*>(c_filename), O_RDONLY));
- }
-
- if (font_set)
- FcFontSetDestroy(font_set);
- FcPatternDestroy(pattern);
-
- return font_fd;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/font_utils_linux.h b/chromium/content/browser/renderer_host/font_utils_linux.h
deleted file mode 100644
index 33b31af68d7..00000000000
--- a/chromium/content/browser/renderer_host/font_utils_linux.h
+++ /dev/null
@@ -1,22 +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_RENDERER_HOST_FONT_UTILS_LINUX_H_
-#define CONTENT_BROWSER_RENDERER_HOST_FONT_UTILS_LINUX_H_
-
-#include <stdint.h>
-
-#include <string>
-
-namespace content {
-
-int MatchFontFaceWithFallback(const std::string& face,
- bool is_bold,
- bool is_italic,
- uint32_t charset,
- uint32_t fallback_family);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_FONT_UTILS_LINUX_H_
diff --git a/chromium/content/browser/renderer_host/frame_connector_delegate.h b/chromium/content/browser/renderer_host/frame_connector_delegate.h
index a1239217056..00a5e62ade0 100644
--- a/chromium/content/browser/renderer_host/frame_connector_delegate.h
+++ b/chromium/content/browser/renderer_host/frame_connector_delegate.h
@@ -71,7 +71,7 @@ class CONTENT_EXPORT FrameConnectorDelegate {
// Provide the SurfaceInfo to the embedder, which becomes a reference to the
// current view's Surface that is included in higher-level compositor
// frames.
- virtual void SetChildFrameSurface(const viz::SurfaceInfo& surface_info) {}
+ virtual void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info) {}
// Sends the given intrinsic sizing information from a sub-frame to
// its corresponding remote frame in the parent frame's renderer.
@@ -149,6 +149,11 @@ class CONTENT_EXPORT FrameConnectorDelegate {
const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) {}
+ // Pass acked touchpad pinch gesture events to the root view for processing.
+ virtual void ForwardAckedTouchpadPinchGestureEvent(
+ const blink::WebGestureEvent& event,
+ InputEventAckState ack_result) {}
+
// Gesture events with unused scroll deltas must be bubbled to ancestors
// who may consume the delta.
virtual void BubbleScrollEvent(const blink::WebGestureEvent& event) {}
diff --git a/chromium/content/browser/renderer_host/frame_metadata_util.cc b/chromium/content/browser/renderer_host/frame_metadata_util.cc
index de9edebd775..e5717aaaf67 100644
--- a/chromium/content/browser/renderer_host/frame_metadata_util.cc
+++ b/chromium/content/browser/renderer_host/frame_metadata_util.cc
@@ -13,16 +13,16 @@ namespace {
// V1 saw errors of ~0.065 between computed window and content widths.
const float kMobileViewportWidthEpsilon = 0.15f;
-bool HasFixedPageScale(const viz::CompositorFrameMetadata& frame_metadata) {
- return frame_metadata.min_page_scale_factor ==
- frame_metadata.max_page_scale_factor;
+bool HasFixedPageScale(float min_page_scale_factor,
+ float max_page_scale_factor) {
+ return min_page_scale_factor == max_page_scale_factor;
}
-bool HasMobileViewport(const viz::CompositorFrameMetadata& frame_metadata) {
- float window_width_dip =
- frame_metadata.page_scale_factor *
- frame_metadata.scrollable_viewport_size.width();
- float content_width_css = frame_metadata.root_layer_size.width();
+bool HasMobileViewport(float page_scale_factor,
+ const gfx::SizeF& scrollable_viewport_size,
+ const gfx::SizeF& root_layer_size) {
+ float window_width_dip = page_scale_factor * scrollable_viewport_size.width();
+ float content_width_css = root_layer_size.width();
return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
}
@@ -30,10 +30,15 @@ bool HasMobileViewport(const viz::CompositorFrameMetadata& frame_metadata) {
namespace content {
-bool IsMobileOptimizedFrame(
- const viz::CompositorFrameMetadata& frame_metadata) {
- bool has_mobile_viewport = HasMobileViewport(frame_metadata);
- bool has_fixed_page_scale = HasFixedPageScale(frame_metadata);
+bool IsMobileOptimizedFrame(float page_scale_factor,
+ float min_page_scale_factor,
+ float max_page_scale_factor,
+ const gfx::SizeF& scrollable_viewport_size,
+ const gfx::SizeF& root_layer_size) {
+ bool has_mobile_viewport = HasMobileViewport(
+ page_scale_factor, scrollable_viewport_size, root_layer_size);
+ bool has_fixed_page_scale =
+ HasFixedPageScale(min_page_scale_factor, max_page_scale_factor);
return has_fixed_page_scale || has_mobile_viewport;
}
diff --git a/chromium/content/browser/renderer_host/frame_metadata_util.h b/chromium/content/browser/renderer_host/frame_metadata_util.h
index 50de6fba264..dfa4585f5c6 100644
--- a/chromium/content/browser/renderer_host/frame_metadata_util.h
+++ b/chromium/content/browser/renderer_host/frame_metadata_util.h
@@ -7,8 +7,8 @@
#include "content/common/content_export.h"
-namespace viz {
-class CompositorFrameMetadata;
+namespace gfx {
+class SizeF;
}
namespace content {
@@ -19,7 +19,11 @@ namespace content {
// (indicating that this is a mobile-optimized or responsive web design);
// - page that prevents zooming in or out.
CONTENT_EXPORT bool IsMobileOptimizedFrame(
- const viz::CompositorFrameMetadata& frame_metadata);
+ float page_scale_factor,
+ float min_page_scale_factor,
+ float max_page_scale_factor,
+ const gfx::SizeF& scrollable_viewport_size,
+ const gfx::SizeF& root_layer_size);
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/README.md b/chromium/content/browser/renderer_host/input/README.md
new file mode 100644
index 00000000000..6348b985031
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/README.md
@@ -0,0 +1,23 @@
+# Renderer Host Input
+
+This directory contains browser side input event handling code.
+
+## TouchpadPinchEventQueue
+
+In order for pages to override the behaviour of touchpad pinch zooming, we offer
+synthetic wheel events that may be canceled. The `TouchpadPinchEventQueue`
+accepts the gesture pinch events created from native events and sends the
+appropriate wheel events to the renderer. Once the renderer has acknowledged a
+wheel event, we offer the corresponding gesture pinch event back to the client
+of the `TouchpadPinchEventQueue`. If the pinch has not been consumed by the page,
+the client may go on to send the actual gesture pinch event to the renderer which
+will perform the pinch zoom.
+
+Note that for touchscreen gesture pinch events, there is no need for a similar
+queue as touch events would have already been offered to the renderer before
+being recognized as a pinch gesture.
+
+See [issue 289887](https://crbug.com/289887) for the discussion on offering
+wheel events for touchpad pinch.
+
+Touchpad pinch zoom [design doc](https://docs.google.com/document/d/1cYdt9r9stHLA2lbJ2I-Ucl_djhdSyngYFbmufZaLRHE/edit?usp=sharing).
diff --git a/chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc b/chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc
index b20cceec519..835b21e194f 100644
--- a/chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc
@@ -245,6 +245,14 @@ IN_PROC_BROWSER_TEST_F(CompositorEventAckBrowserTest,
MAYBE_TouchStartDuringFling) {
LoadURL(kBlockingTouchStartDataURL);
+ // Send a TouchStart so that we can set allowed touch action to Auto.
+ SyntheticWebTouchEvent touch_event;
+ touch_event.PressPoint(50, 50);
+ touch_event.SetTimeStamp(ui::EventTimeForNow());
+ GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch_event,
+ ui::LatencyInfo());
+ GetWidgetHost()->input_router()->OnSetTouchAction(cc::kTouchActionAuto);
+
// Send GSB to start scrolling sequence.
blink::WebGestureEvent gesture_scroll_begin(
blink::WebGestureEvent::kGestureScrollBegin,
@@ -273,13 +281,17 @@ IN_PROC_BROWSER_TEST_F(CompositorEventAckBrowserTest,
.y() <= 0)
observer.WaitForMetadataChange();
+ touch_event.ReleasePoint(0);
+ GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch_event,
+ ui::LatencyInfo());
+ touch_event.ResetPoints();
+
// Send a touch start event and wait for its ack. The touch start must be
// uncancelable since there is an on-going fling with touchscreen source. The
// test will timeout if the touch start event is cancelable since there is a
// busy loop in the blocking touch start event listener.
InputEventAckWaiter touch_start_ack_observer(GetWidgetHost(),
WebInputEvent::kTouchStart);
- SyntheticWebTouchEvent touch_event;
touch_event.PressPoint(50, 50);
touch_event.SetTimeStamp(ui::EventTimeForNow());
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch_event,
diff --git a/chromium/content/browser/renderer_host/input/fling_browsertest.cc b/chromium/content/browser/renderer_host/input/fling_browsertest.cc
index 401de60bf93..b8371dc58c6 100644
--- a/chromium/content/browser/renderer_host/input/fling_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/fling_browsertest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "build/build_config.h"
+#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -28,6 +29,19 @@ const std::string kBrowserFlingDataURL = R"HTML(
<script>
document.title='ready';
</script>)HTML";
+
+const std::string kTouchActionFilterDataURL = R"HTML(
+ <!DOCTYPE html>
+ <meta name='viewport' content='width=device-width'/>
+ <style>
+ body {
+ height: 10000px;
+ touch-action: pan-y;
+ }
+ </style>
+ <script>
+ document.title='ready';
+ </script>)HTML";
} // namespace
namespace content {
@@ -42,6 +56,11 @@ class BrowserSideFlingBrowserTest : public ContentBrowserTest {
"MiddleClickAutoscroll");
}
+ void OnSyntheticGestureCompleted(SyntheticGesture::Result result) {
+ EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
+ run_loop_->Quit();
+ }
+
protected:
RenderWidgetHostImpl* GetWidgetHost() {
return RenderWidgetHostImpl::From(
@@ -81,6 +100,8 @@ class BrowserSideFlingBrowserTest : public ContentBrowserTest {
GetWidgetHost()->ForwardMouseEvent(up_event);
}
+ std::unique_ptr<base::RunLoop> run_loop_;
+
private:
DISALLOW_COPY_AND_ASSIGN(BrowserSideFlingBrowserTest);
};
@@ -149,13 +170,8 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchpadFling) {
}
}
-// TODO(sahel): This test is flaking on OS_CHROMEOS https://crbug.com/838769
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
-#define MAYBE_AutoscrollFling DISABLED_AutoscrollFling
-#else
-#define MAYBE_AutoscrollFling AutoscrollFling
-#endif
-IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, MAYBE_AutoscrollFling) {
+// TODO(sahel): This test is flaky https://crbug.com/838769
+IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, DISABLED_AutoscrollFling) {
LoadURL(kBrowserFlingDataURL);
// Start autoscroll with middle click.
@@ -220,4 +236,64 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest,
}
}
+// Disabled on MacOS because it doesn't support touchscreen scroll.
+#if defined(OS_MACOSX)
+#define MAYBE_ScrollEndGeneratedForFilteredFling \
+ DISABLED_ScrollEndGeneratedForFilteredFling
+#else
+// Flaky, see https://crbug.com/850455
+#define MAYBE_ScrollEndGeneratedForFilteredFling \
+ DISABLED_ScrollEndGeneratedForFilteredFling
+#endif
+IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest,
+ MAYBE_ScrollEndGeneratedForFilteredFling) {
+ LoadURL(kTouchActionFilterDataURL);
+
+ // Necessary for checking the ACK source of the sent events. The events are
+ // filtered when the Browser is the source.
+ auto scroll_begin_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kGestureScrollBegin);
+ auto fling_start_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kGestureFlingStart);
+ auto scroll_end_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kGestureScrollEnd);
+
+ // Do a horizontal touchscreen scroll followed by a fling. The GFS must get
+ // filtered since the GSB is filtered.
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.anchor = gfx::PointF(10, 10);
+ params.distances.push_back(gfx::Vector2d(-60, 0));
+ params.prevent_fling = false;
+
+ run_loop_ = std::make_unique<base::RunLoop>();
+
+ std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ GetWidgetHost()->QueueSyntheticGesture(
+ std::move(gesture),
+ base::BindOnce(&BrowserSideFlingBrowserTest::OnSyntheticGestureCompleted,
+ base::Unretained(this)));
+
+ // Runs until we get the OnSyntheticGestureCompleted callback.
+ run_loop_->Run();
+
+ scroll_begin_watcher->GetAckStateWaitIfNecessary();
+ EXPECT_EQ(InputEventAckSource::BROWSER,
+ scroll_begin_watcher->last_event_ack_source());
+
+ fling_start_watcher->GetAckStateWaitIfNecessary();
+ EXPECT_EQ(InputEventAckSource::BROWSER,
+ fling_start_watcher->last_event_ack_source());
+
+ // Since the GFS is filtered. the input_router_impl will generate and forward
+ // a GSE to make sure that the scrolling sequence and the touch action filter
+ // state get reset properly. The generated GSE will also get filtered since
+ // its equivalent GSB is filtered. The test will timeout if the GSE is not
+ // generated.
+ scroll_end_watcher->GetAckStateWaitIfNecessary();
+ EXPECT_EQ(InputEventAckSource::BROWSER,
+ scroll_end_watcher->last_event_ack_source());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/fling_controller.cc b/chromium/content/browser/renderer_host/input/fling_controller.cc
index ce13d23f10a..ef40b4f664a 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller.cc
+++ b/chromium/content/browser/renderer_host/input/fling_controller.cc
@@ -6,7 +6,8 @@
#include "base/trace_event/trace_event.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
-#include "content/public/common/content_features.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/fling_booster.h"
#include "ui/events/gestures/blink/web_gesture_curve_impl.h"
@@ -42,10 +43,6 @@ FlingController::FlingController(
touchscreen_tap_suppression_controller_(
config.touchscreen_tap_suppression_config),
fling_in_progress_(false),
- send_wheel_events_nonblocking_(
- base::FeatureList::IsEnabled(
- features::kTouchpadAndWheelScrollLatching) &&
- base::FeatureList::IsEnabled(features::kAsyncWheelEvents)),
weak_ptr_factory_(this) {
DCHECK(gesture_event_queue);
DCHECK(event_sender_client);
@@ -103,13 +100,6 @@ bool FlingController::FilterGestureEventForFlingBoosting(
if (!fling_booster_)
return false;
- // TODO(sahel): Don't boost touchpad fling for now. Once browserside
- // touchscreen fling is implemented, move the fling_controller_ from
- // GestureEventQueue to RednerWidgetHostImpl. This will gaurantee proper
- // gesture scroll event order in RednerWidgetHostImpl while boosting.
- if (gesture_event.event.SourceDevice() == blink::kWebGestureDeviceTouchpad)
- return false;
-
bool cancel_current_fling;
bool should_filter_event = fling_booster_->FilterGestureEventForFlingBoosting(
gesture_event.event, &cancel_current_fling);
@@ -270,15 +260,8 @@ void FlingController::GenerateAndSendWheelEvents(
synthetic_wheel.event.SetPositionInWidget(current_fling_parameters_.point);
synthetic_wheel.event.SetPositionInScreen(
current_fling_parameters_.global_point);
- // Send wheel end events nonblocking since they have zero delta and are not
- // sent to JS.
- if (phase == blink::WebMouseWheelEvent::kPhaseEnded) {
- synthetic_wheel.event.dispatch_type = WebInputEvent::kEventNonBlocking;
- } else {
- synthetic_wheel.event.dispatch_type = send_wheel_events_nonblocking_
- ? WebInputEvent::kEventNonBlocking
- : WebInputEvent::kBlocking;
- }
+ // Send wheel events nonblocking.
+ synthetic_wheel.event.dispatch_type = WebInputEvent::kEventNonBlocking;
event_sender_client_->SendGeneratedWheelEvent(synthetic_wheel);
}
@@ -370,8 +353,13 @@ void FlingController::CancelCurrentFling() {
// Synthesize a GestureScrollBegin, as the original event was suppressed. It
// is important to send the GSB after resetting the fling_booster_ otherwise
- // it will get filtered by the booster again.
+ // it will get filtered by the booster again. This is necessary for
+ // touchscreen fling cancelation only, since autoscroll fling cancelation
+ // doesn't get deferred and when the touchpad fling cancelation gets deferred,
+ // the first wheel event after the cancelation will cause a GSB generation.
if (fling_cancellation_is_deferred &&
+ last_fling_boost_event.SourceDevice() ==
+ blink::kWebGestureDeviceTouchscreen &&
(last_fling_boost_event.GetType() == WebInputEvent::kGestureScrollBegin ||
last_fling_boost_event.GetType() ==
WebInputEvent::kGestureScrollUpdate)) {
@@ -387,19 +375,11 @@ void FlingController::CancelCurrentFling() {
: last_fling_boost_event.data.scroll_begin.delta_y_hint;
scroll_begin_event.data.scroll_begin.delta_x_hint = delta_x_hint;
scroll_begin_event.data.scroll_begin.delta_y_hint = delta_y_hint;
- ui::SourceEventType latency_source_event_type =
- ui::SourceEventType::UNKNOWN;
- if (scroll_begin_event.SourceDevice() ==
- blink::kWebGestureDeviceTouchscreen) {
- latency_source_event_type = ui::SourceEventType::INERTIAL;
- } else if (scroll_begin_event.SourceDevice() ==
- blink::kWebGestureDeviceTouchpad) {
- latency_source_event_type = ui::SourceEventType::WHEEL;
- }
event_sender_client_->SendGeneratedGestureScrollEvents(
GestureEventWithLatencyInfo(
- scroll_begin_event, ui::LatencyInfo(latency_source_event_type)));
+ scroll_begin_event,
+ ui::LatencyInfo(ui::SourceEventType::INERTIAL)));
}
if (had_active_fling) {
@@ -430,7 +410,8 @@ bool FlingController::UpdateCurrentFlingState(
ui::WebGestureCurveImpl::CreateFromDefaultPlatformCurve(
current_fling_parameters_.source_device,
current_fling_parameters_.velocity,
- gfx::Vector2dF() /*initial_offset*/, false /*on_main_thread*/));
+ gfx::Vector2dF() /*initial_offset*/, false /*on_main_thread*/,
+ GetContentClient()->browser()->ShouldUseMobileFlingCurve()));
return true;
}
diff --git a/chromium/content/browser/renderer_host/input/fling_controller.h b/chromium/content/browser/renderer_host/input/fling_controller.h
index 929d35ec1c8..869e17b79e2 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller.h
+++ b/chromium/content/browser/renderer_host/input/fling_controller.h
@@ -178,8 +178,6 @@ class CONTENT_EXPORT FlingController {
// for determining if the fling start time should be re-initialized.
bool has_fling_animation_started_;
- bool send_wheel_events_nonblocking_;
-
base::WeakPtrFactory<FlingController> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(FlingController);
diff --git a/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc b/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
index 31a8d531226..9f658accb9f 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -5,10 +5,8 @@
#include "content/browser/renderer_host/input/fling_controller.h"
#include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
-#include "content/public/common/content_features.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/fling_booster.h"
@@ -51,8 +49,6 @@ class FlingControllerTest : public testing::Test,
GestureEventQueue::Config());
fling_controller_ = std::make_unique<FakeFlingController>(
queue_.get(), this, this, FlingController::Config());
- feature_list_.InitFromCommandLine(
- features::kTouchpadAndWheelScrollLatching.name, "");
}
// GestureEventQueueClient
@@ -129,7 +125,6 @@ class FlingControllerTest : public testing::Test,
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<GestureEventQueue> queue_;
- base::test::ScopedFeatureList feature_list_;
};
TEST_F(FlingControllerTest,
@@ -167,8 +162,15 @@ TEST_F(FlingControllerTest, ControllerHandlesTouchpadGestureFling) {
EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, last_sent_wheel_.momentum_phase);
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
- // Now cancel the fling. The GFC will end the fling.
+ // Now cancel the fling. The GFC will get suppressed by fling booster.
SimulateFlingCancel(blink::kWebGestureDeviceTouchpad);
+ EXPECT_TRUE(last_fling_cancel_filtered_);
+ EXPECT_TRUE(FlingInProgress());
+
+ // Wait for the boosting timer to expire. The delayed cancelation must work.
+ progress_time += base::TimeDelta::FromMilliseconds(500);
+ ProgressFling(progress_time);
+ EXPECT_FALSE(FlingInProgress());
EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, last_sent_wheel_.momentum_phase);
EXPECT_EQ(0.f, last_sent_wheel_.delta_x);
EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
@@ -400,9 +402,7 @@ TEST_F(FlingControllerTest, GestureFlingWithNegativeTimeDelta) {
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
}
-// TODO(sahel): Enable the test once boosting is enabled for touchpad fling.
-// https://crbug.com/249063
-TEST_F(FlingControllerTest, DISABLED_ControllerBoostsTouchpadFling) {
+TEST_F(FlingControllerTest, ControllerBoostsTouchpadFling) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler.cc b/chromium/content/browser/renderer_host/input/fling_scheduler.cc
index 0b6ab39313d..63a6f7cca39 100644
--- a/chromium/content/browser/renderer_host/input/fling_scheduler.cc
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler.cc
@@ -78,6 +78,7 @@ ui::Compositor* FlingScheduler::GetCompositor() {
}
void FlingScheduler::OnAnimationStep(base::TimeTicks timestamp) {
+ DCHECK(observed_compositor_);
if (fling_controller_)
fling_controller_->ProgressFling(timestamp);
}
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler.h b/chromium/content/browser/renderer_host/input/fling_scheduler.h
index c29c0fc43f5..634904e7b14 100644
--- a/chromium/content/browser/renderer_host/input/fling_scheduler.h
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_SCHEDULER_H_
#include "content/browser/renderer_host/input/fling_controller.h"
+#include "content/browser/renderer_host/input/fling_scheduler_base.h"
#include "ui/compositor/compositor_animation_observer.h"
namespace ui {
@@ -16,7 +17,7 @@ namespace content {
class RenderWidgetHostImpl;
-class CONTENT_EXPORT FlingScheduler : public FlingControllerSchedulerClient,
+class CONTENT_EXPORT FlingScheduler : public FlingSchedulerBase,
private ui::CompositorAnimationObserver {
public:
FlingScheduler(RenderWidgetHostImpl* host);
@@ -28,7 +29,8 @@ class CONTENT_EXPORT FlingScheduler : public FlingControllerSchedulerClient,
void DidStopFlingingOnBrowser(
base::WeakPtr<FlingController> fling_controller) override;
- void ProgressFlingOnBeginFrameIfneeded(base::TimeTicks current_time);
+ // FlingSchedulerBase
+ void ProgressFlingOnBeginFrameIfneeded(base::TimeTicks current_time) override;
protected:
virtual ui::Compositor* GetCompositor();
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler_android.cc b/chromium/content/browser/renderer_host/input/fling_scheduler_android.cc
new file mode 100644
index 00000000000..c2e968437ea
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler_android.cc
@@ -0,0 +1,83 @@
+// Copyright 2018 The Chromium Authors. All rights 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/fling_scheduler_android.h"
+
+#include "build/build_config.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "ui/compositor/compositor.h"
+
+namespace content {
+
+FlingSchedulerAndroid::FlingSchedulerAndroid(RenderWidgetHostImpl* host)
+ : host_(host) {
+ DCHECK(host);
+}
+
+FlingSchedulerAndroid::~FlingSchedulerAndroid() {
+ if (observed_window_)
+ observed_window_->RemoveObserver(this);
+}
+
+void FlingSchedulerAndroid::ScheduleFlingProgress(
+ base::WeakPtr<FlingController> fling_controller) {
+ DCHECK(fling_controller);
+ fling_controller_ = fling_controller;
+ if (!observed_window_) {
+ ui::WindowAndroid* window = GetRootWindow();
+ // If the root window does not have a Compositor (happens on Android
+ // WebView), we'll never receive an OnAnimate call. In this case fall back
+ // to BeginFrames coming from the host.
+ if (!window || !window->GetCompositor()) {
+ host_->SetNeedsBeginFrameForFlingProgress();
+ return;
+ }
+ window->AddObserver(this);
+ observed_window_ = window;
+ }
+ observed_window_->SetNeedsAnimate();
+}
+
+void FlingSchedulerAndroid::DidStopFlingingOnBrowser(
+ base::WeakPtr<FlingController> fling_controller) {
+ DCHECK(fling_controller);
+ if (observed_window_) {
+ observed_window_->RemoveObserver(this);
+ observed_window_ = nullptr;
+ }
+ fling_controller_ = nullptr;
+ host_->DidStopFlinging();
+}
+
+void FlingSchedulerAndroid::ProgressFlingOnBeginFrameIfneeded(
+ base::TimeTicks current_time) {
+ // If a WindowAndroid is being observed, there is no need for BeginFrames
+ // coming from the host.
+ if (observed_window_)
+ return;
+ if (!fling_controller_)
+ return;
+ fling_controller_->ProgressFling(current_time);
+}
+
+ui::WindowAndroid* FlingSchedulerAndroid::GetRootWindow() {
+ if (!host_->GetView())
+ return nullptr;
+ return host_->GetView()->GetNativeView()->GetWindowAndroid();
+}
+
+void FlingSchedulerAndroid::OnDetachCompositor() {
+ // Once the window's compositor has detached, we will no longer receive
+ // OnAnimate calls. Stop observing the window.
+ observed_window_->RemoveObserver(this);
+ observed_window_ = nullptr;
+}
+
+void FlingSchedulerAndroid::OnAnimate(base::TimeTicks frame_begin_time) {
+ DCHECK(observed_window_);
+ if (fling_controller_)
+ fling_controller_->ProgressFling(frame_begin_time);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler_android.h b/chromium/content/browser/renderer_host/input/fling_scheduler_android.h
new file mode 100644
index 00000000000..cbe1e6e119d
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler_android.h
@@ -0,0 +1,55 @@
+// Copyright 2018 The Chromium Authors. All 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_FLING_SCHEDULER_ANDROID_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_SCHEDULER_ANDROID_H_
+
+#include "content/browser/renderer_host/input/fling_scheduler_base.h"
+#include "content/common/content_export.h"
+#include "ui/android/window_android.h"
+#include "ui/android/window_android_observer.h"
+
+namespace content {
+
+class RenderWidgetHostImpl;
+
+class CONTENT_EXPORT FlingSchedulerAndroid : public FlingSchedulerBase,
+ public ui::WindowAndroidObserver {
+ public:
+ explicit FlingSchedulerAndroid(RenderWidgetHostImpl* host);
+ ~FlingSchedulerAndroid() override;
+
+ // FlingControllerSchedulerClient
+ void ScheduleFlingProgress(
+ base::WeakPtr<FlingController> fling_controller) override;
+ void DidStopFlingingOnBrowser(
+ base::WeakPtr<FlingController> fling_controller) override;
+
+ // FlingSchedulerBase
+ void ProgressFlingOnBeginFrameIfneeded(base::TimeTicks current_time) override;
+
+ protected:
+ RenderWidgetHostImpl* host_;
+ base::WeakPtr<FlingController> fling_controller_;
+
+ private:
+ ui::WindowAndroid* GetRootWindow();
+
+ // WindowAndroidObserver implementation.
+ void OnCompositingDidCommit() override {}
+ void OnRootWindowVisibilityChanged(bool visible) override {}
+ void OnAttachCompositor() override {}
+ void OnDetachCompositor() override;
+ void OnAnimate(base::TimeTicks frame_begin_time) override;
+ void OnActivityStopped() override {}
+ void OnActivityStarted() override {}
+
+ ui::WindowAndroid* observed_window_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(FlingSchedulerAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_SCHEDULER_ANDROID_H_
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler_base.h b/chromium/content/browser/renderer_host/input/fling_scheduler_base.h
new file mode 100644
index 00000000000..cc4b13a7b9c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler_base.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All 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_FLING_SCHEDULER_BASE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_SCHEDULER_BASE_H_
+
+#include "content/browser/renderer_host/input/fling_controller.h"
+
+namespace content {
+
+class FlingSchedulerBase : public FlingControllerSchedulerClient {
+ public:
+ virtual void ProgressFlingOnBeginFrameIfneeded(
+ base::TimeTicks current_time) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_SCHEDULER_BASE_H_
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 10cdaaf1a25..a9ff466e23a 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
@@ -47,13 +47,22 @@ GestureEventQueue::GestureEventQueue(
GestureEventQueue::~GestureEventQueue() { }
-bool GestureEventQueue::QueueEvent(
+bool GestureEventQueue::DebounceOrQueueEvent(
const GestureEventWithLatencyInfo& gesture_event) {
- TRACE_EVENT0("input", "GestureEventQueue::QueueEvent");
- if (!ShouldForwardForBounceReduction(gesture_event) ||
- fling_controller_.FilterGestureEvent(gesture_event)) {
+ // GFS should have been filtered in FlingControllerFilterEvent.
+ DCHECK_NE(gesture_event.event.GetType(), WebInputEvent::kGestureFlingStart);
+ if (!ShouldForwardForBounceReduction(gesture_event))
return false;
- }
+
+ QueueAndForwardIfNecessary(gesture_event);
+ return true;
+}
+
+bool GestureEventQueue::FlingControllerFilterEvent(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ TRACE_EVENT0("input", "GestureEventQueue::QueueEvent");
+ if (fling_controller_.FilterGestureEvent(gesture_event))
+ return true;
// fling_controller_ is in charge of handling GFS events and the events are
// not sent to the renderer, the controller processes the fling and generates
@@ -62,7 +71,7 @@ bool GestureEventQueue::QueueEvent(
if (gesture_event.event.GetType() == WebInputEvent::kGestureFlingStart) {
fling_controller_.ProcessGestureFlingStart(gesture_event);
fling_in_progress_ = true;
- return false;
+ return true;
}
// If the GestureFlingStart event is processed by the fling_controller_, the
@@ -70,11 +79,10 @@ bool GestureEventQueue::QueueEvent(
if (gesture_event.event.GetType() == WebInputEvent::kGestureFlingCancel) {
fling_controller_.ProcessGestureFlingCancel(gesture_event);
fling_in_progress_ = false;
- return false;
+ return true;
}
- QueueAndForwardIfNecessary(gesture_event);
- return true;
+ return false;
}
void GestureEventQueue::StopFling() {
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 db490fde11b..f07f3cd6220 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue.h
@@ -77,10 +77,13 @@ class CONTENT_EXPORT GestureEventQueue {
const Config& config);
~GestureEventQueue();
- // Adds a gesture to the queue if it passes the relevant filters. If
- // there are no events currently queued, the event will be forwarded
- // immediately. Returns false if the event wasn't queued and was filtered.
- bool QueueEvent(const GestureEventWithLatencyInfo&);
+ // Uses fling controller to filter the gesture event. Returns true if the
+ // event wasn't queued and was filtered.
+ bool FlingControllerFilterEvent(const GestureEventWithLatencyInfo&);
+
+ // Check for debouncing, or add the gesture event to the queue. Returns false
+ // if the event wasn't queued.
+ bool DebounceOrQueueEvent(const GestureEventWithLatencyInfo&);
// Indicates that the caller has received an acknowledgement from the renderer
// with state |ack_result| and event |type|. May send events if the queue is
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 d9fc411f476..a977b1921b5 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
@@ -118,7 +118,10 @@ class GestureEventQueueTest : public testing::Test,
}
void SimulateGestureEvent(const WebGestureEvent& gesture) {
- queue()->QueueEvent(GestureEventWithLatencyInfo(gesture));
+ GestureEventWithLatencyInfo gesture_event(gesture);
+ if (!queue()->FlingControllerFilterEvent(gesture_event)) {
+ queue()->DebounceOrQueueEvent(gesture_event);
+ }
}
void SimulateGestureEvent(WebInputEvent::Type type,
@@ -1030,10 +1033,10 @@ TEST_F(GestureEventQueueTest, DebounceDefersFollowingGestureEvents) {
EXPECT_EQ(2U, GestureEventQueueSize());
EXPECT_EQ(2U, GestureEventDebouncingQueueSize());
+ base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMilliseconds(5));
- base::RunLoop().Run();
+ FROM_HERE, run_loop.QuitClosure(), TimeDelta::FromMilliseconds(5));
+ run_loop.Run();
// The deferred events are correctly queued in coalescing queue.
EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
@@ -1053,64 +1056,6 @@ TEST_F(GestureEventQueueTest, DebounceDefersFollowingGestureEvents) {
}
}
-// Test that a GestureFlingStart is not filtered out by debouncing and that
-// GestureFlingStart causes debouncing queue to empty into gesture queue.
-TEST_F(GestureEventQueueTest, DebounceEndsWithFlingStartEvent) {
- SetUpForDebounce(3);
-
- SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
- blink::kWebGestureDeviceTouchpad);
- EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(1U, GestureEventQueueSize());
- EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
- EXPECT_TRUE(ScrollingInProgress());
-
- SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
- blink::kWebGestureDeviceTouchpad);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(1U, GestureEventQueueSize());
- EXPECT_EQ(1U, GestureEventDebouncingQueueSize());
-
- // The deferred events are correctly queued in coalescing queue. The GFS with
- // touchpad source is not queued since it is handled by fling controller.
- SimulateGestureFlingStartEvent(0, 10, blink::kWebGestureDeviceTouchpad);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(2U, GestureEventQueueSize());
- EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
- EXPECT_FALSE(ScrollingInProgress());
- EXPECT_TRUE(FlingInProgress());
-
- // While fling is in progress events don't get debounced.
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchpad);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(3U, GestureEventQueueSize());
- EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
-
- SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
- blink::kWebGestureDeviceTouchpad);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(4U, GestureEventQueueSize());
- EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
-
- SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
- blink::kWebGestureDeviceTouchpad);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(5U, GestureEventQueueSize());
- EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
-
- // Verify that the coalescing queue contains the correct events.
- WebInputEvent::Type expected[] = {
- WebInputEvent::kGestureScrollUpdate, WebInputEvent::kGestureScrollEnd,
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kGestureScrollUpdate};
-
- for (unsigned i = 0; i < sizeof(expected) / sizeof(WebInputEvent::Type);
- i++) {
- WebGestureEvent merged_event = GestureEventQueueEventAt(i);
- EXPECT_EQ(expected[i], merged_event.GetType());
- }
-}
-
// Test that non-scroll events are deferred while scrolling during the debounce
// interval and are discarded if a GestureScrollUpdate event arrives before the
// interval end.
diff --git a/chromium/content/browser/renderer_host/input/input_router.h b/chromium/content/browser/renderer_host/input/input_router.h
index 7b6c6f8cb4b..49cde65f553 100644
--- a/chromium/content/browser/renderer_host/input/input_router.h
+++ b/chromium/content/browser/renderer_host/input/input_router.h
@@ -62,7 +62,7 @@ class InputRouter : public IPC::Listener {
virtual void SetFrameTreeNodeId(int frameTreeNodeId) = 0;
// Return the currently allowed touch-action.
- virtual cc::TouchAction AllowedTouchAction() = 0;
+ virtual base::Optional<cc::TouchAction> AllowedTouchAction() = 0;
virtual void SetForceEnableZoom(bool enabled) = 0;
@@ -75,6 +75,15 @@ class InputRouter : public IPC::Listener {
// Used to check if a fling cancellation is deferred due to boosting or not.
virtual bool FlingCancellationIsDeferred() = 0;
+
+ // Called when a set-touch-action message is received from the renderer
+ // for a touch start event that is currently in flight.
+ virtual void OnSetTouchAction(cc::TouchAction touch_action) = 0;
+
+ // In the case when a gesture event is bubbled from a child frame to the main
+ // frame, we set the touch action in the main frame Auto even if there is no
+ // pending touch start.
+ virtual void ForceSetTouchActionAuto() = 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 c1308d16722..788b74bd305 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.cc
@@ -23,7 +23,6 @@
#include "content/common/view_messages.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
-#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/input_event_ack_state.h"
#include "ipc/ipc_sender.h"
@@ -78,10 +77,9 @@ InputRouterImpl::InputRouterImpl(
frame_tree_node_id_(-1),
active_renderer_fling_count_(0),
touch_scroll_started_sent_(false),
- wheel_scroll_latching_enabled_(base::FeatureList::IsEnabled(
- features::kTouchpadAndWheelScrollLatching)),
- wheel_event_queue_(this, wheel_scroll_latching_enabled_),
+ wheel_event_queue_(this),
touch_event_queue_(this, config.touch_config),
+ touchpad_pinch_event_queue_(this),
gesture_event_queue_(this,
this,
fling_scheduler_client,
@@ -136,6 +134,13 @@ void InputRouterImpl::SendGestureEvent(
GestureEventWithLatencyInfo gesture_event(original_gesture_event);
+ if (gesture_event_queue_.FlingControllerFilterEvent(gesture_event)) {
+ disposition_handler_->OnGestureEventAck(gesture_event,
+ InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ return;
+ }
+
if (touch_action_filter_.FilterGestureEvent(&gesture_event.event) ==
FilterGestureEventResult::kFilterGestureEventFiltered) {
disposition_handler_->OnGestureEventAck(gesture_event,
@@ -164,7 +169,14 @@ void InputRouterImpl::SendGestureEvent(
touch_event_queue_.OnGestureScrollEvent(gesture_event);
}
- if (!gesture_event_queue_.QueueEvent(gesture_event)) {
+ if (blink::WebInputEvent::IsPinchGestureEventType(
+ gesture_event.event.GetType()) &&
+ gesture_event.event.NeedsWheelEvent()) {
+ touchpad_pinch_event_queue_.QueueEvent(gesture_event);
+ return;
+ }
+
+ if (!gesture_event_queue_.DebounceOrQueueEvent(gesture_event)) {
disposition_handler_->OnGestureEventAck(gesture_event,
InputEventAckSource::BROWSER,
INPUT_EVENT_ACK_STATE_CONSUMED);
@@ -185,7 +197,9 @@ void InputRouterImpl::NotifySiteIsMobileOptimized(bool is_mobile_optimized) {
bool InputRouterImpl::HasPendingEvents() const {
return !touch_event_queue_.Empty() || !gesture_event_queue_.empty() ||
- wheel_event_queue_.has_pending() || active_renderer_fling_count_ > 0;
+ wheel_event_queue_.has_pending() ||
+ touchpad_pinch_event_queue_.has_pending() ||
+ active_renderer_fling_count_ > 0;
}
void InputRouterImpl::SetDeviceScaleFactor(float device_scale_factor) {
@@ -200,8 +214,9 @@ void InputRouterImpl::SetForceEnableZoom(bool enabled) {
touch_action_filter_.SetForceEnableZoom(enabled);
}
-cc::TouchAction InputRouterImpl::AllowedTouchAction() {
- return touch_action_filter_.allowed_touch_action();
+base::Optional<cc::TouchAction> InputRouterImpl::AllowedTouchAction() {
+ return touch_action_filter_.allowed_touch_action().value_or(
+ cc::kTouchActionAuto);
}
void InputRouterImpl::BindHost(mojom::WidgetInputHandlerHostRequest request,
@@ -224,15 +239,12 @@ bool InputRouterImpl::FlingCancellationIsDeferred() {
}
void InputRouterImpl::CancelTouchTimeout() {
- touch_event_queue_.SetAckTimeoutEnabled(false);
+ UpdateTouchAckTimeoutEnabled();
}
void InputRouterImpl::SetWhiteListedTouchAction(cc::TouchAction touch_action,
uint32_t unique_touch_event_id,
InputEventAckState state) {
- // TODO(hayleyferr): Catch the cases that we have filtered out sending the
- // touchstart.
-
touch_action_filter_.OnSetWhiteListedTouchAction(touch_action);
client_->OnSetWhiteListedTouchAction(touch_action);
}
@@ -337,12 +349,12 @@ void InputRouterImpl::OnTouchEventAck(const TouchEventWithLatencyInfo& event,
// in some cases we may filter out sending the touchstart - catch those here.
if (WebTouchEventTraits::IsTouchSequenceStart(event.event) &&
ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
- touch_action_filter_.ResetTouchAction();
+ // Touch action must be auto when there is no consumer
+ touch_action_filter_.OnSetTouchAction(cc::kTouchActionAuto);
UpdateTouchAckTimeoutEnabled();
}
disposition_handler_->OnTouchEventAck(event, ack_source, ack_result);
- // Reset the touch action at the end of a touch-action sequence.
if (WebTouchEventTraits::IsTouchSequenceEnd(event.event)) {
touch_action_filter_.ReportAndResetTouchAction();
UpdateTouchAckTimeoutEnabled();
@@ -413,6 +425,18 @@ void InputRouterImpl::ForwardGestureEventWithLatencyInfo(
client_->ForwardGestureEventWithLatencyInfo(event, latency_info);
}
+void InputRouterImpl::SendMouseWheelEventForPinchImmediately(
+ const MouseWheelEventWithLatencyInfo& event) {
+ SendMouseWheelEventImmediately(event);
+}
+
+void InputRouterImpl::OnGestureEventForPinchAck(
+ const GestureEventWithLatencyInfo& event,
+ InputEventAckSource ack_source,
+ InputEventAckState ack_result) {
+ OnGestureEventAck(event, ack_source, ack_result);
+}
+
bool InputRouterImpl::IsWheelScrollInProgress() {
return client_->IsWheelScrollInProgress();
}
@@ -444,8 +468,7 @@ void InputRouterImpl::FilterAndSendWebInputEvent(
std::unique_ptr<InputEvent> event = std::make_unique<InputEvent>(
ScaleEvent(input_event, device_scale_factor_), latency_info);
- if (WebInputEventTraits::ShouldBlockEventStream(
- input_event, wheel_scroll_latching_enabled_)) {
+ if (WebInputEventTraits::ShouldBlockEventStream(input_event)) {
TRACE_EVENT_INSTANT0("input", "InputEventSentBlocking",
TRACE_EVENT_SCOPE_THREAD);
client_->IncrementInFlightEventCount();
@@ -573,23 +596,23 @@ void InputRouterImpl::MouseWheelEventHandled(
DidOverscroll(overscroll.value());
wheel_event_queue_.ProcessMouseWheelAck(source, state, event.latency);
+ touchpad_pinch_event_queue_.ProcessMouseWheelAck(source, state,
+ event.latency);
}
void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) {
TRACE_EVENT1("input", "InputRouterImpl::OnHasTouchEventHandlers",
"has_handlers", has_handlers);
- // Lack of a touch handler indicates that the page either has no touch-action
- // modifiers or that all its touch-action modifiers are auto. Resetting the
- // touch-action here allows forwarding of subsequent gestures even if the
- // underlying touches never reach the router.
- if (!has_handlers)
- touch_action_filter_.ResetTouchAction();
-
+ touch_action_filter_.OnHasTouchEventHandlers(has_handlers);
touch_event_queue_.OnHasTouchEventHandlers(has_handlers);
client_->OnHasTouchEventHandlers(has_handlers);
}
+void InputRouterImpl::ForceSetTouchActionAuto() {
+ touch_action_filter_.OnSetTouchAction(cc::kTouchActionAuto);
+}
+
void InputRouterImpl::OnSetTouchAction(cc::TouchAction touch_action) {
TRACE_EVENT1("input", "InputRouterImpl::OnSetTouchAction", "action",
touch_action);
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 205cb3abc83..53605ce1286 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.h
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.h
@@ -22,6 +22,7 @@
#include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
#include "content/browser/renderer_host/input/passthrough_touch_event_queue.h"
#include "content/browser/renderer_host/input/touch_action_filter.h"
+#include "content/browser/renderer_host/input/touchpad_pinch_event_queue.h"
#include "content/common/input/input_event_stream_validator.h"
#include "content/common/input/input_handler.mojom.h"
#include "content/common/widget.mojom.h"
@@ -55,6 +56,7 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter,
public FlingControllerEventSenderClient,
public MouseWheelEventQueueClient,
public PassthroughTouchEventQueueClient,
+ public TouchpadPinchEventQueueClient,
public mojom::WidgetInputHandlerHost {
public:
InputRouterImpl(InputRouterImplClient* client,
@@ -77,11 +79,13 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter,
void SetDeviceScaleFactor(float device_scale_factor) override;
void SetFrameTreeNodeId(int frame_tree_node_id) override;
void SetForceEnableZoom(bool enabled) override;
- cc::TouchAction AllowedTouchAction() override;
+ base::Optional<cc::TouchAction> AllowedTouchAction() override;
void BindHost(mojom::WidgetInputHandlerHostRequest request,
bool frame_handler) override;
void StopFling() override;
bool FlingCancellationIsDeferred() override;
+ void OnSetTouchAction(cc::TouchAction touch_action) override;
+ void ForceSetTouchActionAuto() override;
// InputHandlerHost impl
void CancelTouchTimeout() override;
@@ -109,6 +113,7 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter,
private:
friend class InputRouterImplTest;
friend class MockRenderWidgetHost;
+ friend class RenderWidgetHostBrowserTest;
// Keeps track of last position of touch points and sets MovementXY for them.
void SetMovementXYForTouchPoints(blink::WebTouchEvent* event);
@@ -148,6 +153,13 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter,
const ui::LatencyInfo& latency_info) override;
bool IsWheelScrollInProgress() override;
+ // TouchpadPinchEventQueueClient
+ void SendMouseWheelEventForPinchImmediately(
+ const MouseWheelEventWithLatencyInfo& event) override;
+ void OnGestureEventForPinchAck(const GestureEventWithLatencyInfo& event,
+ InputEventAckSource ack_source,
+ InputEventAckState ack_result) override;
+
void FilterAndSendWebInputEvent(
const blink::WebInputEvent& input_event,
const ui::LatencyInfo& latency_info,
@@ -191,7 +203,6 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter,
// IPC message handlers
void OnHasTouchEventHandlers(bool has_handlers);
- void OnSetTouchAction(cc::TouchAction touch_action);
// Called when a touch timeout-affecting bit has changed, in turn toggling the
// touch ack timeout feature of the |touch_event_queue_| as appropriate. Input
@@ -213,9 +224,9 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter,
// gesture scroll yet.
bool touch_scroll_started_sent_;
- bool wheel_scroll_latching_enabled_;
MouseWheelEventQueue wheel_event_queue_;
PassthroughTouchEventQueue touch_event_queue_;
+ TouchpadPinchEventQueue touchpad_pinch_event_queue_;
GestureEventQueue gesture_event_queue_;
TouchActionFilter touch_action_filter_;
InputEventStreamValidator input_stream_validator_;
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 3e580d0864f..5ff4766f351 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
@@ -64,9 +64,7 @@ namespace content {
namespace {
bool ShouldBlockEventStream(const blink::WebInputEvent& event) {
- return ui::WebInputEventTraits::ShouldBlockEventStream(
- event,
- base::FeatureList::IsEnabled(features::kTouchpadAndWheelScrollLatching));
+ return ui::WebInputEventTraits::ShouldBlockEventStream(event);
}
WebInputEvent& GetEventWithType(WebInputEvent::Type type) {
@@ -92,12 +90,6 @@ WebInputEvent& GetEventWithType(WebInputEvent::Type type) {
return *event;
}
-enum WheelScrollingMode {
- kWheelScrollingModeNone,
- kWheelScrollLatching,
- kAsyncWheelEvents,
-};
-
} // namespace
// TODO(dtapuska): Remove this class when we don't have multiple implementations
@@ -212,26 +204,9 @@ class MockInputRouterImplClient : public InputRouterImplClient {
class InputRouterImplTest : public testing::Test {
public:
- InputRouterImplTest(
- WheelScrollingMode wheel_scrolling_mode = kWheelScrollLatching)
- : wheel_scroll_latching_enabled_(wheel_scrolling_mode !=
- kWheelScrollingModeNone),
- scoped_task_environment_(
+ InputRouterImplTest()
+ : scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI) {
- if (wheel_scrolling_mode == kAsyncWheelEvents) {
- feature_list_.InitWithFeatures({features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents},
- {});
- } else if (wheel_scrolling_mode == kWheelScrollLatching) {
- feature_list_.InitWithFeatures(
- {features::kTouchpadAndWheelScrollLatching},
- {features::kAsyncWheelEvents});
- } else if (wheel_scrolling_mode == kWheelScrollingModeNone) {
- feature_list_.InitWithFeatures({},
- {features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents});
- }
-
vsync_feature_list_.InitAndEnableFeature(
features::kVsyncAlignedInputEvents);
}
@@ -282,17 +257,6 @@ class InputRouterImplTest : public testing::Test {
}
void SimulateWheelEvent(float x,
- float y,
- float dX,
- float dY,
- int modifiers,
- bool precise) {
- input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(
- SyntheticWebMouseWheelEventBuilder::Build(x, y, dX, dY, modifiers,
- precise)));
- }
-
- void SimulateWheelEventWithPhase(float x,
float y,
float dX,
float dY,
@@ -305,19 +269,9 @@ class InputRouterImplTest : public testing::Test {
input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(wheel_event));
}
- void SimulateWheelEventPossiblyIncludingPhase(
- bool ignore_phase,
- float x,
- float y,
- float dX,
- float dY,
- int modifiers,
- bool precise,
- WebMouseWheelEvent::Phase phase) {
- if (ignore_phase)
- SimulateWheelEvent(x, y, dX, dY, modifiers, precise);
- else
- SimulateWheelEventWithPhase(x, y, dX, dY, modifiers, precise, phase);
+ void SimulateWheelEvent(WebMouseWheelEvent::Phase phase) {
+ input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(
+ SyntheticWebMouseWheelEventBuilder::Build(phase)));
}
void SimulateMouseEvent(WebInputEvent::Type type, int x, int y) {
@@ -325,11 +279,6 @@ class InputRouterImplTest : public testing::Test {
SyntheticWebMouseEventBuilder::Build(type, x, y, 0)));
}
- void SimulateWheelEventWithPhase(WebMouseWheelEvent::Phase phase) {
- input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(
- SyntheticWebMouseWheelEventBuilder::Build(phase)));
- }
-
void SimulateGestureEvent(WebGestureEvent gesture) {
if (gesture.GetType() == WebInputEvent::kGestureScrollBegin &&
gesture.SourceDevice() == blink::kWebGestureDeviceTouchscreen &&
@@ -373,6 +322,28 @@ class InputRouterImplTest : public testing::Test {
scale, anchor_x, anchor_y, modifiers, source_device));
}
+ void SimulateTouchpadGesturePinchEventWithoutWheel(WebInputEvent::Type type,
+ float scale,
+ float anchor_x,
+ float anchor_y,
+ int modifiers) {
+ DCHECK(blink::WebInputEvent::IsPinchGestureEventType(type));
+ WebGestureEvent event =
+ (type == blink::WebInputEvent::kGesturePinchUpdate
+ ? SyntheticWebGestureEventBuilder::BuildPinchUpdate(
+ scale, anchor_x, anchor_y, modifiers,
+ blink::kWebGestureDeviceTouchpad)
+ : SyntheticWebGestureEventBuilder::Build(
+ type, blink::kWebGestureDeviceTouchpad));
+ // For touchpad pinch, we first send wheel events to the renderer. Only
+ // after these have been acknowledged do we send the actual gesture pinch
+ // events to the renderer. We indicate here that the wheel sending phase is
+ // done for the purpose of testing the sending of the gesture events
+ // themselves.
+ event.SetNeedsWheelEvent(false);
+ SimulateGestureEvent(event);
+ }
+
void SimulateGestureFlingStartEvent(float velocity_x,
float velocity_y,
WebGestureDevice source_device) {
@@ -427,44 +398,39 @@ class InputRouterImplTest : public testing::Test {
unique_touch_event_id, ack_result);
}
+ void ResetTouchAction() {
+ input_router_->touch_action_filter_.ResetTouchAction();
+ }
+
DispatchedMessages GetAndResetDispatchedMessages() {
return client_->GetAndResetDispatchedMessages();
}
static void RunTasksAndWait(base::TimeDelta delay) {
+ base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- delay);
- base::RunLoop().Run();
+ FROM_HERE, run_loop.QuitClosure(), delay);
+ run_loop.Run();
}
- void OverscrollDispatch();
+ void PressAndSetTouchActionAuto() {
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ input_router_->OnSetTouchAction(cc::kTouchActionAuto);
+ GetAndResetDispatchedMessages();
+ disposition_handler_->GetAndResetAckCount();
+ }
InputRouter::Config config_;
std::unique_ptr<MockInputRouterImplClient> client_;
std::unique_ptr<InputRouterImpl> input_router_;
std::unique_ptr<MockInputDispositionHandler> disposition_handler_;
- bool wheel_scroll_latching_enabled_;
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
SyntheticWebTouchEvent touch_event_;
base::test::ScopedFeatureList vsync_feature_list_;
- base::test::ScopedFeatureList feature_list_;
-};
-
-class InputRouterImplWheelScrollLatchingDisabledTest
- : public InputRouterImplTest {
- public:
- InputRouterImplWheelScrollLatchingDisabledTest()
- : InputRouterImplTest(kWheelScrollingModeNone) {}
-};
-
-class InputRouterImplAsyncWheelEventEnabledTest : public InputRouterImplTest {
- public:
- InputRouterImplAsyncWheelEventEnabledTest()
- : InputRouterImplTest(kAsyncWheelEvents) {}
};
TEST_F(InputRouterImplTest, HandledInputEvent) {
@@ -521,24 +487,22 @@ TEST_F(InputRouterImplTest, HandleKeyEventsWeSent) {
TEST_F(InputRouterImplTest, CoalescesWheelEvents) {
// Simulate wheel events.
- SimulateWheelEventPossiblyIncludingPhase(
- !wheel_scroll_latching_enabled_, 0, 0, 0, -5, 0, false,
- WebMouseWheelEvent::kPhaseBegan); // sent directly
- SimulateWheelEventPossiblyIncludingPhase(
- !wheel_scroll_latching_enabled_, 0, 0, 0, -10, 0, false,
- WebMouseWheelEvent::kPhaseChanged); // enqueued
- SimulateWheelEventPossiblyIncludingPhase(
- !wheel_scroll_latching_enabled_, 0, 0, 8, -6, 0, false,
+ SimulateWheelEvent(0, 0, 0, -5, 0, false,
+ WebMouseWheelEvent::kPhaseBegan); // sent directly
+ SimulateWheelEvent(0, 0, 0, -10, 0, false,
+ WebMouseWheelEvent::kPhaseChanged); // enqueued
+ SimulateWheelEvent(
+ 0, 0, 8, -6, 0, false,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
- SimulateWheelEventPossiblyIncludingPhase(
- !wheel_scroll_latching_enabled_, 0, 0, 9, -7, 1, false,
+ SimulateWheelEvent(
+ 0, 0, 9, -7, 1, false,
WebMouseWheelEvent::kPhaseChanged); // enqueued, different modifiers
- SimulateWheelEventPossiblyIncludingPhase(
- !wheel_scroll_latching_enabled_, 0, 0, 0, -10, 0, false,
+ SimulateWheelEvent(
+ 0, 0, 0, -10, 0, false,
WebMouseWheelEvent::kPhaseChanged); // enqueued, different modifiers
// Explicitly verify that PhaseEnd isn't coalesced to avoid bugs like
// https://crbug.com/154740.
- SimulateWheelEventWithPhase(WebMouseWheelEvent::kPhaseEnded); // enqueued
+ SimulateWheelEvent(WebMouseWheelEvent::kPhaseEnded); // enqueued
// Check that only the first event was sent.
DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages();
@@ -697,162 +661,8 @@ TEST_F(InputRouterImplTest, TouchEventQueueFlush) {
TEST_F(InputRouterImplTest, UnhandledWheelEvent) {
// Simulate wheel events.
- SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
- 0, 0, -5, 0, false,
- WebMouseWheelEvent::kPhaseBegan);
- SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
- 0, 0, -10, 0, false,
- WebMouseWheelEvent::kPhaseChanged);
-
- // Check that only the first event was sent.
- DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages();
- ASSERT_EQ(1U, dispatched_messages.size());
- ASSERT_TRUE(dispatched_messages[0]->ToEvent());
-
- // Indicate that the wheel event was unhandled.
- dispatched_messages[0]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- dispatched_messages = GetAndResetDispatchedMessages();
-
- // GestureEventQueue allows multiple in-flight events, so there should be a
- // ScrollBegin, ScrollUpdate, and MouseWheel sent.
- ASSERT_EQ(3U, dispatched_messages.size());
- ASSERT_TRUE(dispatched_messages[0]->ToEvent());
- ASSERT_TRUE(dispatched_messages[1]->ToEvent());
- ASSERT_TRUE(dispatched_messages[2]->ToEvent());
-
- ASSERT_EQ(WebInputEvent::kGestureScrollBegin,
- dispatched_messages[0]->ToEvent()->Event()->web_event->GetType());
- ASSERT_EQ(WebInputEvent::kGestureScrollUpdate,
- dispatched_messages[1]->ToEvent()->Event()->web_event->GetType());
- ASSERT_EQ(WebInputEvent::kMouseWheel,
- dispatched_messages[2]->ToEvent()->Event()->web_event->GetType());
- dispatched_messages[0]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Check that the ack for ScrollBegin, MouseWheel were
- // processed.
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -5);
-
- // Ack the gesture scroll update event.
- dispatched_messages[1]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
-
- // Ack the mouse wheel event.
- dispatched_messages[2]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
-
- dispatched_messages = GetAndResetDispatchedMessages();
- ASSERT_EQ(1U, dispatched_messages.size());
- ASSERT_TRUE(dispatched_messages[0]->ToEvent());
- ASSERT_EQ(WebInputEvent::kGestureScrollUpdate,
- dispatched_messages[0]->ToEvent()->Event()->web_event->GetType());
-
- // Check that the correct unhandled wheel event was received.
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
- disposition_handler_->acked_wheel_event_state());
- EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -10);
-
- dispatched_messages[0]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Check that the ack for ScrollUpdate were processed.
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
-}
-TEST_F(InputRouterImplWheelScrollLatchingDisabledTest, UnhandledWheelEvent) {
- // Simulate wheel events.
- SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
- 0, 0, -5, 0, false,
- WebMouseWheelEvent::kPhaseBegan);
- SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
- 0, 0, -10, 0, false,
- WebMouseWheelEvent::kPhaseChanged);
-
- // Check that only the first event was sent.
- DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages();
- ASSERT_EQ(1U, dispatched_messages.size());
- ASSERT_TRUE(dispatched_messages[0]->ToEvent());
-
- // Indicate that the wheel event was unhandled.
- dispatched_messages[0]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- dispatched_messages = GetAndResetDispatchedMessages();
-
- // Check that the ack for MouseWheel and GestureScrollBegin was processed.
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -5);
-
- // There should be a ScrollBegin, ScrollUpdate, ScrollEnd and MouseWheel sent.
- ASSERT_EQ(4U, dispatched_messages.size());
- ASSERT_TRUE(dispatched_messages[0]->ToEvent());
- ASSERT_TRUE(dispatched_messages[1]->ToEvent());
- ASSERT_TRUE(dispatched_messages[2]->ToEvent());
- ASSERT_TRUE(dispatched_messages[3]->ToEvent());
-
- ASSERT_EQ(WebInputEvent::kGestureScrollBegin,
- dispatched_messages[0]->ToEvent()->Event()->web_event->GetType());
- ASSERT_EQ(WebInputEvent::kGestureScrollUpdate,
- dispatched_messages[1]->ToEvent()->Event()->web_event->GetType());
- ASSERT_EQ(WebInputEvent::kGestureScrollEnd,
- dispatched_messages[2]->ToEvent()->Event()->web_event->GetType());
- ASSERT_EQ(WebInputEvent::kMouseWheel,
- dispatched_messages[3]->ToEvent()->Event()->web_event->GetType());
-
- // Ack the ScrollUpdate
- dispatched_messages[1]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Check that the ack for ScrollUpdate and ScrollEnd was processed.
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
-
- // The GestureScrollEnd should have already been processed.
- EXPECT_EQ(0U, GetAndResetDispatchedMessages().size());
-
- // Ack the MouseWheel.
- dispatched_messages[3]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // Check that the ack for MouseWheel and GestureScrollBegin was processed.
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
-
- // There should be a ScrollBegin, ScrollUpdate and ScrollEnd sent.
- dispatched_messages = GetAndResetDispatchedMessages();
- ASSERT_EQ(3U, dispatched_messages.size());
- ASSERT_TRUE(dispatched_messages[0]->ToEvent());
- ASSERT_TRUE(dispatched_messages[1]->ToEvent());
- ASSERT_TRUE(dispatched_messages[2]->ToEvent());
- ASSERT_EQ(WebInputEvent::kGestureScrollBegin,
- dispatched_messages[0]->ToEvent()->Event()->web_event->GetType());
- ASSERT_EQ(WebInputEvent::kGestureScrollUpdate,
- dispatched_messages[1]->ToEvent()->Event()->web_event->GetType());
- ASSERT_EQ(WebInputEvent::kGestureScrollEnd,
- dispatched_messages[2]->ToEvent()->Event()->web_event->GetType());
-
- // Check that the correct unhandled wheel event was received.
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
- disposition_handler_->acked_wheel_event_state());
- EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -10);
-
- dispatched_messages[1]->ToEvent()->CallCallback(
- INPUT_EVENT_ACK_STATE_CONSUMED);
- // The GestureScrollEnd should have already been processed.
- EXPECT_EQ(0U, GetAndResetDispatchedMessages().size());
-
- // Check that the ack for the ScrollUpdate and ScrollEnd were processed.
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
-}
-
-TEST_F(InputRouterImplAsyncWheelEventEnabledTest, UnhandledWheelEvent) {
- // Simulate wheel events.
- SimulateWheelEventWithPhase(0, 0, 0, -5, 0, false,
- WebMouseWheelEvent::kPhaseBegan);
- SimulateWheelEventWithPhase(0, 0, 0, -10, 0, false,
- WebMouseWheelEvent::kPhaseChanged);
+ SimulateWheelEvent(0, 0, 0, -5, 0, false, WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEvent(0, 0, 0, -10, 0, false, WebMouseWheelEvent::kPhaseChanged);
// Check that only the first event was sent.
DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages();
@@ -928,6 +738,7 @@ TEST_F(InputRouterImplTest, TouchTypesIgnoringAck) {
// Precede the TouchCancel with an appropriate TouchStart;
PressTouchPoint(1, 1);
SendTouchEvent();
+ input_router_->OnSetTouchAction(cc::kTouchActionAuto);
DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages();
ASSERT_EQ(1U, dispatched_messages.size());
ASSERT_TRUE(dispatched_messages[0]->ToEvent());
@@ -971,6 +782,7 @@ TEST_F(InputRouterImplTest, GestureTypesIgnoringAck) {
for (size_t i = 0; i < arraysize(eventTypes); ++i) {
WebInputEvent::Type type = eventTypes[i];
if (ShouldBlockEventStream(GetEventWithType(type))) {
+ PressAndSetTouchActionAuto();
SimulateGestureEvent(type, blink::kWebGestureDeviceTouchscreen);
DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages();
@@ -1001,6 +813,10 @@ TEST_F(InputRouterImplTest, GestureTypesIgnoringAck) {
EXPECT_EQ(0, client_->in_flight_event_count());
EXPECT_FALSE(HasPendingEvents());
continue;
+
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ GetAndResetDispatchedMessages();
}
SimulateGestureEvent(type, blink::kWebGestureDeviceTouchscreen);
@@ -1067,7 +883,7 @@ TEST_F(InputRouterImplTest, GestureTypesIgnoringAckInterleaved) {
// Interleave a few events that do and do not ignore acks. All gesture events
// should be dispatched immediately, but the acks will be blocked on blocking
// events.
-
+ PressAndSetTouchActionAuto();
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages();
@@ -1153,11 +969,15 @@ TEST_F(InputRouterImplTest, GestureTypesIgnoringAckInterleaved) {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0, client_->in_flight_event_count());
+
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
}
// Test that GestureShowPress events don't get out of order due to
// ignoring their acks.
TEST_F(InputRouterImplTest, GestureShowPressIsInOrder) {
+ PressAndSetTouchActionAuto();
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages();
@@ -1209,6 +1029,9 @@ TEST_F(InputRouterImplTest, GestureShowPressIsInOrder) {
EXPECT_EQ(0U, GetAndResetDispatchedMessages().size());
EXPECT_EQ(3U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0, client_->in_flight_event_count());
+
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
}
// Test that touch ack timeout behavior is properly configured for
@@ -1242,6 +1065,8 @@ TEST_F(InputRouterImplTest, TouchAckTimeoutConfigured) {
ReleaseTouchPoint(0);
SendTouchEvent();
EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+
+ PressAndSetTouchActionAuto();
EXPECT_EQ(0U, GetAndResetDispatchedMessages().size());
ASSERT_TRUE(TouchEventTimeoutEnabled());
@@ -1272,6 +1097,7 @@ TEST_F(InputRouterImplTest, TouchAckTimeoutConfigured) {
PressTouchPoint(1, 1);
SendTouchEvent();
+ input_router_->OnSetTouchAction(cc::kTouchActionNone);
DispatchedMessages touch_press_event3 = GetAndResetDispatchedMessages();
ASSERT_EQ(1u, touch_press_event3.size());
ASSERT_TRUE(touch_press_event3[0]->ToEvent());
@@ -1291,6 +1117,8 @@ TEST_F(InputRouterImplTest, TouchAckTimeoutConfigured) {
// should be restored.
PressTouchPoint(1, 1);
SendTouchEvent();
+ ResetTouchAction();
+ input_router_->OnSetTouchAction(cc::kTouchActionAuto);
EXPECT_TRUE(TouchEventTimeoutEnabled());
}
@@ -1336,6 +1164,8 @@ TEST_F(InputRouterImplTest,
// End the touch sequence.
ReleaseTouchPoint(0);
SendTouchEvent();
+ ResetTouchAction();
+ input_router_->OnSetTouchAction(cc::kTouchActionAuto);
dispatched_messages = GetAndResetDispatchedMessages();
EXPECT_EQ(1U, dispatched_messages.size());
dispatched_messages[0]->ToEvent()->CallCallback(
@@ -1417,6 +1247,9 @@ TEST_F(InputRouterImplTest, TouchActionResetBeforeEventReachesRenderer) {
// Ensure touch action has been set to auto, as a new touch sequence has
// started.
touch_press_event2[0]->ToEvent()->CallCallback(
+ InputEventAckSource::COMPOSITOR_THREAD, ui::LatencyInfo(),
+ INPUT_EVENT_ACK_STATE_CONSUMED, base::nullopt, cc::kTouchActionAuto);
+ touch_press_event2[0]->ToEvent()->CallCallback(
INPUT_EVENT_ACK_STATE_CONSUMED);
touch_move_event2[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(0U, GetAndResetDispatchedMessages().size());
@@ -1487,6 +1320,7 @@ TEST_F(InputRouterImplTest, TouchActionResetWhenTouchHasNoConsumer) {
touch_press_event2[0]->ToEvent()->CallCallback(
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ PressAndSetTouchActionAuto();
// Ensure touch action has been set to auto, as the touch had no consumer.
EXPECT_EQ(0U, GetAndResetDispatchedMessages().size());
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
@@ -1561,6 +1395,7 @@ TEST_F(InputRouterImplTest, AsyncTouchMoveAckedImmediately) {
PressTouchPoint(1, 1);
SendTouchEvent();
+ input_router_->OnSetTouchAction(cc::kTouchActionAuto);
EXPECT_TRUE(client_->GetAndResetFilterEventCalled());
DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages();
ASSERT_EQ(1U, dispatched_messages.size());
@@ -1676,6 +1511,12 @@ TEST_F(InputRouterImplTest, TouchpadPinchUpdate) {
// Note that the Touchscreen case is verified as NOT doing this as
// part of the ShowPressIsInOrder test.
+ SimulateGestureEvent(WebInputEvent::kGesturePinchBegin,
+ blink::kWebGestureDeviceTouchpad);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ ASSERT_EQ(WebInputEvent::kGesturePinchBegin,
+ disposition_handler_->ack_event_type());
+
SimulateGesturePinchUpdateEvent(1.5f, 20, 25, 0,
blink::kWebGestureDeviceTouchpad);
@@ -1685,13 +1526,15 @@ TEST_F(InputRouterImplTest, TouchpadPinchUpdate) {
ASSERT_TRUE(dispatched_messages[0]->ToEvent());
const WebInputEvent* input_event =
dispatched_messages[0]->ToEvent()->Event()->web_event.get();
- ASSERT_EQ(WebInputEvent::kGesturePinchUpdate, input_event->GetType());
- const WebGestureEvent* gesture_event =
- static_cast<const WebGestureEvent*>(input_event);
- EXPECT_EQ(20, gesture_event->PositionInWidget().x);
- EXPECT_EQ(25, gesture_event->PositionInWidget().y);
- EXPECT_EQ(20, gesture_event->PositionInScreen().x);
- EXPECT_EQ(25, gesture_event->PositionInScreen().y);
+ ASSERT_EQ(WebInputEvent::kMouseWheel, input_event->GetType());
+ const WebMouseWheelEvent* synthetic_wheel =
+ static_cast<const WebMouseWheelEvent*>(input_event);
+ EXPECT_EQ(20, synthetic_wheel->PositionInWidget().x);
+ EXPECT_EQ(25, synthetic_wheel->PositionInWidget().y);
+ EXPECT_EQ(20, synthetic_wheel->PositionInScreen().x);
+ EXPECT_EQ(25, synthetic_wheel->PositionInScreen().y);
+ EXPECT_TRUE(synthetic_wheel->GetModifiers() &
+ blink::WebInputEvent::kControlKey);
dispatched_messages[0]->ToEvent()->CallCallback(
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
@@ -1714,8 +1557,8 @@ TEST_F(InputRouterImplTest, TouchpadPinchUpdate) {
ASSERT_EQ(1U, dispatched_messages.size());
ASSERT_TRUE(dispatched_messages[0]->ToEvent());
input_event = dispatched_messages[0]->ToEvent()->Event()->web_event.get();
- ASSERT_EQ(WebInputEvent::kGesturePinchUpdate, input_event->GetType());
- gesture_event = static_cast<const WebGestureEvent*>(input_event);
+ ASSERT_EQ(WebInputEvent::kMouseWheel, input_event->GetType());
+ synthetic_wheel = static_cast<const WebMouseWheelEvent*>(input_event);
dispatched_messages[0]->ToEvent()->CallCallback(
INPUT_EVENT_ACK_STATE_CONSUMED);
@@ -1728,6 +1571,12 @@ TEST_F(InputRouterImplTest, TouchpadPinchUpdate) {
EXPECT_FLOAT_EQ(
0.3f,
disposition_handler_->acked_gesture_event().data.pinch_update.scale);
+
+ SimulateGestureEvent(WebInputEvent::kGesturePinchEnd,
+ blink::kWebGestureDeviceTouchpad);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ ASSERT_EQ(WebInputEvent::kGesturePinchEnd,
+ disposition_handler_->ack_event_type());
}
// Test proper handling of touchpad Gesture{Pinch,Scroll}Update sequences.
@@ -1744,8 +1593,8 @@ TEST_F(InputRouterImplTest, TouchpadPinchAndScrollUpdate) {
EXPECT_EQ(2, client_->in_flight_event_count());
// Subsequent scroll and pinch events will also be sent immediately.
- SimulateGesturePinchUpdateEvent(1.5f, 20, 25, 0,
- blink::kWebGestureDeviceTouchpad);
+ SimulateTouchpadGesturePinchEventWithoutWheel(
+ WebInputEvent::kGesturePinchUpdate, 1.5f, 20, 25, 0);
DispatchedMessages temp_dispatched_messages = GetAndResetDispatchedMessages();
ASSERT_EQ(1U, temp_dispatched_messages.size());
ASSERT_TRUE(temp_dispatched_messages[0]->ToEvent());
@@ -1760,8 +1609,8 @@ TEST_F(InputRouterImplTest, TouchpadPinchAndScrollUpdate) {
dispatched_messages.emplace_back(std::move(temp_dispatched_messages.at(0)));
EXPECT_EQ(4, client_->in_flight_event_count());
- SimulateGesturePinchUpdateEvent(1.5f, 20, 25, 0,
- blink::kWebGestureDeviceTouchpad);
+ SimulateTouchpadGesturePinchEventWithoutWheel(
+ WebInputEvent::kGesturePinchUpdate, 1.5f, 20, 25, 0);
temp_dispatched_messages = GetAndResetDispatchedMessages();
ASSERT_EQ(1U, temp_dispatched_messages.size());
ASSERT_TRUE(temp_dispatched_messages[0]->ToEvent());
@@ -1815,7 +1664,7 @@ TEST_F(InputRouterImplTest, TouchpadPinchAndScrollUpdate) {
// Test proper routing of overscroll notifications received either from
// event acks or from |DidOverscroll| IPC messages.
-void InputRouterImplTest::OverscrollDispatch() {
+TEST_F(InputRouterImplTest, OverscrollDispatch) {
DidOverscrollParams overscroll;
overscroll.accumulated_overscroll = gfx::Vector2dF(-14, 14);
overscroll.latest_overscroll_delta = gfx::Vector2dF(-7, 0);
@@ -1838,9 +1687,7 @@ void InputRouterImplTest::OverscrollDispatch() {
wheel_overscroll.latest_overscroll_delta = gfx::Vector2dF(3, 0);
wheel_overscroll.current_fling_velocity = gfx::Vector2dF(1, 0);
- SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
- 0, 3, 0, 0, false,
- WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEvent(0, 0, 3, 0, 0, false, WebMouseWheelEvent::kPhaseBegan);
DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages();
ASSERT_EQ(1U, dispatched_messages.size());
ASSERT_TRUE(dispatched_messages[0]->ToEvent());
@@ -1862,16 +1709,6 @@ void InputRouterImplTest::OverscrollDispatch() {
EXPECT_EQ(gfx::Vector2dF(), client_overscroll.current_fling_velocity);
}
-TEST_F(InputRouterImplTest, OverscrollDispatch) {
- OverscrollDispatch();
-}
-TEST_F(InputRouterImplWheelScrollLatchingDisabledTest, OverscrollDispatch) {
- OverscrollDispatch();
-}
-TEST_F(InputRouterImplAsyncWheelEventEnabledTest, OverscrollDispatch) {
- OverscrollDispatch();
-}
-
// Test proper routing of whitelisted touch action notifications received from
// |SetWhiteListedTouchAction| IPC messages.
TEST_F(InputRouterImplTest, OnSetWhiteListedTouchAction) {
@@ -1934,8 +1771,10 @@ TEST_F(InputRouterImplTest, TouchActionInCallback) {
InputEventAckSource::COMPOSITOR_THREAD, ui::LatencyInfo(),
INPUT_EVENT_ACK_STATE_CONSUMED, base::nullopt, cc::kTouchActionNone);
ASSERT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(cc::TouchAction::kTouchActionNone,
- input_router_->AllowedTouchAction());
+ base::Optional<cc::TouchAction> allowed_touch_action =
+ input_router_->AllowedTouchAction();
+ DCHECK(allowed_touch_action.has_value());
+ EXPECT_EQ(cc::TouchAction::kTouchActionNone, allowed_touch_action.value());
}
namespace {
@@ -2005,8 +1844,7 @@ TEST_F(InputRouterImplScaleMouseEventTest, ScaleMouseEventTest) {
}
TEST_F(InputRouterImplScaleEventTest, ScaleMouseWheelEventTest) {
- SimulateWheelEventWithPhase(5, 5, 10, 10, 0, false,
- WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEvent(5, 5, 10, 10, 0, false, WebMouseWheelEvent::kPhaseBegan);
UpdateDispatchedMessages();
const WebMouseWheelEvent* sent_event =
@@ -2106,6 +1944,7 @@ class InputRouterImplScaleTouchEventTest
} // namespace
TEST_F(InputRouterImplScaleTouchEventTest, ScaleTouchEventTest) {
+ ResetTouchAction();
// Press
PressTouchPoint(10, 20);
PressTouchPoint(100, 200);
@@ -2251,6 +2090,7 @@ TEST_F(InputRouterImplScaleGestureEventTest, GestureScrollUpdate) {
}
TEST_F(InputRouterImplScaleGestureEventTest, GestureScrollBegin) {
+ PressAndSetTouchActionAuto();
SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildScrollBegin(
10.f, 20.f, blink::kWebGestureDeviceTouchscreen));
FlushGestureEvent(WebInputEvent::kGestureScrollBegin);
@@ -2267,8 +2107,8 @@ TEST_F(InputRouterImplScaleGestureEventTest, GestureScrollBegin) {
TEST_F(InputRouterImplScaleGestureEventTest, GesturePinchUpdate) {
const gfx::PointF orig(10, 20), scaled(20, 40);
- SimulateGesturePinchUpdateEvent(1.5f, orig.x(), orig.y(), 0,
- blink::kWebGestureDeviceTouchpad);
+ SimulateTouchpadGesturePinchEventWithoutWheel(
+ WebInputEvent::kGesturePinchUpdate, 1.5f, orig.x(), orig.y(), 0);
FlushGestureEvent(WebInputEvent::kGesturePinchUpdate);
const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
TestLocationInSentEvent(sent_event, orig, scaled);
diff --git a/chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc b/chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc
index e899b036cad..a7c0c6dca37 100644
--- a/chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc
@@ -39,8 +39,6 @@ const char kDataURL[] =
"<html>"
"<head>"
"<title>Mouse event trace events reported.</title>"
- "<script src=\"../../resources/testharness.js\"></script>"
- "<script src=\"../../resources/testharnessreport.js\"></script>"
"<script>"
" let i=0;"
" document.addEventListener('mousemove', () => {"
@@ -48,6 +46,12 @@ const char kDataURL[] =
" while(performance.now() < end);"
" document.body.style.backgroundColor = 'rgb(' + (i++) + ',0,0)'"
" });"
+ " document.addEventListener('wheel', (e) => {"
+ " if (!e.cancelable)"
+ " return;"
+ " var end = performance.now() + 50;"
+ " while(performance.now() < end);"
+ " });"
"</script>"
"<style>"
"body {"
@@ -79,11 +83,18 @@ class TracingRenderWidgetHost : public RenderWidgetHostImpl {
process,
routing_id,
std::move(widget),
- hidden) {}
- void OnGpuSwapBuffersCompletedInternal(
- const ui::LatencyInfo& latency_info) override {
- RenderWidgetHostImpl::OnGpuSwapBuffersCompletedInternal(latency_info);
- RunClosureIfNecessary(latency_info);
+ hidden) {
+ ui::LatencyTracker::SetLatencyInfoProcessorForTesting(base::BindRepeating(
+ &TracingRenderWidgetHost::HandleLatencyInfoAfterGpuSwap,
+ base::Unretained(this)));
+ }
+
+ void HandleLatencyInfoAfterGpuSwap(
+ const std::vector<ui::LatencyInfo>& latency_infos) {
+ for (const auto& latency_info : latency_infos) {
+ if (latency_info.terminated())
+ RunClosureIfNecessary(latency_info);
+ }
}
void OnMouseEventAck(const MouseEventWithLatencyInfo& event,
@@ -214,6 +225,24 @@ class MouseLatencyBrowserTest : public ContentBrowserTest {
runner_->Run();
}
+ // Generate mouse wheel scroll.
+ void DoSyncCoalescedMouseWheel(const gfx::PointF position,
+ const gfx::Vector2dF& delta) {
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
+ params.anchor = position;
+ params.distances.push_back(delta);
+
+ GetWidgetHost()->QueueSyntheticGesture(
+ SyntheticGesture::Create(params),
+ base::BindOnce(&MouseLatencyBrowserTest::OnSyntheticGestureCompleted,
+ base::Unretained(this)));
+
+ // Runs until we get the OnSyntheticGestureCompleted callback
+ runner_ = std::make_unique<base::RunLoop>();
+ runner_->Run();
+ }
+
void StartTracing() {
base::trace_event::TraceConfig trace_config(
"{"
@@ -245,6 +274,37 @@ class MouseLatencyBrowserTest : public ContentBrowserTest {
return trace_data_;
}
+ void AssertTraceIdsBeginAndEnd(const base::Value& trace_data,
+ const std::string& trace_event_name) {
+ const base::DictionaryValue* trace_data_dict;
+ ASSERT_TRUE(trace_data.GetAsDictionary(&trace_data_dict));
+
+ const base::ListValue* traceEvents;
+ ASSERT_TRUE(trace_data_dict->GetList("traceEvents", &traceEvents));
+
+ std::map<std::string, int> trace_ids;
+
+ for (size_t i = 0; i < traceEvents->GetSize(); ++i) {
+ const base::DictionaryValue* traceEvent;
+ ASSERT_TRUE(traceEvents->GetDictionary(i, &traceEvent));
+
+ std::string name;
+ ASSERT_TRUE(traceEvent->GetString("name", &name));
+
+ if (name != trace_event_name)
+ continue;
+
+ std::string id;
+ if (traceEvent->GetString("id", &id))
+ ++trace_ids[id];
+ }
+
+ for (auto i : trace_ids) {
+ // Each trace id should show up once for the begin, and once for the end.
+ EXPECT_EQ(2, i.second);
+ }
+ }
+
private:
base::MessageLoop loop_;
std::unique_ptr<base::RunLoop> runner_;
@@ -311,16 +371,10 @@ IN_PROC_BROWSER_TEST_F(MouseLatencyBrowserTest,
// events in the case where events are coalesced. (crbug.com/771165).
// Disabled on Android because we don't support synthetic mouse input on Android
// (crbug.com/723618).
-// http://crbug.com/801629 : Flaky on Linux and Windows
-#if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_LINUX)
-#define MAYBE_CoalescedMouseMovesCorrectlyTerminated \
- DISABLED_CoalescedMouseMovesCorrectlyTerminated
-#else
-#define MAYBE_CoalescedMouseMovesCorrectlyTerminated \
- CoalescedMouseMovesCorrectlyTerminated
-#endif
+// http://crbug.com/801629 : Flaky on Linux and Windows, and Mac with
+// --enable-features=VizDisplayCompositor
IN_PROC_BROWSER_TEST_F(MouseLatencyBrowserTest,
- MAYBE_CoalescedMouseMovesCorrectlyTerminated) {
+ DISABLED_CoalescedMouseMovesCorrectlyTerminated) {
LoadURL();
StartTracing();
@@ -331,34 +385,18 @@ IN_PROC_BROWSER_TEST_F(MouseLatencyBrowserTest,
->WaitFor("InputLatency::MouseUp");
const base::Value& trace_data = StopTracing();
- const base::DictionaryValue* trace_data_dict;
- trace_data.GetAsDictionary(&trace_data_dict);
- ASSERT_TRUE(trace_data.GetAsDictionary(&trace_data_dict));
-
- const base::ListValue* traceEvents;
- ASSERT_TRUE(trace_data_dict->GetList("traceEvents", &traceEvents));
-
- std::map<std::string, int> trace_ids;
-
- for (size_t i = 0; i < traceEvents->GetSize(); ++i) {
- const base::DictionaryValue* traceEvent;
- ASSERT_TRUE(traceEvents->GetDictionary(i, &traceEvent));
-
- std::string name;
- ASSERT_TRUE(traceEvent->GetString("name", &name));
+ AssertTraceIdsBeginAndEnd(trace_data, "InputLatency::MouseMove");
+}
- if (name != "InputLatency::MouseMove")
- continue;
+IN_PROC_BROWSER_TEST_F(MouseLatencyBrowserTest,
+ CoalescedMouseWheelsCorrectlyTerminated) {
+ LoadURL();
- std::string id;
- if (traceEvent->GetString("id", &id))
- ++trace_ids[id];
- }
+ StartTracing();
+ DoSyncCoalescedMouseWheel(gfx::PointF(100, 100), gfx::Vector2dF(0, -100));
+ const base::Value& trace_data = StopTracing();
- for (auto i : trace_ids) {
- // Each trace id should show up once for the begin, and once for the end.
- EXPECT_EQ(2, i.second);
- }
+ AssertTraceIdsBeginAndEnd(trace_data, "InputLatency::MouseWheel");
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
index c3f4641e852..702915772e4 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
@@ -35,15 +35,8 @@ class QueuedWebMouseWheelEvent : public MouseWheelEventWithLatencyInfo {
DISALLOW_COPY_AND_ASSIGN(QueuedWebMouseWheelEvent);
};
-MouseWheelEventQueue::MouseWheelEventQueue(MouseWheelEventQueueClient* client,
- bool enable_scroll_latching)
+MouseWheelEventQueue::MouseWheelEventQueue(MouseWheelEventQueueClient* client)
: client_(client),
- needs_scroll_begin_when_scroll_latching_disabled_(true),
- needs_scroll_end_when_scroll_latching_disabled_(false),
- enable_scroll_latching_(enable_scroll_latching),
- enable_async_wheel_events_(
- base::FeatureList::IsEnabled(features::kAsyncWheelEvents) &&
- enable_scroll_latching),
send_wheel_events_async_(false),
scrolling_device_(blink::kWebGestureDeviceUninitialized) {
DCHECK(client);
@@ -59,6 +52,9 @@ void MouseWheelEventQueue::QueueEvent(
if (event_sent_for_gesture_ack_ && !wheel_queue_.empty()) {
QueuedWebMouseWheelEvent* last_event = wheel_queue_.back().get();
if (last_event->CanCoalesceWith(event)) {
+ // Terminate the LatencyInfo of the event before it gets coalesced away.
+ event.latency.Terminate();
+
last_event->CoalesceWith(event);
TRACE_EVENT_INSTANT2("input", "MouseWheelEventQueue::CoalescedWheelEvent",
TRACE_EVENT_SCOPE_THREAD, "total_dx",
@@ -144,8 +140,7 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
scroll_update.data.scroll_update.delta_y =
event_sent_for_gesture_ack_->event.delta_y;
}
- // Only OSX populates the phase and momentumPhase; so
- // |inertialPhase| will be UnknownMomentumPhase on all other platforms.
+
if (event_sent_for_gesture_ack_->event.momentum_phase !=
blink::WebMouseWheelEvent::kPhaseNone) {
scroll_update.data.scroll_update.inertial_phase =
@@ -209,77 +204,29 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
if (needs_update)
RecordLatchingUmaMetric(client_->IsWheelScrollInProgress());
- if (enable_scroll_latching_) {
- bool synthetic = event_sent_for_gesture_ack_->event.has_synthetic_phase;
- if (event_sent_for_gesture_ack_->event.phase ==
- blink::WebMouseWheelEvent::kPhaseBegan) {
- // Wheel event with phaseBegan must have non-zero deltas.
- DCHECK(needs_update);
- send_wheel_events_async_ = true;
-
- if (!client_->IsWheelScrollInProgress())
- SendScrollBegin(scroll_update, synthetic);
- }
-
- if (needs_update) {
- // It is possible that the wheel event with phaseBegan is consumed and
- // no GSB is sent.
- if (!client_->IsWheelScrollInProgress())
- SendScrollBegin(scroll_update, synthetic);
- ui::LatencyInfo latency = ui::LatencyInfo(ui::SourceEventType::WHEEL);
- latency.AddLatencyNumber(
- ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0);
- client_->ForwardGestureEventWithLatencyInfo(scroll_update, latency);
- }
-
- if (current_phase_ended && client_->IsWheelScrollInProgress()) {
- // Send GSE when scroll latching is enabled, GSB is sent, and no fling
- // is going to happen next.
- SendScrollEnd(scroll_update, synthetic);
- }
- } else { // !enable_scroll_latching_
-
- // 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_when_scroll_latching_disabled_ &&
- current_phase_ended &&
- !event_sent_for_gesture_ack_->event.has_synthetic_phase;
- if (needs_update || !empty_sequence) {
- if (needs_scroll_begin_when_scroll_latching_disabled_) {
- // 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(ui::SourceEventType::WHEEL);
- latency.AddLatencyNumber(
- ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL,
- 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 if (!has_phase_info) {
- SendScrollEnd(scroll_update, false);
- }
- }
+ bool synthetic = event_sent_for_gesture_ack_->event.has_synthetic_phase;
+ if (event_sent_for_gesture_ack_->event.phase ==
+ blink::WebMouseWheelEvent::kPhaseBegan) {
+ // Wheel event with phaseBegan must have non-zero deltas.
+ DCHECK(needs_update);
+ send_wheel_events_async_ = true;
+
+ if (!client_->IsWheelScrollInProgress())
+ SendScrollBegin(scroll_update, synthetic);
+ }
+
+ if (needs_update) {
+ // It is possible that the wheel event with phaseBegan is consumed and
+ // no GSB is sent.
+ if (!client_->IsWheelScrollInProgress())
+ SendScrollBegin(scroll_update, synthetic);
+ client_->ForwardGestureEventWithLatencyInfo(
+ scroll_update, ui::LatencyInfo(ui::SourceEventType::WHEEL));
+ }
+
+ if (current_phase_ended && client_->IsWheelScrollInProgress()) {
+ // Send GSE when GSB is sent and no fling is going to happen next.
+ SendScrollEnd(scroll_update, synthetic);
}
}
@@ -312,18 +259,16 @@ void MouseWheelEventQueue::TryForwardNextEventToRenderer() {
event_sent_for_gesture_ack_ = std::move(wheel_queue_.front());
wheel_queue_.pop_front();
- if (enable_async_wheel_events_) {
- DCHECK(event_sent_for_gesture_ack_->event.phase !=
- blink::WebMouseWheelEvent::kPhaseNone ||
- event_sent_for_gesture_ack_->event.momentum_phase !=
- blink::WebMouseWheelEvent::kPhaseNone);
- if (event_sent_for_gesture_ack_->event.phase ==
- blink::WebMouseWheelEvent::kPhaseBegan) {
- send_wheel_events_async_ = false;
- } else if (send_wheel_events_async_) {
- event_sent_for_gesture_ack_->event.dispatch_type =
- WebInputEvent::kEventNonBlocking;
- }
+ DCHECK(event_sent_for_gesture_ack_->event.phase !=
+ blink::WebMouseWheelEvent::kPhaseNone ||
+ event_sent_for_gesture_ack_->event.momentum_phase !=
+ blink::WebMouseWheelEvent::kPhaseNone);
+ if (event_sent_for_gesture_ack_->event.phase ==
+ blink::WebMouseWheelEvent::kPhaseBegan) {
+ send_wheel_events_async_ = false;
+ } else if (send_wheel_events_async_) {
+ event_sent_for_gesture_ack_->event.dispatch_type =
+ WebInputEvent::kEventNonBlocking;
}
client_->SendMouseWheelEventImmediately(*event_sent_for_gesture_ack_);
@@ -331,10 +276,6 @@ void MouseWheelEventQueue::TryForwardNextEventToRenderer() {
void MouseWheelEventQueue::SendScrollEnd(WebGestureEvent update_event,
bool synthetic) {
- DCHECK(enable_scroll_latching_ ||
- (synthetic && !needs_scroll_end_when_scroll_latching_disabled_) ||
- needs_scroll_end_when_scroll_latching_disabled_);
-
DCHECK(client_->IsWheelScrollInProgress());
WebGestureEvent scroll_end(update_event);
@@ -347,10 +288,6 @@ void MouseWheelEventQueue::SendScrollEnd(WebGestureEvent update_event,
scroll_end.data.scroll_end.delta_units =
update_event.data.scroll_update.delta_units;
- if (!synthetic) {
- needs_scroll_begin_when_scroll_latching_disabled_ = true;
- needs_scroll_end_when_scroll_latching_disabled_ = false;
- }
client_->ForwardGestureEventWithLatencyInfo(
scroll_end, ui::LatencyInfo(ui::SourceEventType::WHEEL));
}
@@ -358,10 +295,6 @@ void MouseWheelEventQueue::SendScrollEnd(WebGestureEvent update_event,
void MouseWheelEventQueue::SendScrollBegin(
const WebGestureEvent& gesture_update,
bool synthetic) {
- DCHECK(enable_scroll_latching_ ||
- (synthetic && !needs_scroll_begin_when_scroll_latching_disabled_) ||
- needs_scroll_begin_when_scroll_latching_disabled_);
-
DCHECK(!client_->IsWheelScrollInProgress());
WebGestureEvent scroll_begin(gesture_update);
@@ -377,8 +310,6 @@ void MouseWheelEventQueue::SendScrollBegin(
scroll_begin.data.scroll_begin.delta_hint_units =
gesture_update.data.scroll_update.delta_units;
- needs_scroll_begin_when_scroll_latching_disabled_ = false;
- needs_scroll_end_when_scroll_latching_disabled_ = true;
client_->ForwardGestureEventWithLatencyInfo(
scroll_begin, ui::LatencyInfo(ui::SourceEventType::WHEEL));
}
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h
index b7042a7f493..20730400dce 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h
@@ -39,13 +39,10 @@ class CONTENT_EXPORT MouseWheelEventQueueClient {
// 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 enable_scroll_latching);
+ // The |client| must outlive the MouseWheelEventQueue.
+ // |IsWheelScrollInProgress| indicates whether mouse wheel events should
+ // generate Scroll[Begin|Update|End] on unhandled acknowledge events.
+ MouseWheelEventQueue(MouseWheelEventQueueClient* client);
~MouseWheelEventQueue();
@@ -92,21 +89,6 @@ class CONTENT_EXPORT MouseWheelEventQueue {
base::circular_deque<std::unique_ptr<QueuedWebMouseWheelEvent>> wheel_queue_;
std::unique_ptr<QueuedWebMouseWheelEvent> event_sent_for_gesture_ack_;
- // True if a non-synthetic GSB needs to be sent before a GSU is sent.
- // This variable is used only when scroll latching is disabled.
- bool needs_scroll_begin_when_scroll_latching_disabled_;
-
- // True if a non-synthetic GSE needs to be sent because a non-synthetic
- // GSB has been sent in the past.
- // This variable is used only when scroll latching is disabled.
- bool needs_scroll_end_when_scroll_latching_disabled_;
-
- // True if the touchpad and wheel scroll latching flag is enabled.
- bool enable_scroll_latching_;
-
- // True if the async wheel events flag is enabled.
- bool enable_async_wheel_events_;
-
// True if the ack for the first wheel event in a scroll sequence is not
// consumed. This lets us to send the rest of the wheel events in the sequence
// as non-blocking.
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc
index 62bfefc9972..b8f0067c4a8 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc
@@ -12,13 +12,11 @@
#include "base/location.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/test/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/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 "content/public/common/content_features.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/events/base_event_utils.h"
@@ -137,43 +135,17 @@ const float kWheelScrollGlobalY = 72;
#define EXPECT_MOUSE_WHEEL(event) \
EXPECT_EQ(WebInputEvent::kMouseWheel, event->GetType());
-enum WheelScrollingMode {
- kWheelScrollingModeNone,
- kWheelScrollLatching,
- kAsyncWheelEvents,
-};
-
} // namespace
-class MouseWheelEventQueueTest
- : public testing::TestWithParam<WheelScrollingMode>,
- public MouseWheelEventQueueClient {
+class MouseWheelEventQueueTest : public testing::Test,
+ public MouseWheelEventQueueClient {
public:
MouseWheelEventQueueTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI),
acked_event_count_(0),
last_acked_event_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {
- scroll_latching_enabled_ = GetParam() != kWheelScrollingModeNone;
- switch (GetParam()) {
- case kWheelScrollingModeNone:
- feature_list_.InitWithFeatures(
- {}, {features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents});
- break;
- case kWheelScrollLatching:
- feature_list_.InitWithFeatures(
- {features::kTouchpadAndWheelScrollLatching},
- {features::kAsyncWheelEvents});
- break;
- case kAsyncWheelEvents:
- feature_list_.InitWithFeatures(
- {features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents},
- {});
- }
-
- queue_.reset(new MouseWheelEventQueue(this, scroll_latching_enabled_));
+ queue_.reset(new MouseWheelEventQueue(this));
}
~MouseWheelEventQueueTest() override {}
@@ -213,8 +185,6 @@ class MouseWheelEventQueueTest
return is_wheel_scroll_in_progress_;
}
- bool scroll_latching_enabled() { return scroll_latching_enabled_; }
-
protected:
size_t queued_event_count() const { return queue_->queued_size(); }
@@ -249,34 +219,7 @@ class MouseWheelEventQueueTest
queue_->ProcessMouseWheelAck(InputEventAckSource::COMPOSITOR_THREAD,
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.rails_mode = 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::kRailsModeFree);
- }
- void SendMouseWheelWithPhase(float x,
float y,
float global_x,
float global_y,
@@ -294,60 +237,18 @@ class MouseWheelEventQueueTest
event.rails_mode = rails_mode;
queue_->QueueEvent(MouseWheelEventWithLatencyInfo(event));
}
- 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) {
- SendMouseWheelWithPhase(x, y, global_x, global_y, dX, dY, modifiers,
- high_precision, phase, momentum_phase,
- WebInputEvent::kRailsModeFree);
- }
-
- void SendMouseWheelPossiblyIncludingPhase(
- bool ignore_phase,
- 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,
- WebInputEvent::RailsMode rails_mode) {
- if (ignore_phase) {
- SendMouseWheel(x, y, global_x, global_y, dX, dY, modifiers,
- high_precision, rails_mode);
- } else {
- SendMouseWheelWithPhase(x, y, global_x, global_y, dX, dY, modifiers,
- high_precision, phase, momentum_phase,
- rails_mode);
- }
- }
-
- void SendMouseWheelPossiblyIncludingPhase(
- bool ignore_phase,
- 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) {
- SendMouseWheelPossiblyIncludingPhase(
- ignore_phase, x, y, global_x, global_y, dX, dY, modifiers,
- high_precision, phase, momentum_phase, WebInputEvent::kRailsModeFree);
+ void SendMouseWheel(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) {
+ SendMouseWheel(x, y, global_x, global_y, dX, dY, modifiers, high_precision,
+ phase, momentum_phase, WebInputEvent::kRailsModeFree);
}
void SendGestureEvent(WebInputEvent::Type type) {
@@ -369,20 +270,20 @@ class MouseWheelEventQueueTest
const WebGestureEvent::ScrollUnits scroll_units =
high_precision ? WebGestureEvent::kPrecisePixels
: WebGestureEvent::kPixels;
- SendMouseWheelPossiblyIncludingPhase(
- !scroll_latching_enabled_, kWheelScrollX, kWheelScrollY,
- kWheelScrollGlobalX, kWheelScrollGlobalY, 1, 1, 0, high_precision,
- WebMouseWheelEvent::kPhaseBegan, WebMouseWheelEvent::kPhaseNone);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, high_precision,
+ WebMouseWheelEvent::kPhaseBegan,
+ WebMouseWheelEvent::kPhaseNone);
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.
- SendMouseWheelPossiblyIncludingPhase(
- !scroll_latching_enabled_, kWheelScrollX, kWheelScrollY,
- kWheelScrollGlobalX, kWheelScrollGlobalY, 5, 5, 0, high_precision,
- WebMouseWheelEvent::kPhaseChanged, WebMouseWheelEvent::kPhaseNone);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 5, 5, 0, high_precision,
+ WebMouseWheelEvent::kPhaseChanged,
+ WebMouseWheelEvent::kPhaseNone);
EXPECT_EQ(1U, queued_event_count());
EXPECT_TRUE(event_in_flight());
EXPECT_EQ(0U, GetAndResetSentEventCount());
@@ -394,20 +295,11 @@ class MouseWheelEventQueueTest
EXPECT_TRUE(event_in_flight());
EXPECT_EQ(WebInputEvent::kMouseWheel, acked_event().GetType());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
- if (scroll_latching_enabled_) {
- EXPECT_EQ(3U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
- EXPECT_MOUSE_WHEEL(sent_input_event(2));
- EXPECT_EQ(3U, GetAndResetSentEventCount());
- } else {
- EXPECT_EQ(4U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
- EXPECT_GESTURE_SCROLL_END(sent_gesture_event(2));
- EXPECT_MOUSE_WHEEL(sent_input_event(3));
- EXPECT_EQ(4U, GetAndResetSentEventCount());
- }
+ EXPECT_EQ(3U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
+ EXPECT_MOUSE_WHEEL(sent_input_event(2));
+ EXPECT_EQ(3U, GetAndResetSentEventCount());
}
void PhaseGestureSendingTest(bool high_precision) {
@@ -415,124 +307,59 @@ class MouseWheelEventQueueTest
high_precision ? WebGestureEvent::kPrecisePixels
: WebGestureEvent::kPixels;
- SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
- kWheelScrollGlobalY, 1, 1, 0, high_precision,
- WebMouseWheelEvent::kPhaseBegan,
- WebMouseWheelEvent::kPhaseNone);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, high_precision,
+ WebMouseWheelEvent::kPhaseBegan,
+ WebMouseWheelEvent::kPhaseNone);
EXPECT_EQ(1U, GetAndResetSentEventCount());
SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- if (scroll_latching_enabled_) {
- EXPECT_EQ(2U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
- EXPECT_EQ(2U, GetAndResetSentEventCount());
- } else {
- EXPECT_EQ(3U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
- EXPECT_SYNTHETIC_GESTURE_SCROLL_END(sent_gesture_event(2));
- EXPECT_EQ(3U, GetAndResetSentEventCount());
- }
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
- SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
- kWheelScrollGlobalY, 5, 5, 0, high_precision,
- WebMouseWheelEvent::kPhaseChanged,
- WebMouseWheelEvent::kPhaseNone);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 5, 5, 0, high_precision,
+ WebMouseWheelEvent::kPhaseChanged,
+ WebMouseWheelEvent::kPhaseNone);
EXPECT_EQ(1U, GetAndResetSentEventCount());
SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- if (scroll_latching_enabled_) {
- EXPECT_EQ(1U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(0));
- EXPECT_EQ(1U, GetAndResetSentEventCount());
- } else {
- EXPECT_EQ(3U, all_sent_events().size());
- EXPECT_SYNTHETIC_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
- EXPECT_SYNTHETIC_GESTURE_SCROLL_END(sent_gesture_event(2));
- EXPECT_EQ(3U, GetAndResetSentEventCount());
- }
-
- // When wheel scroll latching is enabled no wheel event with phase =
- // |kPhaseEnded| will be sent before a wheel event with momentum_phase =
- // |kPhaseBegan|.
- if (!scroll_latching_enabled_) {
- SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
- kWheelScrollGlobalY, 0, 0, 0, high_precision,
- WebMouseWheelEvent::kPhaseEnded,
- WebMouseWheelEvent::kPhaseNone);
- 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_WITH_PHASE(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::kPhaseEnded,
- WebMouseWheelEvent::kPhaseNone);
- EXPECT_EQ(1U, GetAndResetSentEventCount());
- SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, all_sent_events().size());
- EXPECT_EQ(0U, GetAndResetSentEventCount());
- }
+ EXPECT_EQ(1U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(0));
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
- SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
- kWheelScrollGlobalY, 5, 5, 0, high_precision,
- WebMouseWheelEvent::kPhaseNone,
- WebMouseWheelEvent::kPhaseBegan);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 5, 5, 0, high_precision,
+ WebMouseWheelEvent::kPhaseNone,
+ WebMouseWheelEvent::kPhaseBegan);
EXPECT_EQ(1U, GetAndResetSentEventCount());
SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- if (scroll_latching_enabled_) {
- // A fling has started, no ScrollEnd/ScrollBegin is sent.
- EXPECT_EQ(1U, all_sent_events().size());
- EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(sent_gesture_event(0));
- EXPECT_EQ(1U, GetAndResetSentEventCount());
- } else {
- 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());
- }
+ // A fling has started, no ScrollEnd/ScrollBegin is sent.
+ EXPECT_EQ(1U, all_sent_events().size());
+ EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(sent_gesture_event(0));
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
- SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
- kWheelScrollGlobalY, 5, 5, 0, high_precision,
- WebMouseWheelEvent::kPhaseNone,
- WebMouseWheelEvent::kPhaseChanged);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 5, 5, 0, high_precision,
+ WebMouseWheelEvent::kPhaseNone,
+ WebMouseWheelEvent::kPhaseChanged);
EXPECT_EQ(1U, GetAndResetSentEventCount());
SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- if (scroll_latching_enabled_) {
- EXPECT_EQ(1U, all_sent_events().size());
- EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(sent_gesture_event(0));
- EXPECT_EQ(1U, GetAndResetSentEventCount());
- } else {
- 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());
- }
+ EXPECT_EQ(1U, all_sent_events().size());
+ EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(sent_gesture_event(0));
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
- SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
- kWheelScrollGlobalY, 0, 0, 0, high_precision,
- WebMouseWheelEvent::kPhaseNone,
- WebMouseWheelEvent::kPhaseEnded);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 0, 0, 0, high_precision,
+ WebMouseWheelEvent::kPhaseNone,
+ WebMouseWheelEvent::kPhaseEnded);
EXPECT_EQ(1U, GetAndResetSentEventCount());
SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- if (scroll_latching_enabled_) {
- // MomentumPhase is ended, the scroll is done, and GSE is sent
- // immediately.
- EXPECT_EQ(1U, all_sent_events().size());
- EXPECT_INERTIAL_GESTURE_SCROLL_END(sent_gesture_event(0));
- EXPECT_EQ(1U, GetAndResetSentEventCount());
- } else {
- 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());
- }
+ // MomentumPhase is ended, the scroll is done, and GSE is sent
+ // immediately.
+ EXPECT_EQ(1U, all_sent_events().size());
+ EXPECT_INERTIAL_GESTURE_SCROLL_END(sent_gesture_event(0));
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
}
base::test::ScopedTaskEnvironment scoped_task_environment_;
@@ -541,28 +368,26 @@ class MouseWheelEventQueueTest
size_t acked_event_count_;
InputEventAckState last_acked_event_state_;
WebMouseWheelEvent last_acked_event_;
- bool scroll_latching_enabled_;
private:
bool is_wheel_scroll_in_progress_ = false;
- base::test::ScopedFeatureList feature_list_;
};
// Tests that mouse wheel events are queued properly.
-TEST_P(MouseWheelEventQueueTest, Basic) {
- SendMouseWheelPossiblyIncludingPhase(
- !scroll_latching_enabled_, kWheelScrollX, kWheelScrollY,
- kWheelScrollGlobalX, kWheelScrollGlobalY, 1, 1, 0, false,
- WebMouseWheelEvent::kPhaseBegan, WebMouseWheelEvent::kPhaseNone);
+TEST_F(MouseWheelEventQueueTest, Basic) {
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false,
+ WebMouseWheelEvent::kPhaseBegan,
+ WebMouseWheelEvent::kPhaseNone);
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.
- SendMouseWheelPossiblyIncludingPhase(
- !scroll_latching_enabled_, kWheelScrollX, kWheelScrollY,
- kWheelScrollGlobalX, kWheelScrollGlobalY, 5, 5, 0, false,
- WebMouseWheelEvent::kPhaseChanged, WebMouseWheelEvent::kPhaseNone);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 5, 5, 0, false,
+ WebMouseWheelEvent::kPhaseChanged,
+ WebMouseWheelEvent::kPhaseNone);
EXPECT_EQ(1U, queued_event_count());
EXPECT_TRUE(event_in_flight());
EXPECT_EQ(0U, GetAndResetSentEventCount());
@@ -584,29 +409,29 @@ TEST_P(MouseWheelEventQueueTest, Basic) {
EXPECT_EQ(WebInputEvent::kMouseWheel, acked_event().GetType());
}
-TEST_P(MouseWheelEventQueueTest, GestureSending) {
+TEST_F(MouseWheelEventQueueTest, GestureSending) {
GestureSendingTest(false);
}
-TEST_P(MouseWheelEventQueueTest, GestureSendingPrecisePixels) {
+TEST_F(MouseWheelEventQueueTest, GestureSendingPrecisePixels) {
GestureSendingTest(true);
}
-TEST_P(MouseWheelEventQueueTest, GestureSendingWithPhaseInformation) {
+TEST_F(MouseWheelEventQueueTest, GestureSendingWithPhaseInformation) {
PhaseGestureSendingTest(false);
}
-TEST_P(MouseWheelEventQueueTest,
+TEST_F(MouseWheelEventQueueTest,
GestureSendingWithPhaseInformationPrecisePixels) {
PhaseGestureSendingTest(true);
}
-TEST_P(MouseWheelEventQueueTest, GestureSendingInterrupted) {
+TEST_F(MouseWheelEventQueueTest, GestureSendingInterrupted) {
const WebGestureEvent::ScrollUnits scroll_units = WebGestureEvent::kPixels;
- SendMouseWheelPossiblyIncludingPhase(
- !scroll_latching_enabled_, kWheelScrollX, kWheelScrollY,
- kWheelScrollGlobalX, kWheelScrollGlobalY, 1, 1, 0, false,
- WebMouseWheelEvent::kPhaseBegan, WebMouseWheelEvent::kPhaseNone);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false,
+ WebMouseWheelEvent::kPhaseBegan,
+ WebMouseWheelEvent::kPhaseNone);
EXPECT_EQ(0U, queued_event_count());
EXPECT_TRUE(event_in_flight());
EXPECT_EQ(1U, GetAndResetSentEventCount());
@@ -617,46 +442,32 @@ TEST_P(MouseWheelEventQueueTest, GestureSendingInterrupted) {
EXPECT_FALSE(event_in_flight());
EXPECT_EQ(WebInputEvent::kMouseWheel, acked_event().GetType());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
- if (scroll_latching_enabled_) {
- EXPECT_EQ(2U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
- EXPECT_EQ(2U, GetAndResetSentEventCount());
- } else {
- EXPECT_EQ(3U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
- EXPECT_GESTURE_SCROLL_END(sent_gesture_event(2));
- EXPECT_EQ(3U, GetAndResetSentEventCount());
- }
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
- // When wheel scroll latching is enabled and a touch based GSB arrives in the
+ // When a touch based GSB arrives in the
// middle of wheel scrolling sequence, a synthetic wheel event with zero
// deltas and phase = |kPhaseEnded| will be sent.
- if (scroll_latching_enabled_) {
- SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
- kWheelScrollGlobalY, 0, 0, 0, false,
- WebMouseWheelEvent::kPhaseEnded,
- WebMouseWheelEvent::kPhaseNone);
- SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(1U, GetAndResetAckedEventCount());
- }
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 0, 0, 0, false,
+ WebMouseWheelEvent::kPhaseEnded,
+ WebMouseWheelEvent::kPhaseNone);
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
// Ensure that a gesture scroll begin terminates the current scroll event.
SendGestureEvent(WebInputEvent::kGestureScrollBegin);
- if (scroll_latching_enabled_) {
- EXPECT_EQ(2U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_END_WITH_PHASE(sent_gesture_event(1));
- EXPECT_EQ(2U, GetAndResetSentEventCount());
- } else {
- // ScrollEnd has already been sent.
- EXPECT_EQ(0U, all_sent_events().size());
- }
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_END_WITH_PHASE(sent_gesture_event(1));
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
- SendMouseWheelPossiblyIncludingPhase(
- !scroll_latching_enabled_, kWheelScrollX, kWheelScrollY,
- kWheelScrollGlobalX, kWheelScrollGlobalY, 1, 1, 0, false,
- WebMouseWheelEvent::kPhaseBegan, WebMouseWheelEvent::kPhaseNone);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false,
+ WebMouseWheelEvent::kPhaseBegan,
+ WebMouseWheelEvent::kPhaseNone);
EXPECT_EQ(0U, queued_event_count());
EXPECT_TRUE(event_in_flight());
@@ -674,10 +485,10 @@ TEST_P(MouseWheelEventQueueTest, GestureSendingInterrupted) {
SendGestureEvent(WebInputEvent::kGestureScrollEnd);
EXPECT_EQ(0U, all_sent_events().size());
- SendMouseWheelPossiblyIncludingPhase(
- !scroll_latching_enabled_, kWheelScrollX, kWheelScrollY,
- kWheelScrollGlobalX, kWheelScrollGlobalY, 1, 1, 0, false,
- WebMouseWheelEvent::kPhaseBegan, WebMouseWheelEvent::kPhaseNone);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false,
+ WebMouseWheelEvent::kPhaseBegan,
+ WebMouseWheelEvent::kPhaseNone);
EXPECT_EQ(0U, queued_event_count());
EXPECT_TRUE(event_in_flight());
@@ -689,28 +500,18 @@ TEST_P(MouseWheelEventQueueTest, GestureSendingInterrupted) {
EXPECT_FALSE(event_in_flight());
EXPECT_EQ(WebInputEvent::kMouseWheel, acked_event().GetType());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
- if (scroll_latching_enabled_) {
- EXPECT_EQ(2U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
- EXPECT_EQ(2U, GetAndResetSentEventCount());
- } else {
- EXPECT_EQ(3U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
- EXPECT_GESTURE_SCROLL_END(sent_gesture_event(2));
- EXPECT_EQ(3U, GetAndResetSentEventCount());
- }
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
}
-TEST_P(MouseWheelEventQueueTest, GestureRailScrolling) {
+TEST_F(MouseWheelEventQueueTest, GestureRailScrolling) {
const WebGestureEvent::ScrollUnits scroll_units = WebGestureEvent::kPixels;
-
- SendMouseWheelPossiblyIncludingPhase(
- !scroll_latching_enabled_, kWheelScrollX, kWheelScrollY,
- kWheelScrollGlobalX, kWheelScrollGlobalY, 1, 1, 0, false,
- WebMouseWheelEvent::kPhaseBegan, WebMouseWheelEvent::kPhaseNone,
- WebInputEvent::kRailsModeHorizontal);
+ SendMouseWheel(
+ kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX, kWheelScrollGlobalY, 1,
+ 1, 0, false, WebMouseWheelEvent::kPhaseBegan,
+ WebMouseWheelEvent::kPhaseNone, WebInputEvent::kRailsModeHorizontal);
EXPECT_EQ(0U, queued_event_count());
EXPECT_TRUE(event_in_flight());
EXPECT_EQ(1U, GetAndResetSentEventCount());
@@ -721,27 +522,17 @@ TEST_P(MouseWheelEventQueueTest, GestureRailScrolling) {
EXPECT_FALSE(event_in_flight());
EXPECT_EQ(WebInputEvent::kMouseWheel, acked_event().GetType());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
- if (scroll_latching_enabled_) {
- EXPECT_EQ(2U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
- EXPECT_EQ(1U, sent_gesture_event(1)->data.scroll_update.delta_x);
- EXPECT_EQ(0U, sent_gesture_event(1)->data.scroll_update.delta_y);
- EXPECT_EQ(2U, GetAndResetSentEventCount());
- } else {
- EXPECT_EQ(3U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
- EXPECT_GESTURE_SCROLL_END(sent_gesture_event(2));
- EXPECT_EQ(1U, sent_gesture_event(1)->data.scroll_update.delta_x);
- EXPECT_EQ(0U, sent_gesture_event(1)->data.scroll_update.delta_y);
- EXPECT_EQ(3U, GetAndResetSentEventCount());
- }
- SendMouseWheelPossiblyIncludingPhase(
- !scroll_latching_enabled_, kWheelScrollX, kWheelScrollY,
- kWheelScrollGlobalX, kWheelScrollGlobalY, 1, 1, 0, false,
- WebMouseWheelEvent::kPhaseChanged, WebMouseWheelEvent::kPhaseNone,
- WebInputEvent::kRailsModeVertical);
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
+ EXPECT_EQ(1U, sent_gesture_event(1)->data.scroll_update.delta_x);
+ EXPECT_EQ(0U, sent_gesture_event(1)->data.scroll_update.delta_y);
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
+
+ SendMouseWheel(
+ kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX, kWheelScrollGlobalY, 1,
+ 1, 0, false, WebMouseWheelEvent::kPhaseChanged,
+ WebMouseWheelEvent::kPhaseNone, WebInputEvent::kRailsModeVertical);
EXPECT_EQ(0U, queued_event_count());
EXPECT_TRUE(event_in_flight());
@@ -754,32 +545,19 @@ TEST_P(MouseWheelEventQueueTest, GestureRailScrolling) {
EXPECT_EQ(WebInputEvent::kMouseWheel, acked_event().GetType());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
size_t scroll_update_index = 0;
- if (scroll_latching_enabled_) {
- EXPECT_EQ(1U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(0));
- } else {
- EXPECT_EQ(3U, all_sent_events().size());
- EXPECT_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
- EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
- EXPECT_GESTURE_SCROLL_END(sent_gesture_event(2));
- scroll_update_index = 1;
- }
+ EXPECT_EQ(1U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(0));
+
EXPECT_EQ(
0U, sent_gesture_event(scroll_update_index)->data.scroll_update.delta_x);
EXPECT_EQ(
1U, sent_gesture_event(scroll_update_index)->data.scroll_update.delta_y);
- if (scroll_latching_enabled_)
EXPECT_EQ(1U, GetAndResetSentEventCount());
- else
- EXPECT_EQ(3U, GetAndResetSentEventCount());
}
-TEST_P(MouseWheelEventQueueTest, WheelScrollLatching) {
- if (!scroll_latching_enabled_)
- return;
-
+TEST_F(MouseWheelEventQueueTest, WheelScrollLatching) {
const WebGestureEvent::ScrollUnits scroll_units = WebGestureEvent::kPixels;
- SendMouseWheelWithPhase(
+ SendMouseWheel(
kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX, kWheelScrollGlobalY, 1,
1, 0, false, WebMouseWheelEvent::kPhaseBegan,
WebMouseWheelEvent::kPhaseNone, WebInputEvent::kRailsModeVertical);
@@ -800,7 +578,7 @@ TEST_P(MouseWheelEventQueueTest, WheelScrollLatching) {
EXPECT_EQ(1U, sent_gesture_event(1)->data.scroll_update.delta_y);
EXPECT_EQ(2U, GetAndResetSentEventCount());
- SendMouseWheelWithPhase(
+ SendMouseWheel(
kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX, kWheelScrollGlobalY, 1,
1, 0, false, WebMouseWheelEvent::kPhaseChanged,
WebMouseWheelEvent::kPhaseNone, WebInputEvent::kRailsModeVertical);
@@ -823,34 +601,24 @@ TEST_P(MouseWheelEventQueueTest, WheelScrollLatching) {
EXPECT_EQ(1U, GetAndResetSentEventCount());
}
-TEST_P(MouseWheelEventQueueTest, WheelScrollingWasLatchedHistogramCheck) {
+TEST_F(MouseWheelEventQueueTest, WheelScrollingWasLatchedHistogramCheck) {
base::HistogramTester histogram_tester;
const char latching_histogram_name[] = "WheelScrolling.WasLatched";
- SendMouseWheelPossiblyIncludingPhase(
- !scroll_latching_enabled_, kWheelScrollX, kWheelScrollY,
- kWheelScrollGlobalX, kWheelScrollGlobalY, 1, 1, 0, false,
- WebMouseWheelEvent::kPhaseBegan, WebMouseWheelEvent::kPhaseNone);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false,
+ WebMouseWheelEvent::kPhaseBegan,
+ WebMouseWheelEvent::kPhaseNone);
SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
histogram_tester.ExpectBucketCount(latching_histogram_name, 0, 1);
- SendMouseWheelPossiblyIncludingPhase(
- !scroll_latching_enabled_, kWheelScrollX, kWheelScrollY,
- kWheelScrollGlobalX, kWheelScrollGlobalY, 1, 1, 0, false,
- WebMouseWheelEvent::kPhaseChanged, WebMouseWheelEvent::kPhaseNone);
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false,
+ WebMouseWheelEvent::kPhaseChanged,
+ WebMouseWheelEvent::kPhaseNone);
SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- if (scroll_latching_enabled_) {
histogram_tester.ExpectBucketCount(latching_histogram_name, 0, 1);
histogram_tester.ExpectBucketCount(latching_histogram_name, 1, 1);
- } else {
- histogram_tester.ExpectBucketCount(latching_histogram_name, 0, 2);
- }
}
-INSTANTIATE_TEST_CASE_P(MouseWheelEventQueueTests,
- MouseWheelEventQueueTest,
- testing::Values(kWheelScrollingModeNone,
- kWheelScrollLatching,
- kAsyncWheelEvents));
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc b/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
index d1daf8e1aa6..a13243f3727 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
@@ -102,9 +102,7 @@ void MouseWheelPhaseHandler::DispatchPendingWheelEndEvent() {
TRACE_EVENT_INSTANT0("input", "MouseWheelPhaseHandler Dispatched",
TRACE_EVENT_SCOPE_THREAD);
- base::Closure task = mouse_wheel_end_dispatch_timer_.user_task();
- mouse_wheel_end_dispatch_timer_.Stop();
- std::move(task).Run();
+ mouse_wheel_end_dispatch_timer_.FireNow();
}
void MouseWheelPhaseHandler::IgnorePendingWheelEndEvent() {
@@ -157,7 +155,6 @@ void MouseWheelPhaseHandler::SendSyntheticWheelEventWithPhaseEnded(
bool should_route_event) {
TRACE_EVENT0("input",
"MouseWheelPhaseHandler::SendSyntheticWheelEventWithPhaseEnded");
- DCHECK(host_view_->wheel_scroll_latching_enabled());
last_mouse_wheel_event_.SetTimeStamp(ui::EventTimeForNow());
last_mouse_wheel_event_.delta_x = 0;
last_mouse_wheel_event_.delta_y = 0;
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.h b/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.h
index 4f7c03d6293..305095fc420 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.h
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.h
@@ -80,6 +80,12 @@ class MouseWheelPhaseHandler {
void GestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result);
+ // Used to verify the correctness of touchpad_scroll_phase_state_'s value in
+ // testing.
+ TouchpadScrollPhaseState touchpad_scroll_phase_state_for_test() const {
+ return touchpad_scroll_phase_state_;
+ }
+
private:
void SendSyntheticWheelEventWithPhaseEnded(
bool should_route_event);
diff --git a/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
index 0677a6df8f6..3f23c3a3ed1 100644
--- a/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
@@ -310,10 +310,10 @@ class PassthroughTouchEventQueueTest : public testing::Test,
}
static void RunTasksAndWait(base::TimeDelta delay) {
+ base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- delay);
- base::RunLoop().Run();
+ FROM_HERE, run_loop.QuitClosure(), delay);
+ run_loop.Run();
}
int GetUniqueTouchEventID() { return sent_events_ids_.back(); }
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 185919454c6..e94cc9ba251 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
@@ -26,38 +26,18 @@ using blink::WebTouchEvent;
using ui::LatencyInfo;
namespace content {
-namespace {
-
-ukm::SourceId GenerateUkmSourceId() {
- ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get();
- return ukm_recorder ? ukm_recorder->GetNewSourceID() : ukm::kInvalidSourceId;
-}
-
-} // namespace
RenderWidgetHostLatencyTracker::RenderWidgetHostLatencyTracker(
RenderWidgetHostDelegate* delegate)
- : ukm_source_id_(GenerateUkmSourceId()),
- last_event_id_(0),
- latency_component_id_(0),
- has_seen_first_gesture_scroll_update_(false),
+ : has_seen_first_gesture_scroll_update_(false),
active_multi_finger_gesture_(false),
touch_start_default_prevented_(false),
render_widget_host_delegate_(delegate) {}
RenderWidgetHostLatencyTracker::~RenderWidgetHostLatencyTracker() {}
-void RenderWidgetHostLatencyTracker::Initialize(int routing_id,
- int process_id) {
- DCHECK_EQ(0, last_event_id_);
- DCHECK_EQ(0, latency_component_id_);
- last_event_id_ = static_cast<int64_t>(process_id) << 32;
- latency_component_id_ = routing_id | last_event_id_;
-}
-
void RenderWidgetHostLatencyTracker::ComputeInputLatencyHistograms(
WebInputEvent::Type type,
- int64_t latency_component_id,
const LatencyInfo& latency,
InputEventAckState ack_result) {
// If this event was coalesced into another event, ignore it, as the event it
@@ -72,12 +52,10 @@ void RenderWidgetHostLatencyTracker::ComputeInputLatencyHistograms(
// The event will have gone through OnInputEvent(). So the BEGIN_RWH component
// should always be available here.
- LatencyInfo::LatencyComponent rwh_component;
- bool found_component =
- latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- latency_component_id, &rwh_component);
+ base::TimeTicks rwh_timestamp;
+ bool found_component = latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, &rwh_timestamp);
DCHECK(found_component);
- DCHECK_EQ(rwh_component.event_count, 1u);
bool multi_finger_touch_gesture =
WebInputEvent::IsTouchEventType(type) && active_multi_finger_gesture_;
@@ -98,26 +76,23 @@ void RenderWidgetHostLatencyTracker::ComputeInputLatencyHistograms(
std::string default_action_status =
action_prevented ? "DefaultPrevented" : "DefaultAllowed";
- LatencyInfo::LatencyComponent main_component;
- if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
- &main_component)) {
- DCHECK_EQ(main_component.event_count, 1u);
+ base::TimeTicks main_thread_timestamp;
+ if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT,
+ &main_thread_timestamp)) {
if (!multi_finger_touch_gesture) {
UMA_HISTOGRAM_INPUT_LATENCY_MILLISECONDS(
"Event.Latency.QueueingTime." + event_name + default_action_status,
- rwh_component, main_component);
+ rwh_timestamp, main_thread_timestamp);
}
}
- LatencyInfo::LatencyComponent acked_component;
- if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
- &acked_component)) {
- DCHECK_EQ(acked_component.event_count, 1u);
- if (!multi_finger_touch_gesture &&
- main_component.event_time != base::TimeTicks()) {
+ base::TimeTicks rwh_ack_timestamp;
+ if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT,
+ &rwh_ack_timestamp)) {
+ if (!multi_finger_touch_gesture && !main_thread_timestamp.is_null()) {
UMA_HISTOGRAM_INPUT_LATENCY_MILLISECONDS(
"Event.Latency.BlockingTime." + event_name + default_action_status,
- main_component, acked_component);
+ main_thread_timestamp, rwh_ack_timestamp);
}
}
}
@@ -129,12 +104,6 @@ void RenderWidgetHostLatencyTracker::OnInputEvent(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
OnEventStart(latency);
- if (!set_url_for_ukm_ && render_widget_host_delegate_ &&
- ukm_source_id_ != ukm::kInvalidSourceId) {
- render_widget_host_delegate_->UpdateUrlForUkmSource(ukm::UkmRecorder::Get(),
- ukm_source_id_);
- set_url_for_ukm_ = true;
- }
if (event.GetType() == WebInputEvent::kTouchStart) {
const WebTouchEvent& touch_event =
@@ -150,13 +119,12 @@ void RenderWidgetHostLatencyTracker::OnInputEvent(
// This is the only place to add the BEGIN_RWH component. So this component
// should not already be present in the latency info.
- bool found_component =
- latency->FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- latency_component_id_, nullptr);
+ bool found_component = latency->FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr);
DCHECK(!found_component);
if (!event.TimeStamp().is_null() &&
- !latency->FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
+ !latency->FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
nullptr)) {
base::TimeTicks timestamp_now = base::TimeTicks::Now();
base::TimeTicks timestamp_original = event.TimeStamp();
@@ -170,13 +138,12 @@ void RenderWidgetHostLatencyTracker::OnInputEvent(
latency->AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
- 0,
timestamp_original,
1);
}
latency->AddLatencyNumberWithTraceName(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, latency_component_id_,
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
WebInputEvent::GetName(event.GetType()));
if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
@@ -185,15 +152,14 @@ void RenderWidgetHostLatencyTracker::OnInputEvent(
// Make a copy of the INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT with a
// different name INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT.
// So we can track the latency specifically for scroll update events.
- LatencyInfo::LatencyComponent original_component;
- if (latency->FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
- &original_component)) {
+ base::TimeTicks original_event_timestamp;
+ if (latency->FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
+ &original_event_timestamp)) {
latency->AddLatencyNumberWithTimestamp(
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.event_time,
- original_component.event_count);
+ original_event_timestamp, 1);
}
has_seen_first_gesture_scroll_update_ = true;
@@ -207,9 +173,9 @@ void RenderWidgetHostLatencyTracker::OnInputEventAck(
// Latency ends if an event is acked but does not cause render scheduling.
bool rendering_scheduled = latency->FindLatency(
- ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0, nullptr);
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, nullptr);
rendering_scheduled |= latency->FindLatency(
- ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, nullptr);
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, nullptr);
if (WebInputEvent::IsTouchEventType(event.GetType())) {
const WebTouchEvent& touch_event =
@@ -223,23 +189,25 @@ void RenderWidgetHostLatencyTracker::OnInputEventAck(
}
}
- latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0);
+ latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT);
// If this event couldn't have caused a gesture event, and it didn't trigger
// rendering, we're done processing it. If the event got coalesced then
- // terminate it as well.
- if (!rendering_scheduled || latency->coalesced()) {
- latency->AddLatencyNumber(
- ui::INPUT_EVENT_LATENCY_TERMINATED_NO_SWAP_COMPONENT, 0);
+ // terminate it as well. We also exclude cases where we're against the scroll
+ // extent from scrolling metrics.
+ if (!rendering_scheduled || latency->coalesced() ||
+ (event.GetType() == WebInputEvent::kGestureScrollUpdate &&
+ ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)) {
+ latency->Terminate();
}
- ComputeInputLatencyHistograms(event.GetType(), latency_component_id_,
- *latency, ack_result);
+ ComputeInputLatencyHistograms(event.GetType(), *latency, ack_result);
}
void RenderWidgetHostLatencyTracker::OnEventStart(ui::LatencyInfo* latency) {
static uint64_t global_trace_id = 0;
latency->set_trace_id(++global_trace_id);
- latency->set_ukm_source_id(ukm_source_id_);
+ latency->set_ukm_source_id(
+ render_widget_host_delegate_->GetUkmSourceIdForLastCommittedSource());
}
} // namespace content
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 5f51b9170ab..ab481225e5c 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
@@ -32,7 +32,6 @@ class CONTENT_EXPORT RenderWidgetHostLatencyTracker {
void Initialize(int routing_id, int process_id);
void ComputeInputLatencyHistograms(blink::WebInputEvent::Type type,
- int64_t latency_component_id,
const ui::LatencyInfo& latency,
InputEventAckState ack_result);
@@ -52,18 +51,10 @@ class CONTENT_EXPORT RenderWidgetHostLatencyTracker {
void reset_delegate() { render_widget_host_delegate_ = nullptr; }
- // Returns the ID that uniquely describes this component to the latency
- // subsystem.
- int64_t latency_component_id() const { return latency_component_id_; }
-
private:
void OnEventStart(ui::LatencyInfo* latency);
- ukm::SourceId ukm_source_id_;
- int64_t last_event_id_;
- int64_t latency_component_id_;
bool has_seen_first_gesture_scroll_update_;
- bool set_url_for_ukm_ = false;
// Whether the current stream of touch events includes more than one active
// touch point. This is set in OnInputEvent, and cleared in OnInputEventAck.
bool active_multi_finger_gesture_;
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 629d56804fd..b174affcfc1 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
@@ -3,12 +3,14 @@
// found in the LICENSE file.
#include "content/browser/renderer_host/input/render_widget_host_latency_tracker.h"
+
#include "base/metrics/metrics_hashes.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "components/rappor/public/rappor_utils.h"
#include "components/rappor/test_rappor_service.h"
#include "components/ukm/test_ukm_recorder.h"
#include "components/ukm/ukm_source.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/test/test_content_browser_client.h"
@@ -34,23 +36,22 @@ void AddFakeComponentsWithTimeStamp(
ui::LatencyInfo* latency,
base::TimeTicks time_stamp) {
latency->AddLatencyNumberWithTimestamp(ui::INPUT_EVENT_LATENCY_UI_COMPONENT,
- 0, time_stamp, 1);
+ time_stamp, 1);
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, time_stamp,
- 1);
+ ui::INPUT_EVENT_LATENCY_FRAME_SWAP_COMPONENT, time_stamp, 1);
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, time_stamp, 1);
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, time_stamp, 1);
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, time_stamp, 1);
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, time_stamp, 1);
latency->AddLatencyNumberWithTimestamp(
- ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, 0, time_stamp, 1);
+ ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, time_stamp, 1);
}
void AddFakeComponents(const RenderWidgetHostLatencyTracker& tracker,
ui::LatencyInfo* latency) {
latency->AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker.latency_component_id(), base::TimeTicks::Now(), 1);
+ base::TimeTicks::Now(), 1);
AddFakeComponentsWithTimeStamp(tracker, latency, base::TimeTicks::Now());
}
@@ -59,13 +60,13 @@ void AddRenderingScheduledComponent(ui::LatencyInfo* latency,
base::TimeTicks time_stamp) {
if (main) {
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0,
- time_stamp, 1);
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, time_stamp,
+ 1);
} else {
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0,
- time_stamp, 1);
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, time_stamp,
+ 1);
}
}
@@ -91,7 +92,8 @@ class RenderWidgetHostLatencyTrackerTest
ResetHistograms();
}
- void ExpectUkmReported(const char* event_name,
+ void ExpectUkmReported(ukm::SourceId source_id,
+ const char* event_name,
const std::vector<std::string>& metric_names,
size_t expected_count) {
const ukm::TestUkmRecorder* ukm_recoder =
@@ -100,7 +102,7 @@ class RenderWidgetHostLatencyTrackerTest
auto entries = ukm_recoder->GetEntriesByName(event_name);
EXPECT_EQ(expected_count, entries.size());
for (const auto* const entry : entries) {
- ukm_recoder->ExpectEntrySourceHasUrl(entry, GURL(kUrl));
+ EXPECT_EQ(source_id, entry->source_id);
for (const auto& metric_name : metric_names) {
EXPECT_TRUE(ukm_recoder->EntryHasMetric(entry, metric_name.c_str()));
}
@@ -135,7 +137,6 @@ class RenderWidgetHostLatencyTrackerTest
RenderViewHostImplTestHarness::SetUp();
old_browser_client_ = SetBrowserClientForTesting(&test_browser_client_);
tracker_ = std::make_unique<RenderWidgetHostLatencyTracker>(contents());
- tracker_->Initialize(kTestRoutingId, kTestProcessId);
viz_tracker_.DisableMetricSamplingForTesting();
}
@@ -146,14 +147,12 @@ class RenderWidgetHostLatencyTrackerTest
}
protected:
- DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostLatencyTrackerTest);
- const int kTestRoutingId = 3;
- const int kTestProcessId = 1;
std::unique_ptr<base::HistogramTester> histogram_tester_;
std::unique_ptr<RenderWidgetHostLatencyTracker> tracker_;
ui::LatencyTracker viz_tracker_;
RenderWidgetHostLatencyTrackerTestBrowserClient test_browser_client_;
ContentBrowserClient* old_browser_client_;
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostLatencyTrackerTest);
};
TEST_F(RenderWidgetHostLatencyTrackerTest, TestValidEventTiming) {
@@ -164,32 +163,31 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestValidEventTiming) {
latency_info.set_source_event_type(ui::SourceEventType::WHEEL);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
now + base::TimeDelta::FromMilliseconds(60), 1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT,
now + base::TimeDelta::FromMilliseconds(50), 1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT,
now + base::TimeDelta::FromMilliseconds(40), 1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, 0,
+ ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT,
now + base::TimeDelta::FromMilliseconds(30), 1);
latency_info.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(),
now + base::TimeDelta::FromMilliseconds(20), 1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0,
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT,
now + base::TimeDelta::FromMilliseconds(10), 1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, now, 1);
+ ui::INPUT_EVENT_LATENCY_FRAME_SWAP_COMPONENT, now, 1);
viz_tracker()->OnGpuSwapBuffersCompleted(latency_info);
@@ -219,6 +217,9 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToFirstScrollHistograms) {
const GURL url(kUrl);
size_t total_ukm_entry_count = 0;
contents()->NavigateAndCommit(url);
+ ukm::SourceId source_id = static_cast<WebContentsImpl*>(contents())
+ ->GetUkmSourceIdForLastCommittedSource();
+ EXPECT_NE(ukm::kInvalidSourceId, source_id);
for (bool rendering_on_main : {false, true}) {
ResetHistograms();
{
@@ -228,16 +229,15 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToFirstScrollHistograms) {
wheel.SetTimeStamp(now);
ui::LatencyInfo wheel_latency(ui::SourceEventType::WHEEL);
wheel_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), now, 1);
+ ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, now,
+ 1);
AddFakeComponentsWithTimeStamp(*tracker(), &wheel_latency, now);
AddRenderingScheduledComponent(&wheel_latency, rendering_on_main, now);
tracker()->OnInputEvent(wheel, &wheel_latency);
EXPECT_TRUE(wheel_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
EXPECT_TRUE(wheel_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, nullptr));
tracker()->OnInputEventAck(wheel, &wheel_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
viz_tracker()->OnGpuSwapBuffersCompleted(wheel_latency);
@@ -245,7 +245,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToFirstScrollHistograms) {
// UKM metrics.
total_ukm_entry_count++;
ExpectUkmReported(
- "Event.ScrollBegin.Wheel",
+ source_id, "Event.ScrollBegin.Wheel",
{"TimeToScrollUpdateSwapBegin", "TimeToHandled", "IsMainThread"},
total_ukm_entry_count);
@@ -331,6 +331,9 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToScrollHistograms) {
const GURL url(kUrl);
size_t total_ukm_entry_count = 0;
contents()->NavigateAndCommit(url);
+ ukm::SourceId source_id = static_cast<WebContentsImpl*>(contents())
+ ->GetUkmSourceIdForLastCommittedSource();
+ EXPECT_NE(ukm::kInvalidSourceId, source_id);
for (bool rendering_on_main : {false, true}) {
ResetHistograms();
{
@@ -340,16 +343,14 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToScrollHistograms) {
wheel.SetTimeStamp(now);
ui::LatencyInfo wheel_latency(ui::SourceEventType::WHEEL);
wheel_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), now, 1);
+ ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &wheel_latency, now);
AddRenderingScheduledComponent(&wheel_latency, rendering_on_main, now);
tracker()->OnInputEvent(wheel, &wheel_latency);
EXPECT_TRUE(wheel_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
EXPECT_TRUE(wheel_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, nullptr));
tracker()->OnInputEventAck(wheel, &wheel_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
viz_tracker()->OnGpuSwapBuffersCompleted(wheel_latency);
@@ -357,7 +358,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToScrollHistograms) {
// UKM metrics.
total_ukm_entry_count++;
ExpectUkmReported(
- "Event.ScrollUpdate.Wheel",
+ source_id, "Event.ScrollUpdate.Wheel",
{"TimeToScrollUpdateSwapBegin", "TimeToHandled", "IsMainThread"},
total_ukm_entry_count);
@@ -451,17 +452,13 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestInertialToScrollHistograms) {
base::TimeTicks now = base::TimeTicks::Now();
scroll.SetTimeStamp(now);
ui::LatencyInfo scroll_latency(ui::SourceEventType::INERTIAL);
- scroll_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &scroll_latency, now);
AddRenderingScheduledComponent(&scroll_latency, rendering_on_main, now);
tracker()->OnInputEvent(scroll, &scroll_latency);
EXPECT_TRUE(scroll_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
EXPECT_TRUE(scroll_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, nullptr));
tracker()->OnInputEventAck(scroll, &scroll_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
viz_tracker()->OnGpuSwapBuffersCompleted(scroll_latency);
@@ -503,6 +500,9 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToFirstScrollHistograms) {
const GURL url(kUrl);
contents()->NavigateAndCommit(url);
size_t total_ukm_entry_count = 0;
+ ukm::SourceId source_id = static_cast<WebContentsImpl*>(contents())
+ ->GetUkmSourceIdForLastCommittedSource();
+ EXPECT_NE(ukm::kInvalidSourceId, source_id);
for (bool rendering_on_main : {false, true}) {
ResetHistograms();
{
@@ -511,17 +511,13 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToFirstScrollHistograms) {
base::TimeTicks now = base::TimeTicks::Now();
scroll.SetTimeStamp(now);
ui::LatencyInfo scroll_latency;
- scroll_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &scroll_latency, now);
AddRenderingScheduledComponent(&scroll_latency, rendering_on_main, now);
tracker()->OnInputEvent(scroll, &scroll_latency);
EXPECT_TRUE(scroll_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
EXPECT_TRUE(scroll_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, nullptr));
tracker()->OnInputEventAck(scroll, &scroll_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
}
@@ -533,16 +529,15 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToFirstScrollHistograms) {
ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH);
base::TimeTicks now = base::TimeTicks::Now();
touch_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), now, 1);
+ ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, now,
+ 1);
AddFakeComponentsWithTimeStamp(*tracker(), &touch_latency, now);
AddRenderingScheduledComponent(&touch_latency, rendering_on_main, now);
tracker()->OnInputEvent(touch, &touch_latency);
EXPECT_TRUE(touch_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
EXPECT_TRUE(touch_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, nullptr));
tracker()->OnInputEventAck(touch, &touch_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
viz_tracker()->OnGpuSwapBuffersCompleted(touch_latency);
@@ -551,7 +546,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToFirstScrollHistograms) {
// UKM metrics.
total_ukm_entry_count++;
ExpectUkmReported(
- "Event.ScrollBegin.Touch",
+ source_id, "Event.ScrollBegin.Touch",
{"TimeToScrollUpdateSwapBegin", "TimeToHandled", "IsMainThread"},
total_ukm_entry_count);
@@ -617,6 +612,9 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToScrollHistograms) {
const GURL url(kUrl);
contents()->NavigateAndCommit(url);
size_t total_ukm_entry_count = 0;
+ ukm::SourceId source_id = static_cast<WebContentsImpl*>(contents())
+ ->GetUkmSourceIdForLastCommittedSource();
+ EXPECT_NE(ukm::kInvalidSourceId, source_id);
for (bool rendering_on_main : {false, true}) {
ResetHistograms();
{
@@ -625,17 +623,13 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToScrollHistograms) {
base::TimeTicks now = base::TimeTicks::Now();
scroll.SetTimeStamp(now);
ui::LatencyInfo scroll_latency;
- scroll_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &scroll_latency, now);
AddRenderingScheduledComponent(&scroll_latency, rendering_on_main, now);
tracker()->OnInputEvent(scroll, &scroll_latency);
EXPECT_TRUE(scroll_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
EXPECT_TRUE(scroll_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, nullptr));
tracker()->OnInputEventAck(scroll, &scroll_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
}
@@ -647,16 +641,14 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToScrollHistograms) {
ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH);
base::TimeTicks now = base::TimeTicks::Now();
touch_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), now, 1);
+ ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &touch_latency, now);
AddRenderingScheduledComponent(&touch_latency, rendering_on_main, now);
tracker()->OnInputEvent(touch, &touch_latency);
EXPECT_TRUE(touch_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
EXPECT_TRUE(touch_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, nullptr));
tracker()->OnInputEventAck(touch, &touch_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
viz_tracker()->OnGpuSwapBuffersCompleted(touch_latency);
@@ -665,7 +657,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToScrollHistograms) {
// UKM metrics.
total_ukm_entry_count++;
ExpectUkmReported(
- "Event.ScrollUpdate.Touch",
+ source_id, "Event.ScrollUpdate.Touch",
{"TimeToScrollUpdateSwapBegin", "TimeToHandled", "IsMainThread"},
total_ukm_entry_count);
@@ -737,8 +729,6 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
tracker()->OnInputEvent(scroll, &scroll_latency);
tracker()->OnInputEventAck(scroll, &scroll_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(scroll_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_TERMINATED_NO_SWAP_COMPONENT, 0, nullptr));
EXPECT_TRUE(scroll_latency.terminated());
}
@@ -751,8 +741,6 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
tracker()->OnInputEvent(wheel, &wheel_latency);
tracker()->OnInputEventAck(wheel, &wheel_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(wheel_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_TERMINATED_NO_SWAP_COMPONENT, 0, nullptr));
EXPECT_TRUE(wheel_latency.terminated());
}
@@ -765,8 +753,6 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
tracker()->OnInputEvent(touch, &touch_latency);
tracker()->OnInputEventAck(touch, &touch_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(touch_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_TERMINATED_NO_SWAP_COMPONENT, 0, nullptr));
EXPECT_TRUE(touch_latency.terminated());
}
@@ -778,8 +764,6 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
tracker()->OnInputEvent(mouse_move, &mouse_latency);
tracker()->OnInputEventAck(mouse_move, &mouse_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(mouse_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_TERMINATED_NO_SWAP_COMPONENT, 0, nullptr));
EXPECT_TRUE(mouse_latency.terminated());
}
@@ -792,8 +776,6 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
tracker()->OnInputEvent(key_event, &key_latency);
tracker()->OnInputEventAck(key_event, &key_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(key_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_TERMINATED_NO_SWAP_COMPONENT, 0, nullptr));
EXPECT_TRUE(key_latency.terminated());
}
@@ -812,16 +794,38 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
EXPECT_TRUE(HistogramSizeEq("Event.Latency.ScrollUpdate.GpuSwap", 0));
}
+TEST_F(RenderWidgetHostLatencyTrackerTest, LatencyTerminatedOnAckIfGSUIgnored) {
+ for (blink::WebGestureDevice source_device :
+ {blink::kWebGestureDeviceTouchscreen,
+ blink::kWebGestureDeviceTouchpad}) {
+ for (bool rendering_on_main : {false, true}) {
+ auto scroll = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
+ 5.f, -5.f, 0, source_device);
+ base::TimeTicks now = base::TimeTicks::Now();
+ scroll.SetTimeStamp(now);
+ ui::LatencyInfo scroll_latency;
+ scroll_latency.set_source_event_type(
+ source_device == blink::kWebGestureDeviceTouchscreen
+ ? ui::SourceEventType::TOUCH
+ : ui::SourceEventType::WHEEL);
+ AddFakeComponentsWithTimeStamp(*tracker(), &scroll_latency, now);
+ AddRenderingScheduledComponent(&scroll_latency, rendering_on_main, now);
+ tracker()->OnInputEvent(scroll, &scroll_latency);
+ tracker()->OnInputEventAck(scroll, &scroll_latency,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ EXPECT_TRUE(scroll_latency.terminated());
+ }
+ }
+}
+
TEST_F(RenderWidgetHostLatencyTrackerTest, ScrollLatency) {
auto scroll_begin = SyntheticWebGestureEventBuilder::BuildScrollBegin(
5, -5, blink::kWebGestureDeviceTouchscreen);
ui::LatencyInfo scroll_latency;
- scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
- 0);
+ scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT);
tracker()->OnInputEvent(scroll_begin, &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_BEGIN_RWH_COMPONENT, nullptr));
EXPECT_EQ(2U, scroll_latency.latency_components().size());
// The first GestureScrollUpdate should be provided with
@@ -829,18 +833,14 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, ScrollLatency) {
auto first_scroll_update = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
5.f, -5.f, 0, blink::kWebGestureDeviceTouchscreen);
scroll_latency = ui::LatencyInfo();
- scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
- 0);
+ scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT);
tracker()->OnInputEvent(first_scroll_update, &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_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
+ EXPECT_TRUE(scroll_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, nullptr));
EXPECT_FALSE(scroll_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, nullptr));
EXPECT_EQ(3U, scroll_latency.latency_components().size());
// Subsequent GestureScrollUpdates should be provided with
@@ -848,18 +848,14 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, ScrollLatency) {
auto scroll_update = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
-5.f, 5.f, 0, blink::kWebGestureDeviceTouchscreen);
scroll_latency = ui::LatencyInfo();
- scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
- 0);
+ scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT);
tracker()->OnInputEvent(scroll_update, &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_BEGIN_RWH_COMPONENT, nullptr));
EXPECT_FALSE(scroll_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, nullptr));
EXPECT_TRUE(scroll_latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, nullptr));
EXPECT_EQ(3U, scroll_latency.latency_components().size());
}
@@ -885,28 +881,26 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TouchBlockingAndQueueingTime) {
fake_latency.set_source_event_type(ui::SourceEventType::TOUCH);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[2]),
1);
// Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
// overwriting components.
- tracker()->ComputeInputLatencyHistograms(
- event.GetType(), tracker()->latency_component_id(), fake_latency,
- blocking);
+ tracker()->ComputeInputLatencyHistograms(event.GetType(), fake_latency,
+ blocking);
tracker()->OnInputEventAck(event, &latency,
blocking);
@@ -920,10 +914,9 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TouchBlockingAndQueueingTime) {
tracker()->OnInputEvent(event, &latency);
EXPECT_TRUE(latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
- EXPECT_TRUE(
- latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, nullptr));
+ EXPECT_TRUE(latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
EXPECT_EQ(2U, latency.latency_components().size());
@@ -932,28 +925,26 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TouchBlockingAndQueueingTime) {
fake_latency.set_source_event_type(ui::SourceEventType::TOUCH);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchmove_timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchmove_timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchmove_timestamps_ms[2]),
1);
// Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
// overwriting components.
- tracker()->ComputeInputLatencyHistograms(
- event.GetType(), tracker()->latency_component_id(), fake_latency,
- blocking);
+ tracker()->ComputeInputLatencyHistograms(event.GetType(), fake_latency,
+ blocking);
}
{
@@ -964,10 +955,9 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TouchBlockingAndQueueingTime) {
tracker()->OnInputEvent(event, &latency);
EXPECT_TRUE(latency.FindLatency(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
- EXPECT_TRUE(
- latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), nullptr));
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, nullptr));
+ EXPECT_TRUE(latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
EXPECT_EQ(2U, latency.latency_components().size());
@@ -976,28 +966,26 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TouchBlockingAndQueueingTime) {
fake_latency.set_source_event_type(ui::SourceEventType::TOUCH);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchend_timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchend_timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchend_timestamps_ms[2]),
1);
// Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
// overwriting components.
- tracker()->ComputeInputLatencyHistograms(
- event.GetType(), tracker()->latency_component_id(), fake_latency,
- blocking);
+ tracker()->ComputeInputLatencyHistograms(event.GetType(), fake_latency,
+ blocking);
}
}
@@ -1079,28 +1067,26 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, KeyBlockingAndQueueingTime) {
fake_latency.set_source_event_type(ui::SourceEventType::KEY_PRESS);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(event_timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(event_timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(event_timestamps_ms[2]),
1);
// Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
// overwriting components.
- tracker()->ComputeInputLatencyHistograms(
- event.GetType(), tracker()->latency_component_id(), fake_latency,
- blocking);
+ tracker()->ComputeInputLatencyHistograms(event.GetType(), fake_latency,
+ blocking);
tracker()->OnInputEventAck(event, &latency_info, blocking);
}
@@ -1132,26 +1118,25 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, KeyEndToEndLatency) {
latency_info.set_trace_id(kTraceEventId);
latency_info.set_source_event_type(ui::SourceEventType::KEY_PRESS);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMicroseconds(event_timestamps_microseconds[0]),
1);
latency_info.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMicroseconds(event_timestamps_microseconds[0]),
1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0,
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMicroseconds(event_timestamps_microseconds[1]),
1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_FRAME_SWAP_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMicroseconds(event_timestamps_microseconds[1]),
1);
@@ -1192,19 +1177,18 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
fake_latency.set_trace_id(kTraceEventId);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[2]),
1);
@@ -1212,7 +1196,6 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
// Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
// overwriting components.
tracker()->ComputeInputLatencyHistograms(event.GetType(),
- tracker()->latency_component_id(),
fake_latency, ack_state);
tracker()->OnInputEventAck(event, &latency, ack_state);
@@ -1263,24 +1246,22 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, WheelDuringMultiFingerTouch) {
fake_latency.set_source_event_type(ui::SourceEventType::TOUCH);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(),
base::TimeTicks() + base::TimeDelta::FromMilliseconds(timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT,
base::TimeTicks() + base::TimeDelta::FromMilliseconds(timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT,
base::TimeTicks() + base::TimeDelta::FromMilliseconds(timestamps_ms[2]),
1);
// Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
// overwriting components.
tracker()->ComputeInputLatencyHistograms(wheel_event.GetType(),
- tracker()->latency_component_id(),
fake_latency, ack_state);
tracker()->OnInputEventAck(wheel_event, &latency, ack_state);
diff --git a/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc b/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc
index 156ca38da6e..2d8e33bd72a 100644
--- a/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
@@ -30,7 +30,7 @@ const char kDataURL[] =
"<!DOCTYPE html>"
"<html>"
"<head>"
- "<title>Mouse wheel latency histograms reported.</title>"
+ "<title>Scroll latency histograms browsertests.</title>"
"<script src=\"../../resources/testharness.js\"></script>"
"<script src=\"../../resources/testharnessreport.js\"></script>"
"<style>"
@@ -40,7 +40,20 @@ const char kDataURL[] =
"</style>"
"</head>"
"<body>"
+ "<div id='spinner'>Spinning</div>"
"</body>"
+ "<script>"
+ "var degree = 0;"
+ "function spin() {"
+ "degree = degree + 3;"
+ "if (degree >= 360)"
+ "degree -= 360;"
+ "document.getElementById('spinner').style['transform'] = "
+ "'rotate(' + degree + 'deg)';"
+ "requestAnimationFrame(spin);"
+ "}"
+ "spin();"
+ "</script>"
"</html>";
} // namespace
@@ -73,6 +86,11 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
frame_observer_->Wait();
}
+ void OnSyntheticGestureCompleted(SyntheticGesture::Result result) {
+ EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
+ run_loop_->Quit();
+ }
+
protected:
void LoadURL() {
const GURL data_url(kDataURL);
@@ -109,9 +127,20 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
GetWidgetHost()->ForwardGestureEvent(event2);
}
+ // Returns true if the given histogram has recorded the expected number of
+ // samples.
+ bool VerifyRecordedSamplesForHistogram(
+ const size_t num_samples,
+ const std::string& histogram_name) const {
+ return num_samples ==
+ histogram_tester_.GetAllSamples(histogram_name).size();
+ }
+
+ std::unique_ptr<base::RunLoop> run_loop_;
+
private:
+ base::HistogramTester histogram_tester_;
base::MessageLoop loop_;
- base::RunLoop runner_;
std::unique_ptr<MainThreadFrameObserver> frame_observer_;
DISALLOW_COPY_AND_ASSIGN(ScrollLatencyBrowserTest);
@@ -122,20 +151,63 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
IN_PROC_BROWSER_TEST_F(ScrollLatencyBrowserTest, SmoothWheelScroll) {
LoadURL();
- base::HistogramTester histogram_tester;
DoSmoothWheelScroll(gfx::Vector2d(0, 100));
-
- size_t num_samples = 0;
-
- while (num_samples == 0) {
- FetchHistogramsFromChildProcesses();
- num_samples =
- histogram_tester
- .GetAllSamples(
- "Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin2")
- .size();
+ while (!VerifyRecordedSamplesForHistogram(
+ 1, "Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin2")) {
GiveItSomeTime();
+ FetchHistogramsFromChildProcesses();
}
}
+// Do an upward wheel scroll, and verify that no scroll metrics is recorded when
+// the scroll event is ignored.
+IN_PROC_BROWSER_TEST_F(ScrollLatencyBrowserTest,
+ ScrollLatencyNotRecordedIfGSUIgnored) {
+ LoadURL();
+ auto scroll_update_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kGestureScrollUpdate);
+
+ // Try to scroll upward, the GSU(s) will get ignored since the scroller is at
+ // its extent.
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.anchor = gfx::PointF(10, 10);
+ params.distances.push_back(gfx::Vector2d(0, 60));
+
+ run_loop_ = std::make_unique<base::RunLoop>();
+
+ std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ GetWidgetHost()->QueueSyntheticGesture(
+ std::move(gesture),
+ base::BindOnce(&ScrollLatencyBrowserTest::OnSyntheticGestureCompleted,
+ base::Unretained(this)));
+
+ // Runs until we get the OnSyntheticGestureCompleted callback and verify that
+ // the first GSU event is ignored.
+ run_loop_->Run();
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
+ scroll_update_watcher->GetAckStateWaitIfNecessary());
+
+ // Wait for one frame and then verify that the scroll metrics are not
+ // recorded.
+ std::unique_ptr<RenderFrameSubmissionObserver> frame_observer =
+ std::make_unique<RenderFrameSubmissionObserver>(
+ GetWidgetHost()->render_frame_metadata_provider());
+ frame_observer->WaitForAnyFrameSubmission();
+ FetchHistogramsFromChildProcesses();
+ EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
+ 0, "Event.Latency.ScrollBegin.Touch.BrowserNotifiedToBeforeGpuSwap2"));
+ EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
+ 0, "Event.Latency.ScrollBegin.Touch.GpuSwap2"));
+ EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
+ 0, "Event.Latency.ScrollBegin.Touch.HandledToRendererSwap2_Impl"));
+ EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
+ 0, "Event.Latency.ScrollBegin.Touch.RendererSwapToBrowserNotified2"));
+ EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
+ 0, "Event.Latency.ScrollBegin.Touch.TimeToHandled2_Impl"));
+ EXPECT_TRUE(VerifyRecordedSamplesForHistogram(
+ 0, "Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin2"));
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/stylus_text_selector.cc b/chromium/content/browser/renderer_host/input/stylus_text_selector.cc
index 89660b8b72a..cc4e7ebd16f 100644
--- a/chromium/content/browser/renderer_host/input/stylus_text_selector.cc
+++ b/chromium/content/browser/renderer_host/input/stylus_text_selector.cc
@@ -103,7 +103,7 @@ bool StylusTextSelector::OnTouchEvent(const MotionEvent& event) {
if (!gesture_detector_)
gesture_detector_ = CreateGestureDetector(this);
- gesture_detector_->OnTouchEvent(event);
+ gesture_detector_->OnTouchEvent(event, false /* should_process_double_tap */);
// Always return true, even if |gesture_detector_| technically doesn't
// consume the event. This prevents forwarding of a partial touch stream.
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 33c478a33f8..63a710082da 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
@@ -96,6 +96,22 @@ WebInputEvent::Type ToWebMouseEventType(
return WebInputEvent::kUndefined;
}
+WebInputEvent::Type WebTouchPointStateToEventType(
+ blink::WebTouchPoint::State state) {
+ switch (state) {
+ case blink::WebTouchPoint::kStateReleased:
+ return WebInputEvent::kTouchEnd;
+ case blink::WebTouchPoint::kStatePressed:
+ return WebInputEvent::kTouchStart;
+ case blink::WebTouchPoint::kStateMoved:
+ return WebInputEvent::kTouchMove;
+ case blink::WebTouchPoint::kStateCancelled:
+ return WebInputEvent::kTouchCancel;
+ default:
+ return WebInputEvent::kUndefined;
+ }
+}
+
class MockSyntheticGesture : public SyntheticGesture {
public:
MockSyntheticGesture(bool* finished, int num_steps)
@@ -541,11 +557,13 @@ class MockSyntheticPointerTouchActionTarget
const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
type_ = touch_event.GetType();
for (size_t i = 0; i < WebTouchEvent::kTouchesLengthCap; ++i) {
+ if (WebTouchPointStateToEventType(touch_event.touches[i].state) != type_)
+ continue;
+
indexes_[i] = touch_event.touches[i].id;
positions_[i] = gfx::PointF(touch_event.touches[i].PositionInWidget());
states_[i] = touch_event.touches[i].state;
}
- touch_length_ = touch_event.touches_length;
num_actions_dispatched_++;
}
@@ -581,16 +599,12 @@ class MockSyntheticPointerTouchActionTarget
testing::AssertionResult SyntheticTouchActionListDispatchedCorrectly(
const std::vector<SyntheticPointerActionParams>& params_list) {
- if (touch_length_ != params_list.size()) {
- return testing::AssertionFailure() << "Touch point length was "
- << touch_length_ << ", expected "
- << params_list.size() << ".";
- }
-
testing::AssertionResult result = testing::AssertionSuccess();
for (size_t i = 0; i < params_list.size(); ++i) {
- result = SyntheticTouchActionDispatchedCorrectly(params_list[i],
- params_list[i].index());
+ if (params_list[i].pointer_action_type() !=
+ SyntheticPointerActionParams::PointerActionType::IDLE)
+ result = SyntheticTouchActionDispatchedCorrectly(
+ params_list[i], params_list[i].index());
if (result == testing::AssertionFailure())
return result;
}
@@ -599,7 +613,6 @@ class MockSyntheticPointerTouchActionTarget
private:
gfx::PointF positions_[kTouchPointersLength];
- unsigned touch_length_;
int indexes_[kTouchPointersLength];
WebTouchPoint::State states_[kTouchPointersLength];
};
@@ -1655,7 +1668,7 @@ TEST_F(SyntheticGestureControllerTest, PointerTouchAction) {
static_cast<MockSyntheticPointerTouchActionTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
- EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 1);
+ EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 2);
EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
param_list));
@@ -1676,7 +1689,7 @@ TEST_F(SyntheticGestureControllerTest, PointerTouchAction) {
EXPECT_EQ(2, num_success_);
EXPECT_EQ(0, num_failure_);
- EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 2);
+ EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 4);
EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
param_list));
@@ -1693,7 +1706,7 @@ TEST_F(SyntheticGestureControllerTest, PointerTouchAction) {
EXPECT_EQ(3, num_success_);
EXPECT_EQ(0, num_failure_);
- EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 3);
+ EXPECT_EQ(pointer_touch_target->num_actions_dispatched(), 5);
EXPECT_TRUE(pointer_touch_target->SyntheticTouchActionListDispatchedCorrectly(
param_list));
}
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
index 56c9d367e7e..c238c21add2 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
@@ -49,7 +49,7 @@ void SyntheticGestureTargetBase::DispatchInputEventToPlatform(
"type", WebInputEvent::GetName(event.GetType()));
ui::LatencyInfo latency_info;
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT);
if (WebInputEvent::IsTouchEventType(event.GetType())) {
const WebTouchEvent& web_touch =
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 38de025910c..bc0526b5fee 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
@@ -79,8 +79,9 @@ SyntheticPointerAction::ForwardTouchOrMouseInputEvents(
case SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED:
return INVALID;
}
+ synthetic_pointer_driver_->DispatchEvent(target, timestamp);
}
- synthetic_pointer_driver_->DispatchEvent(target, timestamp);
+
num_actions_dispatched_++;
if (num_actions_dispatched_ == params_.params.size())
return DONE;
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc b/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
index 0c681c68c67..c4d45f9d825 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
@@ -60,6 +60,22 @@ WebInputEvent::Type ToWebMouseEventType(
return WebInputEvent::kUndefined;
}
+WebInputEvent::Type WebTouchPointStateToEventType(
+ blink::WebTouchPoint::State state) {
+ switch (state) {
+ case blink::WebTouchPoint::kStateReleased:
+ return WebInputEvent::kTouchEnd;
+ case blink::WebTouchPoint::kStatePressed:
+ return WebInputEvent::kTouchStart;
+ case blink::WebTouchPoint::kStateMoved:
+ return WebInputEvent::kTouchMove;
+ case blink::WebTouchPoint::kStateCancelled:
+ return WebInputEvent::kTouchCancel;
+ default:
+ return WebInputEvent::kUndefined;
+ }
+}
+
class MockSyntheticPointerActionTarget : public SyntheticGestureTarget {
public:
MockSyntheticPointerActionTarget() {}
@@ -107,11 +123,13 @@ class MockSyntheticPointerTouchActionTarget
const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
type_ = touch_event.GetType();
for (size_t i = 0; i < WebTouchEvent::kTouchesLengthCap; ++i) {
+ if (WebTouchPointStateToEventType(touch_event.touches[i].state) != type_)
+ continue;
+
indexes_[i] = touch_event.touches[i].id;
positions_[i] = gfx::PointF(touch_event.touches[i].PositionInWidget());
states_[i] = touch_event.touches[i].state;
}
- touch_length_ = touch_event.touches_length;
}
testing::AssertionResult SyntheticTouchActionDispatchedCorrectly(
@@ -146,16 +164,12 @@ class MockSyntheticPointerTouchActionTarget
testing::AssertionResult SyntheticTouchActionListDispatchedCorrectly(
const std::vector<SyntheticPointerActionParams>& params_list) {
- if (touch_length_ != params_list.size()) {
- return testing::AssertionFailure() << "Touch point length was "
- << touch_length_ << ", expected "
- << params_list.size() << ".";
- }
-
testing::AssertionResult result = testing::AssertionSuccess();
for (size_t i = 0; i < params_list.size(); ++i) {
- result = SyntheticTouchActionDispatchedCorrectly(params_list[i],
- params_list[i].index());
+ if (params_list[i].pointer_action_type() !=
+ SyntheticPointerActionParams::PointerActionType::IDLE)
+ result = SyntheticTouchActionDispatchedCorrectly(
+ params_list[i], params_list[i].index());
if (result == testing::AssertionFailure())
return result;
}
@@ -169,7 +183,6 @@ class MockSyntheticPointerTouchActionTarget
private:
gfx::PointF positions_[WebTouchEvent::kTouchesLengthCap];
- unsigned touch_length_;
int indexes_[WebTouchEvent::kTouchesLengthCap];
WebTouchPoint::State states_[WebTouchEvent::kTouchesLengthCap];
};
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 f06e309f256..41c2c94fe34 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -101,9 +101,9 @@ const char kTouchActionURLWithOverlapArea[] =
" touch-action: pan-x;"
"}"
"</style>"
+ "<div class='box ta-auto'></div>"
"<div class='box ta-panx'></div>"
"<div class='box ta-pany'></div>"
- "<div class='box ta-auto'></div>"
"<div class=spacer></div>"
"<script>"
" document.title='ready';"
@@ -279,10 +279,25 @@ class TouchActionBrowserTest : public ContentBrowserTest {
ExecuteScriptAndExtractInt("document.documentElement.scrollHeight");
EXPECT_EQ(expected_scroll_height_after_scroll, scroll_height);
+ float page_scale_factor =
+ frame_observer_->LastRenderFrameMetadata().page_scale_factor;
+ if (page_scale_factor == 0)
+ page_scale_factor = 1.0f;
+ gfx::PointF touch_point(point);
+ if (page_scale_factor != 1.0f) {
+ touch_point.set_x(touch_point.x() * page_scale_factor);
+ touch_point.set_y(touch_point.y() * page_scale_factor);
+ }
SyntheticSmoothScrollGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
- params.anchor = gfx::PointF(point);
+ params.anchor = touch_point;
params.distances.push_back(-distance);
+ // Set the speed to very high so that there is one GSU only.
+ // It seems that when the speed is too high, it has a race with the timeout
+ // test.
+ if (jank_time != kLongJankTime) {
+ params.speed_in_pixels_s = 1000000;
+ }
run_loop_ = std::make_unique<base::RunLoop>();
@@ -331,7 +346,7 @@ class TouchActionBrowserTest : public ContentBrowserTest {
int scroll_top = GetScrollTop();
int scroll_left = GetScrollLeft();
- // Allow for 1px rounding inaccuracies for some screen sizes.
+ // Expect it scrolled at least half of the expected distance.
EXPECT_LE(expected_scroll_position_after_scroll.y() / 2, scroll_top);
EXPECT_LE(expected_scroll_position_after_scroll.x() / 2, scroll_left);
}
@@ -342,10 +357,9 @@ class TouchActionBrowserTest : public ContentBrowserTest {
DISALLOW_COPY_AND_ASSIGN(TouchActionBrowserTest);
};
-// Mac doesn't yet have a gesture recognizer, so can't support turning touch
-// events into scroll gestures.
-// Will be fixed with http://crbug.com/337142
-#if defined(OS_MACOSX)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) || \
+ defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+ defined(THREAD_SANITIZER)
#define MAYBE_DefaultAuto DISABLED_DefaultAuto
#else
#define MAYBE_DefaultAuto DefaultAuto
@@ -367,8 +381,9 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_DefaultAuto) {
// Verify that touching a touch-action: none region disables scrolling and
// enables all touch events to be sent.
-// Disabled on MacOS because it doesn't support touch input.
-#if defined(OS_MACOSX)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) || \
+ defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+ defined(THREAD_SANITIZER)
#define MAYBE_TouchActionNone DISABLED_TouchActionNone
#else
#define MAYBE_TouchActionNone TouchActionNone
@@ -385,7 +400,9 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_TouchActionNone) {
EXPECT_EQ(0, ExecuteScriptAndExtractInt("eventCounts.touchcancel"));
}
-#if defined(OS_MACOSX)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) || \
+ defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+ defined(THREAD_SANITIZER)
#define MAYBE_PanYMainThreadJanky DISABLED_PanYMainThreadJanky
#else
#define MAYBE_PanYMainThreadJanky PanYMainThreadJanky
@@ -397,7 +414,9 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_PanYMainThreadJanky) {
gfx::Vector2d(0, 45), kShortJankTime);
}
-#if defined(OS_MACOSX)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) || \
+ defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+ defined(THREAD_SANITIZER)
#define MAYBE_PanXMainThreadJanky DISABLED_PanXMainThreadJanky
#else
#define MAYBE_PanXMainThreadJanky PanXMainThreadJanky
@@ -438,7 +457,9 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
DoTwoFingerTouchScroll(false, gfx::Vector2d(20, 0));
}
-#if defined(OS_MACOSX)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) || \
+ defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+ defined(THREAD_SANITIZER)
#define MAYBE_PanXYMainThreadJanky DISABLED_PanXYMainThreadJanky
#else
#define MAYBE_PanXYMainThreadJanky PanXYMainThreadJanky
@@ -450,8 +471,9 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_PanXYMainThreadJanky) {
gfx::Vector2d(45, 45), kShortJankTime);
}
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
-// Flaky: https://crbug.com/833015
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) || \
+ defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+ defined(THREAD_SANITIZER)
#define MAYBE_PanXYAtXAreaMainThreadJanky DISABLED_PanXYAtXAreaMainThreadJanky
#else
#define MAYBE_PanXYAtXAreaMainThreadJanky PanXYAtXAreaMainThreadJanky
@@ -460,12 +482,13 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
MAYBE_PanXYAtXAreaMainThreadJanky) {
LoadURL(kTouchActionURLWithOverlapArea);
- DoTouchScroll(gfx::Point(125, 25), gfx::Vector2d(45, 45), false, 10000,
+ DoTouchScroll(gfx::Point(125, 25), gfx::Vector2d(45, 20), false, 10000,
gfx::Vector2d(45, 0), kShortJankTime);
}
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
-// Flaky: https://crbug.com/833015
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) || \
+ defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+ defined(THREAD_SANITIZER)
#define MAYBE_PanXYAtYAreaMainThreadJanky DISABLED_PanXYAtYAreaMainThreadJanky
#else
#define MAYBE_PanXYAtYAreaMainThreadJanky PanXYAtYAreaMainThreadJanky
@@ -474,11 +497,13 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
MAYBE_PanXYAtYAreaMainThreadJanky) {
LoadURL(kTouchActionURLWithOverlapArea);
- DoTouchScroll(gfx::Point(25, 125), gfx::Vector2d(45, 45), false, 10000,
+ DoTouchScroll(gfx::Point(25, 125), gfx::Vector2d(20, 45), false, 10000,
gfx::Vector2d(0, 45), kShortJankTime);
}
-#if defined(OS_MACOSX)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) || \
+ defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+ defined(THREAD_SANITIZER)
#define MAYBE_PanXYAtAutoYOverlapAreaMainThreadJanky \
DISABLED_PanXYAtAutoYOverlapAreaMainThreadJanky
#else
@@ -489,11 +514,13 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
MAYBE_PanXYAtAutoYOverlapAreaMainThreadJanky) {
LoadURL(kTouchActionURLWithOverlapArea);
- DoTouchScroll(gfx::Point(75, 125), gfx::Vector2d(45, 45), false, 10000,
+ DoTouchScroll(gfx::Point(75, 125), gfx::Vector2d(20, 45), false, 10000,
gfx::Vector2d(0, 45), kShortJankTime);
}
-#if defined(OS_MACOSX)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) || \
+ defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+ defined(THREAD_SANITIZER)
#define MAYBE_PanXYAtAutoXOverlapAreaMainThreadJanky \
DISABLED_PanXYAtAutoXOverlapAreaMainThreadJanky
#else
@@ -504,7 +531,7 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
MAYBE_PanXYAtAutoXOverlapAreaMainThreadJanky) {
LoadURL(kTouchActionURLWithOverlapArea);
- DoTouchScroll(gfx::Point(125, 75), gfx::Vector2d(45, 45), false, 10000,
+ DoTouchScroll(gfx::Point(125, 75), gfx::Vector2d(45, 20), false, 10000,
gfx::Vector2d(45, 0), kShortJankTime);
}
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter.cc b/chromium/content/browser/renderer_host/input/touch_action_filter.cc
index a7cd888a9cb..16e30e8e392 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.cc
@@ -38,8 +38,7 @@ TouchActionFilter::TouchActionFilter()
: suppress_manipulation_events_(false),
drop_current_tap_ending_event_(false),
allow_current_double_tap_event_(true),
- force_enable_zoom_(false),
- allowed_touch_action_(cc::kTouchActionAuto) {}
+ force_enable_zoom_(false) {}
FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
WebGestureEvent* gesture_event) {
@@ -49,15 +48,21 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
// Filter for allowable touch actions first (eg. before the TouchEventQueue
// can decide to send a touch cancel event).
switch (gesture_event->GetType()) {
- case WebInputEvent::kGestureScrollBegin:
+ case WebInputEvent::kGestureScrollBegin: {
DCHECK(!suppress_manipulation_events_);
+ DCHECK(!touchscreen_scroll_in_progress_);
+ touchscreen_scroll_in_progress_ = true;
+ // TODO(https://crbug.com/851644): Make sure the value is properly set.
+ if (!scrolling_touch_action_.has_value())
+ SetTouchAction(cc::kTouchActionAuto);
suppress_manipulation_events_ =
ShouldSuppressManipulation(*gesture_event);
return suppress_manipulation_events_
? FilterGestureEventResult::kFilterGestureEventFiltered
: FilterGestureEventResult::kFilterGestureEventAllowed;
+ }
- case WebInputEvent::kGestureScrollUpdate:
+ case WebInputEvent::kGestureScrollUpdate: {
if (suppress_manipulation_events_)
return FilterGestureEventResult::kFilterGestureEventFiltered;
@@ -69,39 +74,25 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
// two-finger scrolling but a "touch-action: pan-x pinch-zoom" region
// doesn't.
// TODO(mustaq): Add it to spec?
- if (IsYAxisActionDisallowed(allowed_touch_action_)) {
+ if (IsYAxisActionDisallowed(scrolling_touch_action_.value())) {
gesture_event->data.scroll_update.delta_y = 0;
gesture_event->data.scroll_update.velocity_y = 0;
- } else if (IsXAxisActionDisallowed(allowed_touch_action_)) {
+ } else if (IsXAxisActionDisallowed(scrolling_touch_action_.value())) {
gesture_event->data.scroll_update.delta_x = 0;
gesture_event->data.scroll_update.velocity_x = 0;
}
break;
+ }
case WebInputEvent::kGestureFlingStart:
- ReportGestureEventFiltered(suppress_manipulation_events_);
- // Touchscreen flings should always have non-zero velocity.
- DCHECK(gesture_event->data.fling_start.velocity_x ||
- gesture_event->data.fling_start.velocity_y);
- if (!suppress_manipulation_events_) {
- // Flings restricted to a specific axis shouldn't permit velocity
- // in the perpendicular axis.
- if (IsYAxisActionDisallowed(allowed_touch_action_))
- gesture_event->data.fling_start.velocity_y = 0;
- else if (IsXAxisActionDisallowed(allowed_touch_action_))
- gesture_event->data.fling_start.velocity_x = 0;
- // As the renderer expects a scroll-ending event, but does not expect a
- // zero-velocity fling, convert the now zero-velocity fling accordingly.
- if (!gesture_event->data.fling_start.velocity_x &&
- !gesture_event->data.fling_start.velocity_y) {
- gesture_event->SetType(WebInputEvent::kGestureScrollEnd);
- }
- }
- return FilterManipulationEventAndResetState()
- ? FilterGestureEventResult::kFilterGestureEventFiltered
- : FilterGestureEventResult::kFilterGestureEventAllowed;
+ // Fling controller processes FlingStart event, and we should never get
+ // it here.
+ NOTREACHED();
+ break;
case WebInputEvent::kGestureScrollEnd:
+ DCHECK(touchscreen_scroll_in_progress_);
+ touchscreen_scroll_in_progress_ = false;
ReportGestureEventFiltered(suppress_manipulation_events_);
return FilterManipulationEventAndResetState()
? FilterGestureEventResult::kFilterGestureEventFiltered
@@ -125,21 +116,21 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
break;
// If double tap is disabled, there's no reason for the tap delay.
- case WebInputEvent::kGestureTapUnconfirmed:
+ case WebInputEvent::kGestureTapUnconfirmed: {
DCHECK_EQ(1, gesture_event->data.tap.tap_count);
- allow_current_double_tap_event_ =
- (allowed_touch_action_ & cc::kTouchActionDoubleTapZoom) != 0;
+ // TODO(https://crbug.com/851644): Make sure the value is properly set.
+ if (!scrolling_touch_action_.has_value())
+ SetTouchAction(cc::kTouchActionAuto);
+ allow_current_double_tap_event_ = (scrolling_touch_action_.value() &
+ cc::kTouchActionDoubleTapZoom) != 0;
if (!allow_current_double_tap_event_) {
gesture_event->SetType(WebInputEvent::kGestureTap);
drop_current_tap_ending_event_ = true;
}
break;
+ }
case WebInputEvent::kGestureTap:
- allow_current_double_tap_event_ =
- (allowed_touch_action_ & cc::kTouchActionDoubleTapZoom) != 0;
- FALLTHROUGH;
-
case WebInputEvent::kGestureTapCancel:
if (drop_current_tap_ending_event_) {
drop_current_tap_ending_event_ = false;
@@ -148,6 +139,16 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
break;
case WebInputEvent::kGestureTapDown:
+ // If the gesture is hitting a region that has a non-blocking (such as a
+ // passive) event listener.
+ if (gesture_event->is_source_touch_event_set_non_blocking)
+ SetTouchAction(cc::kTouchActionAuto);
+ scrolling_touch_action_ = allowed_touch_action_;
+ // TODO(https://crbug.com/851644): The value may not set in the case when
+ // the gesture event is flushed due to touch ack time out after the finger
+ // is lifted up. Make sure the value is properly set.
+ if (!scrolling_touch_action_.has_value())
+ SetTouchAction(cc::kTouchActionAuto);
DCHECK(!drop_current_tap_ending_event_);
break;
@@ -160,6 +161,11 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
return FilterGestureEventResult::kFilterGestureEventAllowed;
}
+void TouchActionFilter::SetTouchAction(cc::TouchAction touch_action) {
+ allowed_touch_action_ = touch_action;
+ scrolling_touch_action_ = allowed_touch_action_;
+}
+
bool TouchActionFilter::FilterManipulationEventAndResetState() {
if (suppress_manipulation_events_) {
suppress_manipulation_events_ = false;
@@ -169,6 +175,8 @@ bool TouchActionFilter::FilterManipulationEventAndResetState() {
}
void TouchActionFilter::OnSetTouchAction(cc::TouchAction touch_action) {
+ // TODO(https://crbug.com/849819): add a DCHECK for
+ // |has_touch_event_handler_|.
// For multiple fingers, we take the intersection of the touch actions for
// all fingers that have gone down during this action. In the majority of
// real-world scenarios the touch action for all fingers will be the same.
@@ -180,22 +188,35 @@ void TouchActionFilter::OnSetTouchAction(cc::TouchAction touch_action) {
// down "at once" will be deterministic.
// 2. Only subtractive - eg. can't trigger scrolling on a element that
// otherwise has scrolling disabling by the addition of a finger.
- allowed_touch_action_ &= touch_action;
+ allowed_touch_action_ =
+ allowed_touch_action_.value_or(cc::kTouchActionAuto) & touch_action;
// When user enabled force enable zoom, we should always allow pinch-zoom
// except for touch-action:none.
- if (force_enable_zoom_ && allowed_touch_action_ != cc::kTouchActionNone)
- allowed_touch_action_ |= cc::kTouchActionPinchZoom;
+ if (force_enable_zoom_ && allowed_touch_action_ != cc::kTouchActionNone) {
+ allowed_touch_action_ =
+ allowed_touch_action_.value() | cc::kTouchActionPinchZoom;
+ }
+ scrolling_touch_action_ = allowed_touch_action_;
}
void TouchActionFilter::ReportAndResetTouchAction() {
+ ReportTouchAction();
+ ResetTouchAction();
+}
+
+void TouchActionFilter::ReportTouchAction() {
+ // TODO(https://crbug.com/851644): make sure the value is properly set.
+ if (!scrolling_touch_action_.has_value())
+ SetTouchAction(cc::kTouchActionAuto);
// Report the effective touch action computed by blink such as
// kTouchActionNone, kTouchActionPanX, etc.
// Since |cc::kTouchActionAuto| is equivalent to |cc::kTouchActionMax|, we
// must add one to the upper bound to be able to visualize the number of
// times |cc::kTouchActionAuto| is hit.
UMA_HISTOGRAM_ENUMERATION("TouchAction.EffectiveTouchAction",
- allowed_touch_action_, cc::kTouchActionMax + 1);
+ scrolling_touch_action_.value(),
+ cc::kTouchActionMax + 1);
// Report how often the effective touch action computed by blink is or is
// not equivalent to the whitelisted touch action computed by the
@@ -203,16 +224,25 @@ void TouchActionFilter::ReportAndResetTouchAction() {
if (white_listed_touch_action_.has_value()) {
UMA_HISTOGRAM_BOOLEAN(
"TouchAction.EquivalentEffectiveAndWhiteListed",
- allowed_touch_action_ == white_listed_touch_action_.value());
+ scrolling_touch_action_.value() == white_listed_touch_action_.value());
}
- ResetTouchAction();
}
void TouchActionFilter::ResetTouchAction() {
// Note that resetting the action mid-sequence is tolerated. Gestures that had
- // their begin event(s) suppressed will be suppressed until the next sequence.
- allowed_touch_action_ = cc::kTouchActionAuto;
- white_listed_touch_action_.reset();
+ // their begin event(s) suppressed will be suppressed until the next
+ // sequenceo.
+ if (has_touch_event_handler_) {
+ allowed_touch_action_.reset();
+ white_listed_touch_action_.reset();
+ } else {
+ // Lack of a touch handler indicates that the page either has no
+ // touch-action modifiers or that all its touch-action modifiers are auto.
+ // Resetting the touch-action here allows forwarding of subsequent gestures
+ // even if the underlying touches never reach the router.
+ SetTouchAction(cc::kTouchActionAuto);
+ white_listed_touch_action_ = cc::kTouchActionAuto;
+ }
}
void TouchActionFilter::OnSetWhiteListedTouchAction(
@@ -235,7 +265,7 @@ bool TouchActionFilter::ShouldSuppressManipulation(
// Any GestureScrollBegin with more than one fingers is like a pinch-zoom
// for touch-actions, see crbug.com/632525. Therefore, we switch to
// blocked-manipulation mode iff pinch-zoom is disallowed.
- return (allowed_touch_action_ & cc::kTouchActionPinchZoom) == 0;
+ return (scrolling_touch_action_.value() & cc::kTouchActionPinchZoom) == 0;
}
const float& deltaXHint = gesture_event.data.scroll_begin.delta_x_hint;
@@ -262,7 +292,24 @@ bool TouchActionFilter::ShouldSuppressManipulation(
}
DCHECK(minimal_conforming_touch_action != cc::kTouchActionNone);
- return (allowed_touch_action_ & minimal_conforming_touch_action) == 0;
+ return (scrolling_touch_action_.value() & minimal_conforming_touch_action) ==
+ 0;
+}
+
+void TouchActionFilter::OnHasTouchEventHandlers(bool has_handlers) {
+ // The has_touch_event_handler_ is default to false which is why we have the
+ // "&&" condition here, to ensure that touch actions will be set if there is
+ // no touch event handler on a page.
+ if (has_handlers && has_touch_event_handler_ == has_handlers)
+ return;
+ has_touch_event_handler_ = has_handlers;
+ ResetTouchAction();
+ // If a page has a touch event handler, this function can be called twice with
+ // has_handlers = false first and then true later. When it is true, we need to
+ // reset the |scrolling_touch_action_|. However, we do not want to reset it if
+ // there is an active scroll in progress.
+ if (has_touch_event_handler_ && !touchscreen_scroll_in_progress_)
+ scrolling_touch_action_.reset();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter.h b/chromium/content/browser/renderer_host/input/touch_action_filter.h
index 851d92e954b..d1167ae83d6 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter.h
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.h
@@ -57,15 +57,22 @@ class CONTENT_EXPORT TouchActionFilter {
// renderer for a touch start event that is currently in flight.
void OnSetWhiteListedTouchAction(cc::TouchAction white_listed_touch_action);
- cc::TouchAction allowed_touch_action() const { return allowed_touch_action_; }
+ base::Optional<cc::TouchAction> allowed_touch_action() const {
+ return allowed_touch_action_;
+ }
void SetForceEnableZoom(bool enabled) { force_enable_zoom_ = enabled; }
+ void OnHasTouchEventHandlers(bool has_handlers);
+
private:
friend class MockRenderWidgetHost;
+ friend class TouchActionFilterTest;
bool ShouldSuppressManipulation(const blink::WebGestureEvent&);
bool FilterManipulationEventAndResetState();
+ void ReportTouchAction();
+ void SetTouchAction(cc::TouchAction touch_action);
// Whether scroll and pinch gestures should be discarded due to touch-action.
bool suppress_manipulation_events_;
@@ -83,8 +90,23 @@ class CONTENT_EXPORT TouchActionFilter {
// Force enable zoom for Accessibility.
bool force_enable_zoom_;
+ // Indicates whether this page has touch event handler or not. Set by
+ // InputRouterImpl::OnHasTouchEventHandler.
+ // TODO(https://crbug.com/850238): default to true or make it Optional.
+ bool has_touch_event_handler_ = false;
+
+ // True if an active touch scroll gesture is in progress. i.e. after GSB and
+ // before GSE.
+ bool touchscreen_scroll_in_progress_ = false;
+
// What touch actions are currently permitted.
- cc::TouchAction allowed_touch_action_;
+ base::Optional<cc::TouchAction> allowed_touch_action_;
+
+ // The touch action that is used for the current scrolling gesture sequence.
+ // At the touch sequence end, the |allowed_touch_action| is reset while this
+ // remains set as the effective touch action, for the still in progress scroll
+ // sequence due to fling.
+ base::Optional<cc::TouchAction> scrolling_touch_action_;
// Whitelisted touch action received from the compositor.
base::Optional<cc::TouchAction> white_listed_touch_action_;
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc b/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc
index eadd374e19c..9a5d4a8c41c 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc
@@ -20,175 +20,177 @@ const blink::WebGestureDevice kSourceDevice =
} // namespace
-static void PanTest(cc::TouchAction action,
- float scroll_x,
- float scroll_y,
- float dx,
- float dy,
- float fling_x,
- float fling_y,
- float expected_dx,
- float expected_dy,
- float expected_fling_x,
- float expected_fling_y) {
- TouchActionFilter filter;
- WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
- WebInputEvent::kGestureScrollEnd, kSourceDevice);
-
- {
- // Scrolls with no direction hint are permitted in the |action| direction.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(action);
-
- WebGestureEvent scroll_begin =
- SyntheticWebGestureEventBuilder::BuildScrollBegin(0, 0, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
- FilterGestureEventResult::kFilterGestureEventAllowed);
-
- WebGestureEvent scroll_update =
- SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0,
- kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(expected_dx, scroll_update.data.scroll_update.delta_x);
- EXPECT_EQ(expected_dy, scroll_update.data.scroll_update.delta_y);
-
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- }
-
- {
- // Scrolls biased towards the touch-action axis are permitted.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(action);
- WebGestureEvent scroll_begin =
- SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y,
- kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
- FilterGestureEventResult::kFilterGestureEventAllowed);
-
- WebGestureEvent scroll_update =
- SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0,
- kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(expected_dx, scroll_update.data.scroll_update.delta_x);
- EXPECT_EQ(expected_dy, scroll_update.data.scroll_update.delta_y);
-
- // Ensure that scrolls in the opposite direction are not filtered once
- // scrolling has started. (Once scrolling is started, the direction may
- // be reversed by the user even if scrolls that start in the reversed
- // direction are disallowed.
- WebGestureEvent scroll_update2 =
- SyntheticWebGestureEventBuilder::BuildScrollUpdate(-dx, -dy, 0,
- kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update2),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(-expected_dx, scroll_update2.data.scroll_update.delta_x);
- EXPECT_EQ(-expected_dy, scroll_update2.data.scroll_update.delta_y);
-
- WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
- fling_x, fling_y, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(expected_fling_x, fling_start.data.fling_start.velocity_x);
- EXPECT_EQ(expected_fling_y, fling_start.data.fling_start.velocity_y);
- }
-
- {
- // Scrolls biased towards the perpendicular of the touch-action axis are
- // suppressed entirely.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(action);
- WebGestureEvent scroll_begin =
- SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_y, scroll_x,
- kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
- FilterGestureEventResult::kFilterGestureEventFiltered);
-
- WebGestureEvent scroll_update =
- SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0,
- kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
- FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(dx, scroll_update.data.scroll_update.delta_x);
- EXPECT_EQ(dy, scroll_update.data.scroll_update.delta_y);
+class TouchActionFilterTest : public testing::Test {
+ public:
+ TouchActionFilterTest(){};
+ ~TouchActionFilterTest() override {}
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
- FilterGestureEventResult::kFilterGestureEventFiltered);
+ protected:
+ base::Optional<cc::TouchAction> ScrollingTouchAction() const {
+ return filter_.scrolling_touch_action_;
}
-}
-
-static void PanTestForUnidirectionalTouchAction(cc::TouchAction action,
- float scroll_x,
- float scroll_y) {
- TouchActionFilter filter;
- WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
- WebInputEvent::kGestureScrollEnd, kSourceDevice);
-
- {
- // Scrolls towards the touch-action direction are permitted.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(action);
- WebGestureEvent scroll_begin =
- SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y,
- kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
- FilterGestureEventResult::kFilterGestureEventAllowed);
+ void PanTest(cc::TouchAction action,
+ float scroll_x,
+ float scroll_y,
+ float dx,
+ float dy,
+ float expected_dx,
+ float expected_dy) {
+ WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureScrollEnd, kSourceDevice);
- WebGestureEvent scroll_update =
- SyntheticWebGestureEventBuilder::BuildScrollUpdate(scroll_x, scroll_y,
- 0, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
- FilterGestureEventResult::kFilterGestureEventAllowed);
+ {
+ // Scrolls with no direction hint are permitted in the |action| direction.
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(action);
+
+ WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(0, 0,
+ kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+
+ WebGestureEvent scroll_update =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0,
+ kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(expected_dx, scroll_update.data.scroll_update.delta_x);
+ EXPECT_EQ(expected_dy, scroll_update.data.scroll_update.delta_y);
+
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ }
+
+ {
+ // Scrolls biased towards the touch-action axis are permitted.
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(action);
+ WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y,
+ kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+
+ WebGestureEvent scroll_update =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0,
+ kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(expected_dx, scroll_update.data.scroll_update.delta_x);
+ EXPECT_EQ(expected_dy, scroll_update.data.scroll_update.delta_y);
+
+ // Ensure that scrolls in the opposite direction are not filtered once
+ // scrolling has started. (Once scrolling is started, the direction may
+ // be reversed by the user even if scrolls that start in the reversed
+ // direction are disallowed.
+ WebGestureEvent scroll_update2 =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(-dx, -dy, 0,
+ kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update2),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(-expected_dx, scroll_update2.data.scroll_update.delta_x);
+ EXPECT_EQ(-expected_dy, scroll_update2.data.scroll_update.delta_y);
+
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ }
+
+ {
+ // Scrolls biased towards the perpendicular of the touch-action axis are
+ // suppressed entirely.
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(action);
+ WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_y, scroll_x,
+ kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+
+ WebGestureEvent scroll_update =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0,
+ kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(dx, scroll_update.data.scroll_update.delta_x);
+ EXPECT_EQ(dy, scroll_update.data.scroll_update.delta_y);
+
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ }
}
- {
- // Scrolls towards the exact opposite of the touch-action direction are
- // suppressed entirely.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(action);
- WebGestureEvent scroll_begin =
- SyntheticWebGestureEventBuilder::BuildScrollBegin(-scroll_x, -scroll_y,
- kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
- FilterGestureEventResult::kFilterGestureEventFiltered);
+ void PanTestForUnidirectionalTouchAction(cc::TouchAction action,
+ float scroll_x,
+ float scroll_y) {
+ WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureScrollEnd, kSourceDevice);
- WebGestureEvent scroll_update =
- SyntheticWebGestureEventBuilder::BuildScrollUpdate(-scroll_x, -scroll_y,
- 0, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
- FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
- FilterGestureEventResult::kFilterGestureEventFiltered);
+ {
+ // Scrolls towards the touch-action direction are permitted.
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(action);
+ WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y,
+ kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+
+ WebGestureEvent scroll_update =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(scroll_x, scroll_y,
+ 0, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ }
+
+ {
+ // Scrolls towards the exact opposite of the touch-action direction are
+ // suppressed entirely.
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(action);
+ WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(
+ -scroll_x, -scroll_y, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+
+ WebGestureEvent scroll_update =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(
+ -scroll_x, -scroll_y, 0, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ }
+
+ {
+ // Scrolls towards the diagonal opposite of the touch-action direction are
+ // suppressed entirely.
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(action);
+ WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(
+ -scroll_x - scroll_y, -scroll_x - scroll_y, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+
+ WebGestureEvent scroll_update =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(
+ -scroll_x - scroll_y, -scroll_x - scroll_y, 0, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ }
}
+ TouchActionFilter filter_;
+};
- {
- // Scrolls towards the diagonal opposite of the touch-action direction are
- // suppressed entirely.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(action);
- WebGestureEvent scroll_begin =
- SyntheticWebGestureEventBuilder::BuildScrollBegin(
- -scroll_x - scroll_y, -scroll_x - scroll_y, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
- FilterGestureEventResult::kFilterGestureEventFiltered);
-
- WebGestureEvent scroll_update =
- SyntheticWebGestureEventBuilder::BuildScrollUpdate(
- -scroll_x - scroll_y, -scroll_x - scroll_y, 0, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
- FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
- FilterGestureEventResult::kFilterGestureEventFiltered);
- }
-}
-
-TEST(TouchActionFilterTest, SimpleFilter) {
- TouchActionFilter filter;
-
+TEST_F(TouchActionFilterTest, SimpleFilter) {
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice);
const float kDeltaX = 5;
@@ -201,287 +203,209 @@ TEST(TouchActionFilterTest, SimpleFilter) {
WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureTap, kSourceDevice);
- // No events filtered by default.
- filter.ResetTouchAction();
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x);
- EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- filter.ResetTouchAction();
- EXPECT_EQ(filter.FilterGestureEvent(&tap),
- FilterGestureEventResult::kFilterGestureEventAllowed);
-
// cc::kTouchActionAuto doesn't cause any filtering.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
// cc::kTouchActionNone filters out all scroll events, but no other events.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&tap),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
// When a new touch sequence begins, the state is reset.
- filter.ResetTouchAction();
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
// Setting touch action doesn't impact any in-progress gestures.
- filter.ResetTouchAction();
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
// And the state is still cleared for the next gesture.
- filter.ResetTouchAction();
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
// Changing the touch action during a gesture has no effect.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
}
-TEST(TouchActionFilterTest, Fling) {
- TouchActionFilter filter;
-
- WebGestureEvent scroll_begin =
- SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice);
- WebGestureEvent scroll_update =
- SyntheticWebGestureEventBuilder::BuildScrollUpdate(5, 10, 0,
- kSourceDevice);
- const float kFlingX = 7;
- const float kFlingY = -4;
- WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
- kFlingX, kFlingY, kSourceDevice);
- WebGestureEvent pad_fling = SyntheticWebGestureEventBuilder::BuildFling(
- kFlingX, kFlingY, blink::kWebGestureDeviceTouchpad);
-
- // cc::kTouchActionNone filters out fling events.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
- FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
- FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
- FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(kFlingX, fling_start.data.fling_start.velocity_x);
- EXPECT_EQ(kFlingY, fling_start.data.fling_start.velocity_y);
-
- // touchpad flings aren't filtered.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
- FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
- FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pad_fling),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
- FilterGestureEventResult::kFilterGestureEventFiltered);
-}
-
-TEST(TouchActionFilterTest, PanLeft) {
+TEST_F(TouchActionFilterTest, PanLeft) {
const float kDX = 5;
const float kDY = 10;
const float kScrollX = 7;
const float kScrollY = 6;
- const float kFlingX = 7;
- const float kFlingY = -4;
- PanTest(cc::kTouchActionPanLeft, kScrollX, kScrollY, kDX, kDY, kFlingX,
- kFlingY, kDX, 0, kFlingX, 0);
+ PanTest(cc::kTouchActionPanLeft, kScrollX, kScrollY, kDX, kDY, kDX, 0);
PanTestForUnidirectionalTouchAction(cc::kTouchActionPanLeft, kScrollX, 0);
}
-TEST(TouchActionFilterTest, PanRight) {
+TEST_F(TouchActionFilterTest, PanRight) {
const float kDX = 5;
const float kDY = 10;
const float kScrollX = -7;
const float kScrollY = 6;
- const float kFlingX = 7;
- const float kFlingY = -4;
- PanTest(cc::kTouchActionPanRight, kScrollX, kScrollY, kDX, kDY, kFlingX,
- kFlingY, kDX, 0, kFlingX, 0);
+ PanTest(cc::kTouchActionPanRight, kScrollX, kScrollY, kDX, kDY, kDX, 0);
PanTestForUnidirectionalTouchAction(cc::kTouchActionPanRight, kScrollX, 0);
}
-TEST(TouchActionFilterTest, PanX) {
+TEST_F(TouchActionFilterTest, PanX) {
const float kDX = 5;
const float kDY = 10;
const float kScrollX = 7;
const float kScrollY = 6;
- const float kFlingX = 7;
- const float kFlingY = -4;
- PanTest(cc::kTouchActionPanX, kScrollX, kScrollY, kDX, kDY, kFlingX, kFlingY,
- kDX, 0, kFlingX, 0);
+ PanTest(cc::kTouchActionPanX, kScrollX, kScrollY, kDX, kDY, kDX, 0);
}
-TEST(TouchActionFilterTest, PanUp) {
+TEST_F(TouchActionFilterTest, PanUp) {
const float kDX = 5;
const float kDY = 10;
const float kScrollX = 6;
const float kScrollY = 7;
- const float kFlingX = 7;
- const float kFlingY = -4;
- PanTest(cc::kTouchActionPanUp, kScrollX, kScrollY, kDX, kDY, kFlingX, kFlingY,
- 0, kDY, 0, kFlingY);
+ PanTest(cc::kTouchActionPanUp, kScrollX, kScrollY, kDX, kDY, 0, kDY);
PanTestForUnidirectionalTouchAction(cc::kTouchActionPanUp, 0, kScrollY);
}
-TEST(TouchActionFilterTest, PanDown) {
+TEST_F(TouchActionFilterTest, PanDown) {
const float kDX = 5;
const float kDY = 10;
const float kScrollX = 6;
const float kScrollY = -7;
- const float kFlingX = 7;
- const float kFlingY = -4;
- PanTest(cc::kTouchActionPanDown, kScrollX, kScrollY, kDX, kDY, kFlingX,
- kFlingY, 0, kDY, 0, kFlingY);
+ PanTest(cc::kTouchActionPanDown, kScrollX, kScrollY, kDX, kDY, 0, kDY);
PanTestForUnidirectionalTouchAction(cc::kTouchActionPanDown, 0, kScrollY);
}
-TEST(TouchActionFilterTest, PanY) {
+TEST_F(TouchActionFilterTest, PanY) {
const float kDX = 5;
const float kDY = 10;
const float kScrollX = 6;
const float kScrollY = 7;
- const float kFlingX = 7;
- const float kFlingY = -4;
- PanTest(cc::kTouchActionPanY, kScrollX, kScrollY, kDX, kDY, kFlingX, kFlingY,
- 0, kDY, 0, kFlingY);
+ PanTest(cc::kTouchActionPanY, kScrollX, kScrollY, kDX, kDY, 0, kDY);
}
-TEST(TouchActionFilterTest, PanXY) {
- TouchActionFilter filter;
+TEST_F(TouchActionFilterTest, PanXY) {
const float kDX = 5;
const float kDY = 10;
- const float kFlingX = 7;
- const float kFlingY = -4;
+ WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureScrollEnd, kSourceDevice);
{
// Scrolls hinted in the X axis are permitted and unmodified.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPan);
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionPan);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-7, 6, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0,
kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(kDX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDY, scroll_update.data.scroll_update.delta_y);
- WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
- kFlingX, kFlingY, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(kFlingX, fling_start.data.fling_start.velocity_x);
- EXPECT_EQ(kFlingY, fling_start.data.fling_start.velocity_y);
}
{
// Scrolls hinted in the Y axis are permitted and unmodified.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPan);
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionPan);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0,
kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(kDX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDY, scroll_update.data.scroll_update.delta_y);
- WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
- kFlingX, kFlingY, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(kFlingX, fling_start.data.fling_start.velocity_x);
- EXPECT_EQ(kFlingY, fling_start.data.fling_start.velocity_y);
}
{
// A two-finger gesture is not allowed.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPan);
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionPan);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice,
2);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0,
kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
- WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
- kFlingX, kFlingY, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
}
}
-TEST(TouchActionFilterTest, BitMath) {
+TEST_F(TouchActionFilterTest, BitMath) {
// Verify that the simple flag mixing properties we depend on are now
// trivially true.
EXPECT_EQ(cc::kTouchActionNone, cc::kTouchActionNone & cc::kTouchActionAuto);
@@ -495,9 +419,7 @@ TEST(TouchActionFilterTest, BitMath) {
cc::kTouchActionManipulation | cc::kTouchActionDoubleTapZoom);
}
-TEST(TouchActionFilterTest, MultiTouch) {
- TouchActionFilter filter;
-
+TEST_F(TouchActionFilterTest, MultiTouch) {
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice);
const float kDeltaX = 5;
@@ -509,38 +431,37 @@ TEST(TouchActionFilterTest, MultiTouch) {
WebInputEvent::kGestureScrollEnd, kSourceDevice);
// For multiple points, the intersection is what matters.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionNone);
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
// Intersection of PAN_X and PAN_Y is NONE.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPanX);
- filter.OnSetTouchAction(cc::kTouchActionPanY);
- filter.OnSetTouchAction(cc::kTouchActionPan);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionPanX);
+ filter_.OnSetTouchAction(cc::kTouchActionPanY);
+ filter_.OnSetTouchAction(cc::kTouchActionPan);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
}
class TouchActionFilterPinchTest : public testing::Test {
public:
void RunTest(bool force_enable_zoom) {
- TouchActionFilter filter;
- filter.SetForceEnableZoom(force_enable_zoom);
+ filter_.SetForceEnableZoom(force_enable_zoom);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice,
@@ -556,171 +477,175 @@ class TouchActionFilterPinchTest : public testing::Test {
WebInputEvent::kGestureScrollEnd, kSourceDevice);
// Pinch is allowed with touch-action: auto.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
// Pinch is not allowed with touch-action: none.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
// Pinch is not allowed with touch-action: pan-x pan-y except for force
// enable zoom.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPan);
- EXPECT_NE(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionPan);
+ EXPECT_NE(filter_.FilterGestureEvent(&scroll_begin),
force_enable_zoom
? FilterGestureEventResult::kFilterGestureEventFiltered
: FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_NE(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_NE(filter_.FilterGestureEvent(&pinch_begin),
force_enable_zoom
? FilterGestureEventResult::kFilterGestureEventFiltered
: FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_NE(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_NE(filter_.FilterGestureEvent(&pinch_update),
force_enable_zoom
? FilterGestureEventResult::kFilterGestureEventFiltered
: FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_NE(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_NE(filter_.FilterGestureEvent(&pinch_end),
force_enable_zoom
? FilterGestureEventResult::kFilterGestureEventFiltered
: FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_NE(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_NE(filter_.FilterGestureEvent(&scroll_end),
force_enable_zoom
? FilterGestureEventResult::kFilterGestureEventFiltered
: FilterGestureEventResult::kFilterGestureEventAllowed);
// Pinch is allowed with touch-action: manipulation.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionManipulation);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionManipulation);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
// Pinch state is automatically reset at the end of a scroll.
- filter.ResetTouchAction();
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
// Pinching is only computed at GestureScrollBegin time.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
// Once a pinch has started, any change in state won't affect the pinch
// gestures since it is computed in GestureScrollBegin.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
// Scrolling is allowed when two fingers are down.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPinchZoom);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionPinchZoom);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
// A pinch event sequence with only one pointer is equivalent to a scroll
// gesture, so disallowed as a pinch gesture.
scroll_begin.data.scroll_begin.pointer_count = 1;
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPinchZoom);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionPinchZoom);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
}
+
+ private:
+ TouchActionFilter filter_;
};
TEST_F(TouchActionFilterPinchTest, Pinch) {
@@ -733,9 +658,7 @@ TEST_F(TouchActionFilterPinchTest, ForceEnableZoom) {
RunTest(true);
}
-TEST(TouchActionFilterTest, DoubleTapWithTouchActionAuto) {
- TouchActionFilter filter;
-
+TEST_F(TouchActionFilterTest, DoubleTapWithTouchActionAuto) {
WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent unconfirmed_tap = SyntheticWebGestureEventBuilder::Build(
@@ -746,28 +669,27 @@ TEST(TouchActionFilterTest, DoubleTapWithTouchActionAuto) {
WebInputEvent::kGestureDoubleTap, kSourceDevice);
// Double tap is allowed with touch action auto.
- filter.ResetTouchAction();
- EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&unconfirmed_tap),
+ EXPECT_EQ(filter_.FilterGestureEvent(&unconfirmed_tap),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(unconfirmed_tap.GetType(), WebInputEvent::kGestureTapUnconfirmed);
// The tap cancel will come as part of the next touch sequence.
- filter.ResetTouchAction();
+ filter_.ResetTouchAction();
// Changing the touch action for the second tap doesn't effect the behaviour
// of the event.
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&tap_cancel),
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&double_tap),
+ EXPECT_EQ(filter_.FilterGestureEvent(&double_tap),
FilterGestureEventResult::kFilterGestureEventAllowed);
}
-TEST(TouchActionFilterTest, DoubleTap) {
- TouchActionFilter filter;
-
+TEST_F(TouchActionFilterTest, DoubleTap) {
WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent unconfirmed_tap = SyntheticWebGestureEventBuilder::Build(
@@ -778,29 +700,27 @@ TEST(TouchActionFilterTest, DoubleTap) {
WebInputEvent::kGestureDoubleTap, kSourceDevice);
// Double tap is disabled with any touch action other than auto.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionManipulation);
- EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionManipulation);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&unconfirmed_tap),
+ EXPECT_EQ(filter_.FilterGestureEvent(&unconfirmed_tap),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(WebInputEvent::kGestureTap, unconfirmed_tap.GetType());
// Changing the touch action for the second tap doesn't effect the behaviour
// of the event. The tap cancel will come as part of the next touch sequence.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_EQ(filter.FilterGestureEvent(&tap_cancel),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&double_tap),
+ EXPECT_EQ(filter_.FilterGestureEvent(&double_tap),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(WebInputEvent::kGestureTap, double_tap.GetType());
}
-TEST(TouchActionFilterTest, SingleTapWithTouchActionAuto) {
- TouchActionFilter filter;
-
+TEST_F(TouchActionFilterTest, SingleTapWithTouchActionAuto) {
WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent unconfirmed_tap1 = SyntheticWebGestureEventBuilder::Build(
@@ -809,19 +729,18 @@ TEST(TouchActionFilterTest, SingleTapWithTouchActionAuto) {
WebInputEvent::kGestureTap, kSourceDevice);
// Single tap is allowed with touch action auto.
- filter.ResetTouchAction();
- EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&unconfirmed_tap1),
+ EXPECT_EQ(filter_.FilterGestureEvent(&unconfirmed_tap1),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(WebInputEvent::kGestureTapUnconfirmed, unconfirmed_tap1.GetType());
- EXPECT_EQ(filter.FilterGestureEvent(&tap),
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap),
FilterGestureEventResult::kFilterGestureEventAllowed);
}
-TEST(TouchActionFilterTest, SingleTap) {
- TouchActionFilter filter;
-
+TEST_F(TouchActionFilterTest, SingleTap) {
WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent unconfirmed_tap1 = SyntheticWebGestureEventBuilder::Build(
@@ -830,20 +749,20 @@ TEST(TouchActionFilterTest, SingleTap) {
WebInputEvent::kGestureTap, kSourceDevice);
// With touch action other than auto, tap unconfirmed is turned into tap.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&unconfirmed_tap1),
+ EXPECT_EQ(filter_.FilterGestureEvent(&unconfirmed_tap1),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(WebInputEvent::kGestureTap, unconfirmed_tap1.GetType());
- EXPECT_EQ(filter.FilterGestureEvent(&tap),
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap),
FilterGestureEventResult::kFilterGestureEventFiltered);
}
-TEST(TouchActionFilterTest, TouchActionResetsOnResetTouchAction) {
- TouchActionFilter filter;
-
+TEST_F(TouchActionFilterTest, TouchActionResetsOnResetTouchAction) {
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureTap, kSourceDevice);
WebGestureEvent scroll_begin =
@@ -851,26 +770,27 @@ TEST(TouchActionFilterTest, TouchActionResetsOnResetTouchAction) {
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureScrollEnd, kSourceDevice);
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&tap),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap),
FilterGestureEventResult::kFilterGestureEventAllowed);
- filter.ResetTouchAction();
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
}
-TEST(TouchActionFilterTest, TouchActionResetMidSequence) {
- TouchActionFilter filter;
-
+TEST_F(TouchActionFilterTest, TouchActionResetMidSequence) {
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice);
WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build(
@@ -883,95 +803,104 @@ TEST(TouchActionFilterTest, TouchActionResetMidSequence) {
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureScrollEnd, kSourceDevice);
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
// Even though the allowed action is auto after the reset, the remaining
// scroll and pinch events should be suppressed.
- filter.ResetTouchAction();
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
// A new scroll and pinch sequence should be allowed.
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
// Resetting from auto to auto mid-stream should have no effect.
- filter.ResetTouchAction();
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
}
-TEST(TouchActionFilterTest, ZeroVelocityFlingsConvertedToScrollEnd) {
- TouchActionFilter filter;
- const float kFlingX = 7;
- const float kFlingY = -4;
+// This test makes sure that we do not reset scrolling touch action in the
+// middle of a gesture sequence.
+TEST_F(TouchActionFilterTest, TouchActionNotResetWithinGestureSequence) {
+ filter_.OnHasTouchEventHandlers(true);
+ EXPECT_FALSE(filter_.allowed_touch_action().has_value());
+ filter_.OnSetTouchAction(cc::kTouchActionPanY);
- {
- // Scrolls hinted mostly in the Y axis will suppress flings with a
- // component solely on the X axis, converting them to a GestureScrollEnd.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPanY);
- WebGestureEvent scroll_begin =
- SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
- FilterGestureEventResult::kFilterGestureEventAllowed);
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
+ WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(1, 3, kSourceDevice);
+ WebGestureEvent scroll_update =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(1, 5, 0,
+ kSourceDevice);
+ WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureScrollEnd, kSourceDevice);
- WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
- kFlingX, 0, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(WebInputEvent::kGestureScrollEnd, fling_start.GetType());
- }
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(cc::kTouchActionPanY, ScrollingTouchAction().value());
- filter.ResetTouchAction();
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ // Simulate a touch sequence end by calling ReportAndResetTouchAction.
+ filter_.ReportAndResetTouchAction();
+ EXPECT_FALSE(filter_.allowed_touch_action().has_value());
+ EXPECT_EQ(cc::kTouchActionPanY, ScrollingTouchAction().value());
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ // The |allowed_touch_action_| should have been reset, but not the
+ // |scrolling_touch_action_|.
+ EXPECT_FALSE(filter_.allowed_touch_action().has_value());
+ EXPECT_EQ(cc::kTouchActionPanY, ScrollingTouchAction().value());
- {
- // Scrolls hinted mostly in the X axis will suppress flings with a
- // component solely on the Y axis, converting them to a GestureScrollEnd.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPanX);
- WebGestureEvent scroll_begin =
- SyntheticWebGestureEventBuilder::BuildScrollBegin(-7, 6, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
- FilterGestureEventResult::kFilterGestureEventAllowed);
+ // In the fling boosting case, we won't get a TapDown after the previous GSE.
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
- WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
- 0, kFlingY, kSourceDevice);
- EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
- FilterGestureEventResult::kFilterGestureEventAllowed);
- EXPECT_EQ(WebInputEvent::kGestureScrollEnd, fling_start.GetType());
- }
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_TRUE(filter_.allowed_touch_action().has_value());
+ EXPECT_TRUE(ScrollingTouchAction().has_value());
}
-TEST(TouchActionFilterTest, TouchpadScroll) {
- TouchActionFilter filter;
-
+TEST_F(TouchActionFilterTest, TouchpadScroll) {
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(
2, 3, blink::kWebGestureDeviceTouchpad);
// cc::kTouchActionNone filters out only touchscreen scroll events.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ filter_.ResetTouchAction();
+ filter_.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
}
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.cc b/chromium/content/browser/renderer_host/input/touch_emulator.cc
index e8aa3c16478..bb6fb67ff9f 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.cc
@@ -439,6 +439,10 @@ void TouchEmulator::OnGestureEvent(const ui::GestureEventData& gesture) {
}
}
+bool TouchEmulator::RequiresDoubleTapGestureEvents() const {
+ return true;
+}
+
void TouchEmulator::InjectTouchEvent(const blink::WebTouchEvent& event,
RenderWidgetHostViewBase* target_view,
base::OnceClosure callback) {
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.h b/chromium/content/browser/renderer_host/input/touch_emulator.h
index c419968b6ef..3ff06e2158b 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.h
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.h
@@ -88,6 +88,7 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
private:
// ui::GestureProviderClient implementation.
void OnGestureEvent(const ui::GestureEventData& gesture) override;
+ bool RequiresDoubleTapGestureEvents() const override;
// Returns cursor size in DIP.
gfx::SizeF InitCursorFromResource(
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
index 746afa48833..3b7ecd5a70f 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
@@ -130,8 +130,7 @@ TouchSelectionControllerClientAura::TouchSelectionControllerClientAura(
FROM_HERE,
base::TimeDelta::FromMilliseconds(kQuickMenuDelayInMs),
base::Bind(&TouchSelectionControllerClientAura::ShowQuickMenu,
- base::Unretained(this)),
- false),
+ base::Unretained(this))),
quick_menu_requested_(false),
touch_down_(false),
scroll_in_progress_(false),
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
index 791ee5a4d32..a18886536d5 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
@@ -125,7 +125,7 @@ class CONTENT_EXPORT TouchSelectionControllerClientAura
base::ObserverList<TouchSelectionControllerClientManager::Observer>
observers_;
- base::Timer quick_menu_timer_;
+ base::RetainingOneShotTimer quick_menu_timer_;
bool quick_menu_requested_;
bool touch_down_;
bool scroll_in_progress_;
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 c6ee3bdf7c2..d8350f38862 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
@@ -19,6 +19,7 @@
#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/hit_test_region_observer.h"
#include "content/public/test/scoped_overscroll_modes.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
@@ -422,7 +423,7 @@ IN_PROC_BROWSER_TEST_P(TouchSelectionControllerClientAuraSiteIsolationTest,
// The child will change with the cross-site navigation. It shouldn't change
// after this.
child = root->child_at(0);
- WaitForChildFrameSurfaceReady(child->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
RenderWidgetHostViewChildFrame* child_view =
static_cast<RenderWidgetHostViewChildFrame*>(
@@ -529,7 +530,7 @@ IN_PROC_BROWSER_TEST_P(TouchSelectionControllerClientAuraSiteIsolationTest,
// The child will change with the cross-site navigation. It shouldn't change
// after this.
child = root->child_at(0);
- WaitForChildFrameSurfaceReady(child->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
RenderWidgetHostViewChildFrame* child_view =
static_cast<RenderWidgetHostViewChildFrame*>(
@@ -1049,6 +1050,13 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraScaleFactorTest,
gfx::PointF point;
ASSERT_TRUE(GetPointInsideTextfield(&point));
+
+ ui::GestureEventDetails gesture_tap_down_details(ui::ET_GESTURE_TAP_DOWN);
+ gesture_tap_down_details.set_device_type(
+ ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent gesture_tap_down(2, 2, 0, ui::EventTimeForNow(),
+ gesture_tap_down_details);
+ rwhva->OnGestureEvent(&gesture_tap_down);
ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
tap_details.set_tap_count(1);
diff --git a/chromium/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc b/chromium/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
new file mode 100644
index 00000000000..7111ab6ae9c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
@@ -0,0 +1,187 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/run_loop.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/public/browser/web_contents.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"
+
+namespace {
+
+const char kTouchpadPinchDataURL[] =
+ "data:text/html;charset=utf-8,"
+ "<!DOCTYPE html>"
+ "<style>"
+ "html,body {"
+ " height: 100%;"
+ "}"
+ "</style>"
+ "<p>Hello.</p>"
+ "<script>"
+ " var resolveHandlerPromise = null;"
+ " var handlerPromise = new Promise(function(resolve) {"
+ " resolveHandlerPromise = resolve;"
+ " });"
+ " function preventPinchListener(e) {"
+ " e.preventDefault();"
+ " resolveHandlerPromise(e);"
+ " }"
+ " function allowPinchListener(e) {"
+ " resolveHandlerPromise(e);"
+ " }"
+ " function setListener(prevent) {"
+ " document.body.addEventListener("
+ " 'wheel',"
+ " (prevent ? preventPinchListener : allowPinchListener),"
+ " {passive: false});"
+ " }"
+ " function reset() {"
+ " document.body.removeEventListener("
+ " 'wheel', preventPinchListener, {passive: false});"
+ " document.body.removeEventListener("
+ " 'wheel', allowPinchListener, {passive: false});"
+ " handlerPromise = new Promise(function(resolve) {"
+ " resolveHandlerPromise = resolve;"
+ " });"
+ " }"
+ "</script>";
+
+} // namespace
+
+namespace content {
+
+class TouchpadPinchBrowserTest : public ContentBrowserTest {
+ public:
+ TouchpadPinchBrowserTest() = default;
+ ~TouchpadPinchBrowserTest() override = default;
+
+ protected:
+ void LoadURL() {
+ const GURL data_url(kTouchpadPinchDataURL);
+ NavigateToURL(shell(), data_url);
+ SynchronizeThreads();
+ }
+
+ RenderWidgetHostImpl* GetRenderWidgetHost() {
+ return RenderWidgetHostImpl::From(shell()
+ ->web_contents()
+ ->GetRenderWidgetHostView()
+ ->GetRenderWidgetHost());
+ }
+
+ void SynchronizeThreads() {
+ MainThreadFrameObserver observer(GetRenderWidgetHost());
+ observer.Wait();
+ }
+};
+
+// Performing a touchpad pinch gesture should change the page scale.
+IN_PROC_BROWSER_TEST_F(TouchpadPinchBrowserTest,
+ TouchpadPinchChangesPageScale) {
+ LoadURL();
+
+ content::TestPageScaleObserver scale_observer(shell()->web_contents());
+
+ const gfx::Rect contents_rect = shell()->web_contents()->GetContainerBounds();
+ const gfx::Point pinch_position(contents_rect.width() / 2,
+ contents_rect.height() / 2);
+ SimulateGesturePinchSequence(shell()->web_contents(), pinch_position, 1.23,
+ blink::kWebGestureDeviceTouchpad);
+
+ scale_observer.WaitForPageScaleUpdate();
+}
+
+// We should offer synthetic wheel events to the page when a touchpad pinch
+// is performed.
+IN_PROC_BROWSER_TEST_F(TouchpadPinchBrowserTest, WheelListenerAllowingPinch) {
+ LoadURL();
+ ASSERT_TRUE(
+ content::ExecuteScript(shell()->web_contents(), "setListener(false);"));
+ SynchronizeThreads();
+
+ content::TestPageScaleObserver scale_observer(shell()->web_contents());
+
+ const gfx::Rect contents_rect = shell()->web_contents()->GetContainerBounds();
+ const gfx::Point pinch_position(contents_rect.width() / 2,
+ contents_rect.height() / 2);
+ SimulateGesturePinchSequence(shell()->web_contents(), pinch_position, 1.23,
+ blink::kWebGestureDeviceTouchpad);
+
+ // Ensure that the page saw the synthetic wheel.
+ bool default_prevented = false;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ shell()->web_contents(),
+ "handlerPromise.then(function(e) {"
+ " window.domAutomationController.send(e.defaultPrevented);"
+ "});",
+ &default_prevented));
+ EXPECT_FALSE(default_prevented);
+
+ // Since the listener did not cancel the synthetic wheel, we should still
+ // change the page scale.
+ scale_observer.WaitForPageScaleUpdate();
+}
+
+// If the synthetic wheel event for a touchpad pinch is canceled, we should not
+// change the page scale.
+IN_PROC_BROWSER_TEST_F(TouchpadPinchBrowserTest, WheelListenerPreventingPinch) {
+ LoadURL();
+
+ // Perform an initial pinch so we can figure out the page scale we're
+ // starting with for the test proper.
+ content::TestPageScaleObserver starting_scale_observer(
+ shell()->web_contents());
+ const gfx::Rect contents_rect = shell()->web_contents()->GetContainerBounds();
+ const gfx::Point pinch_position(contents_rect.width() / 2,
+ contents_rect.height() / 2);
+ SimulateGesturePinchSequence(shell()->web_contents(), pinch_position, 1.23,
+ blink::kWebGestureDeviceTouchpad);
+ const float starting_scale_factor =
+ starting_scale_observer.WaitForPageScaleUpdate();
+ ASSERT_GT(starting_scale_factor, 0.f);
+
+ ASSERT_TRUE(
+ content::ExecuteScript(shell()->web_contents(), "setListener(true);"));
+ SynchronizeThreads();
+
+ SimulateGesturePinchSequence(shell()->web_contents(), pinch_position, 1.5,
+ blink::kWebGestureDeviceTouchpad);
+
+ // Ensure the page handled a wheel event that it was able to cancel.
+ bool default_prevented = false;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ shell()->web_contents(),
+ "handlerPromise.then(function(e) {"
+ " window.domAutomationController.send(e.defaultPrevented);"
+ "});",
+ &default_prevented));
+ EXPECT_TRUE(default_prevented);
+
+ // We'll check that the previous pinch did not cause a scale change by
+ // performing another pinch that does change the scale.
+ ASSERT_TRUE(content::ExecuteScript(shell()->web_contents(),
+ "reset(); "
+ "setListener(false);"));
+ SynchronizeThreads();
+
+ content::TestPageScaleObserver scale_observer(shell()->web_contents());
+ SimulateGesturePinchSequence(shell()->web_contents(), pinch_position, 2.0,
+ blink::kWebGestureDeviceTouchpad);
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ shell()->web_contents(),
+ "handlerPromise.then(function(e) {"
+ " window.domAutomationController.send(e.defaultPrevented);"
+ "});",
+ &default_prevented));
+ EXPECT_FALSE(default_prevented);
+
+ const float last_scale_factor = scale_observer.WaitForPageScaleUpdate();
+ EXPECT_FLOAT_EQ(starting_scale_factor * 2.0, last_scale_factor);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.cc b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.cc
new file mode 100644
index 00000000000..f0279ae7225
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.cc
@@ -0,0 +1,161 @@
+// Copyright 2018 The Chromium Authors. All rights 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/touchpad_pinch_event_queue.h"
+
+#include "base/trace_event/trace_event.h"
+#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/blink/blink_event_util.h"
+#include "ui/latency/latency_info.h"
+
+namespace content {
+
+namespace {
+
+blink::WebMouseWheelEvent CreateSyntheticWheelFromTouchpadPinchEvent(
+ const blink::WebGestureEvent& pinch_event) {
+ DCHECK_EQ(blink::WebInputEvent::kGesturePinchUpdate, pinch_event.GetType());
+
+ // For pinch gesture events, similar to ctrl+wheel zooming, allow content to
+ // prevent the browser from zooming by sending fake wheel events with the ctrl
+ // modifier set when we see trackpad pinch gestures. Ideally we'd someday get
+ // a platform 'pinch' event and send that instead.
+ blink::WebMouseWheelEvent wheel_event(
+ blink::WebInputEvent::kMouseWheel,
+ pinch_event.GetModifiers() | blink::WebInputEvent::kControlKey,
+ pinch_event.TimeStamp());
+ wheel_event.SetPositionInWidget(pinch_event.PositionInWidget());
+ wheel_event.SetPositionInScreen(pinch_event.PositionInScreen());
+ wheel_event.delta_x = 0;
+
+ // The function to convert scales to deltaY values is designed to be
+ // compatible with websites existing use of wheel events, and with existing
+ // Windows trackpad behavior. In particular, we want:
+ // - deltas should accumulate via addition: f(s1*s2)==f(s1)+f(s2)
+ // - deltas should invert via negation: f(1/s) == -f(s)
+ // - zoom in should be positive: f(s) > 0 iff s > 1
+ // - magnitude roughly matches wheels: f(2) > 25 && f(2) < 100
+ // - a formula that's relatively easy to use from JavaScript
+ // Note that 'wheel' event deltaY values have their sign inverted. So to
+ // convert a wheel deltaY back to a scale use Math.exp(-deltaY/100).
+ DCHECK_GT(pinch_event.data.pinch_update.scale, 0);
+ wheel_event.delta_y = 100.0f * log(pinch_event.data.pinch_update.scale);
+ wheel_event.has_precise_scrolling_deltas = true;
+ wheel_event.wheel_ticks_x = 0;
+ wheel_event.wheel_ticks_y = pinch_event.data.pinch_update.scale > 1 ? 1 : -1;
+
+ return wheel_event;
+}
+
+} // namespace
+
+// This is a single queued pinch event to which we add trace events.
+class QueuedTouchpadPinchEvent : public GestureEventWithLatencyInfo {
+ public:
+ QueuedTouchpadPinchEvent(const GestureEventWithLatencyInfo& original_event)
+ : GestureEventWithLatencyInfo(original_event) {
+ TRACE_EVENT_ASYNC_BEGIN0("input", "TouchpadPinchEventQueue::QueueEvent",
+ this);
+ }
+
+ ~QueuedTouchpadPinchEvent() {
+ TRACE_EVENT_ASYNC_END0("input", "TouchpadPinchEventQueue::QueueEvent",
+ this);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QueuedTouchpadPinchEvent);
+};
+
+TouchpadPinchEventQueue::TouchpadPinchEventQueue(
+ TouchpadPinchEventQueueClient* client)
+ : client_(client) {
+ DCHECK(client_);
+}
+
+TouchpadPinchEventQueue::~TouchpadPinchEventQueue() = default;
+
+void TouchpadPinchEventQueue::QueueEvent(
+ const GestureEventWithLatencyInfo& event) {
+ TRACE_EVENT0("input", "TouchpadPinchEventQueue::QueueEvent");
+
+ if (!pinch_queue_.empty()) {
+ QueuedTouchpadPinchEvent* last_event = pinch_queue_.back().get();
+ if (last_event->CanCoalesceWith(event)) {
+ // Terminate the LatencyInfo of the event before it gets coalesced away.
+ event.latency.Terminate();
+
+ last_event->CoalesceWith(event);
+ DCHECK_EQ(blink::WebInputEvent::kGesturePinchUpdate,
+ last_event->event.GetType());
+ TRACE_EVENT_INSTANT1("input",
+ "TouchpadPinchEventQueue::CoalescedPinchEvent",
+ TRACE_EVENT_SCOPE_THREAD, "scale",
+ last_event->event.data.pinch_update.scale);
+ return;
+ }
+ }
+
+ pinch_queue_.push_back(std::make_unique<QueuedTouchpadPinchEvent>(event));
+ TryForwardNextEventToRenderer();
+}
+
+void TouchpadPinchEventQueue::ProcessMouseWheelAck(
+ InputEventAckSource ack_source,
+ InputEventAckState ack_result,
+ const ui::LatencyInfo& latency_info) {
+ TRACE_EVENT0("input", "TouchpadPinchEventQueue::ProcessMouseWheelAck");
+ if (!pinch_event_awaiting_ack_)
+ return;
+
+ pinch_event_awaiting_ack_->latency.AddNewLatencyFrom(latency_info);
+ client_->OnGestureEventForPinchAck(*pinch_event_awaiting_ack_, ack_source,
+ ack_result);
+
+ pinch_event_awaiting_ack_.reset();
+ TryForwardNextEventToRenderer();
+}
+
+void TouchpadPinchEventQueue::TryForwardNextEventToRenderer() {
+ TRACE_EVENT0("input",
+ "TouchpadPinchEventQueue::TryForwardNextEventToRenderer");
+
+ if (pinch_queue_.empty() || pinch_event_awaiting_ack_)
+ return;
+
+ pinch_event_awaiting_ack_ = std::move(pinch_queue_.front());
+ pinch_queue_.pop_front();
+
+ if (pinch_event_awaiting_ack_->event.GetType() ==
+ blink::WebInputEvent::kGesturePinchBegin ||
+ pinch_event_awaiting_ack_->event.GetType() ==
+ blink::WebInputEvent::kGesturePinchEnd) {
+ // Wheel event listeners are given individual events with no phase
+ // information, so we don't need to do anything at the beginning or
+ // end of a pinch.
+ // TODO(565980): Consider sending the rest of the wheel events as
+ // non-blocking if the first wheel event of the pinch sequence is not
+ // consumed.
+ client_->OnGestureEventForPinchAck(*pinch_event_awaiting_ack_,
+ InputEventAckSource::BROWSER,
+ INPUT_EVENT_ACK_STATE_IGNORED);
+ pinch_event_awaiting_ack_.reset();
+ TryForwardNextEventToRenderer();
+ return;
+ }
+
+ const MouseWheelEventWithLatencyInfo synthetic_wheel(
+ CreateSyntheticWheelFromTouchpadPinchEvent(
+ pinch_event_awaiting_ack_->event),
+ pinch_event_awaiting_ack_->latency);
+
+ client_->SendMouseWheelEventForPinchImmediately(synthetic_wheel);
+}
+
+bool TouchpadPinchEventQueue::has_pending() const {
+ return !pinch_queue_.empty() || pinch_event_awaiting_ack_;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.h b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.h
new file mode 100644
index 00000000000..f7def2c8636
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue.h
@@ -0,0 +1,76 @@
+// Copyright 2018 The Chromium Authors. All 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_TOUCHPAD_PINCH_EVENT_QUEUE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCHPAD_PINCH_EVENT_QUEUE_H_
+
+#include <memory>
+
+#include "base/containers/circular_deque.h"
+#include "content/common/content_export.h"
+#include "content/common/input/event_with_latency_info.h"
+#include "content/public/common/input_event_ack_source.h"
+#include "content/public/common/input_event_ack_state.h"
+#include "third_party/blink/public/platform/web_input_event.h"
+
+namespace ui {
+class LatencyInfo;
+} // namespace ui
+
+namespace content {
+
+class QueuedTouchpadPinchEvent;
+
+// Interface with which TouchpadPinchEventQueue can forward synthetic mouse
+// wheel events and notify of pinch events.
+class CONTENT_EXPORT TouchpadPinchEventQueueClient {
+ public:
+ virtual ~TouchpadPinchEventQueueClient() = default;
+
+ virtual void SendMouseWheelEventForPinchImmediately(
+ const MouseWheelEventWithLatencyInfo& event) = 0;
+ virtual void OnGestureEventForPinchAck(
+ const GestureEventWithLatencyInfo& event,
+ InputEventAckSource ack_source,
+ InputEventAckState ack_result) = 0;
+};
+
+// A queue for sending synthetic mouse wheel events for touchpad pinches.
+// In order for a page to prevent touchpad pinch zooming, we send synthetic
+// wheel events which may be cancelled. Once we've determined whether a page
+// has prevented the pinch, the TouchpadPinchEventQueueClient may proceed with
+// handling the pinch.
+// See README.md for further details.
+class CONTENT_EXPORT TouchpadPinchEventQueue {
+ public:
+ // The |client| must outlive the TouchpadPinchEventQueue.
+ TouchpadPinchEventQueue(TouchpadPinchEventQueueClient* client);
+ ~TouchpadPinchEventQueue();
+
+ // Adds the given touchpad pinch |event| to the queue. The event may be
+ // coalesced with previously queued events.
+ void QueueEvent(const GestureEventWithLatencyInfo& event);
+
+ // Notifies the queue that a synthetic mouse wheel event has been processed
+ // by the renderer.
+ void ProcessMouseWheelAck(InputEventAckSource ack_source,
+ InputEventAckState ack_result,
+ const ui::LatencyInfo& latency_info);
+
+ bool has_pending() const WARN_UNUSED_RESULT;
+
+ private:
+ void TryForwardNextEventToRenderer();
+
+ TouchpadPinchEventQueueClient* client_;
+
+ base::circular_deque<std::unique_ptr<QueuedTouchpadPinchEvent>> pinch_queue_;
+ std::unique_ptr<QueuedTouchpadPinchEvent> pinch_event_awaiting_ack_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchpadPinchEventQueue);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCHPAD_PINCH_EVENT_QUEUE_H_
diff --git a/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue_unittest.cc
new file mode 100644
index 00000000000..73c6424a06e
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touchpad_pinch_event_queue_unittest.cc
@@ -0,0 +1,350 @@
+// Copyright 2018 The Chromium Authors. All rights 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/touchpad_pinch_event_queue.h"
+
+#include <string>
+
+#include "content/common/input/event_with_latency_info.h"
+#include "content/public/common/input_event_ack_source.h"
+#include "content/public/common/input_event_ack_state.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/latency/latency_info.h"
+
+namespace content {
+
+class MockTouchpadPinchEventQueueClient : public TouchpadPinchEventQueueClient {
+ public:
+ MockTouchpadPinchEventQueueClient() = default;
+ ~MockTouchpadPinchEventQueueClient() override = default;
+
+ // TouchpadPinchEventQueueClient
+ MOCK_METHOD1(SendMouseWheelEventForPinchImmediately,
+ void(const MouseWheelEventWithLatencyInfo& event));
+ MOCK_METHOD3(OnGestureEventForPinchAck,
+ void(const GestureEventWithLatencyInfo& event,
+ InputEventAckSource ack_source,
+ InputEventAckState ack_result));
+};
+
+class TouchpadPinchEventQueueTest : public ::testing::Test {
+ protected:
+ TouchpadPinchEventQueueTest() : queue_(&mock_client_) {}
+ ~TouchpadPinchEventQueueTest() = default;
+
+ void QueueEvent(const blink::WebGestureEvent& event) {
+ queue_.QueueEvent(GestureEventWithLatencyInfo(event));
+ }
+
+ void QueuePinchBegin() {
+ blink::WebGestureEvent event(
+ blink::WebInputEvent::kGesturePinchBegin,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests(),
+ blink::kWebGestureDeviceTouchpad);
+ event.SetPositionInWidget(gfx::PointF(1, 1));
+ event.SetPositionInScreen(gfx::PointF(1, 1));
+ event.SetNeedsWheelEvent(true);
+ QueueEvent(event);
+ }
+
+ void QueuePinchEnd() {
+ blink::WebGestureEvent event(
+ blink::WebInputEvent::kGesturePinchEnd,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests(),
+ blink::kWebGestureDeviceTouchpad);
+ event.SetPositionInWidget(gfx::PointF(1, 1));
+ event.SetPositionInScreen(gfx::PointF(1, 1));
+ event.SetNeedsWheelEvent(true);
+ QueueEvent(event);
+ }
+
+ void QueuePinchUpdate(float scale, bool zoom_disabled) {
+ blink::WebGestureEvent event(
+ blink::WebInputEvent::kGesturePinchUpdate,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests(),
+ blink::kWebGestureDeviceTouchpad);
+ event.SetPositionInWidget(gfx::PointF(1, 1));
+ event.SetPositionInScreen(gfx::PointF(1, 1));
+ event.SetNeedsWheelEvent(true);
+ event.data.pinch_update.zoom_disabled = zoom_disabled;
+ event.data.pinch_update.scale = scale;
+ QueueEvent(event);
+ }
+
+ void SendWheelEventAck(InputEventAckSource ack_source,
+ InputEventAckState ack_result) {
+ queue_.ProcessMouseWheelAck(ack_source, ack_result, ui::LatencyInfo());
+ }
+
+ testing::StrictMock<MockTouchpadPinchEventQueueClient> mock_client_;
+ TouchpadPinchEventQueue queue_;
+};
+
+MATCHER_P(EventHasType,
+ type,
+ std::string(negation ? "does not have" : "has") + " type " +
+ ::testing::PrintToString(type)) {
+ return arg.event.GetType() == type;
+}
+
+MATCHER(EventHasCtrlModifier,
+ std::string(negation ? "does not have" : "has") + " control modifier") {
+ return (arg.event.GetModifiers() & blink::WebInputEvent::kControlKey) != 0;
+}
+
+MATCHER(EventIsBlocking,
+ std::string(negation ? "is not" : "is") + " blocking") {
+ return arg.event.dispatch_type == blink::WebInputEvent::kBlocking;
+}
+
+// Ensure that when the queue receives a touchpad pinch sequence, it sends a
+// synthetic mouse wheel event and acks the pinch events back to the client.
+TEST_F(TouchpadPinchEventQueueTest, Basic) {
+ ::testing::InSequence sequence;
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchBegin),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(
+ ::testing::AllOf(EventHasCtrlModifier(), EventIsBlocking())));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchEnd),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+
+ QueuePinchBegin();
+ QueuePinchUpdate(1.23, false);
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ QueuePinchEnd();
+}
+
+// Ensure that if the renderer consumes the synthetic wheel event, the ack of
+// the GesturePinchUpdate reflects this.
+TEST_F(TouchpadPinchEventQueueTest, Consumed) {
+ ::testing::InSequence sequence;
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchBegin),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(
+ ::testing::AllOf(EventHasCtrlModifier(), EventIsBlocking())));
+ EXPECT_CALL(
+ mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::MAIN_THREAD, INPUT_EVENT_ACK_STATE_CONSUMED));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchEnd),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+
+ QueuePinchBegin();
+ QueuePinchUpdate(1.23, false);
+ SendWheelEventAck(InputEventAckSource::MAIN_THREAD,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ QueuePinchEnd();
+}
+
+// Ensure that the queue sends wheel events for updates with |zoom_disabled| as
+// well.
+TEST_F(TouchpadPinchEventQueueTest, ZoomDisabled) {
+ ::testing::InSequence sequence;
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchBegin),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(
+ ::testing::AllOf(EventHasCtrlModifier(), EventIsBlocking())));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchEnd),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+
+ QueuePinchBegin();
+ QueuePinchUpdate(1.23, true);
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ QueuePinchEnd();
+}
+
+TEST_F(TouchpadPinchEventQueueTest, MultipleSequences) {
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchBegin),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED))
+ .Times(2);
+ EXPECT_CALL(mock_client_, SendMouseWheelEventForPinchImmediately(testing::_))
+ .Times(2);
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS))
+ .Times(2);
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchEnd),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED))
+ .Times(2);
+
+ QueuePinchBegin();
+ QueuePinchUpdate(1.23, false);
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ QueuePinchEnd();
+
+ QueuePinchBegin();
+ QueuePinchUpdate(1.23, false);
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ QueuePinchEnd();
+}
+
+// Ensure we can queue additional pinch event sequences while the queue is
+// waiting for a wheel event ack.
+TEST_F(TouchpadPinchEventQueueTest, MultipleQueuedSequences) {
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchBegin),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ EXPECT_CALL(mock_client_, SendMouseWheelEventForPinchImmediately(testing::_));
+ QueuePinchBegin();
+ QueuePinchUpdate(1.23, false);
+
+ testing::Mock::VerifyAndClearExpectations(&mock_client_);
+
+ QueuePinchEnd();
+
+ QueuePinchBegin();
+ QueuePinchUpdate(1.23, false);
+ QueuePinchEnd();
+
+ // No calls since we're still waiting on the ack for the first wheel event.
+ testing::Mock::VerifyAndClearExpectations(&mock_client_);
+
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchEnd),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchBegin),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ EXPECT_CALL(mock_client_, SendMouseWheelEventForPinchImmediately(testing::_));
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+
+ // After acking the first wheel event, the queue continues.
+ testing::Mock::VerifyAndClearExpectations(&mock_client_);
+
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchEnd),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+}
+
+// Ensure the queue handles pinch event sequences with multiple updates.
+TEST_F(TouchpadPinchEventQueueTest, MultipleUpdatesInSequence) {
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchBegin),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(EventHasCtrlModifier()))
+ .Times(3);
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS))
+ .Times(3);
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchEnd),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+
+ QueuePinchBegin();
+ QueuePinchUpdate(1.23, false);
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ QueuePinchUpdate(1.23, false);
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ QueuePinchUpdate(1.23, false);
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ QueuePinchEnd();
+}
+
+// Ensure the queue coalesces pinch update events.
+TEST_F(TouchpadPinchEventQueueTest, MultipleUpdatesCoalesced) {
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchBegin),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+ EXPECT_CALL(mock_client_,
+ SendMouseWheelEventForPinchImmediately(EventHasCtrlModifier()))
+ .Times(2);
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchUpdate),
+ InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS))
+ .Times(2);
+ EXPECT_CALL(mock_client_,
+ OnGestureEventForPinchAck(
+ EventHasType(blink::WebInputEvent::kGesturePinchEnd),
+ InputEventAckSource::BROWSER, INPUT_EVENT_ACK_STATE_IGNORED));
+
+ QueuePinchBegin();
+ // The queue will send the first wheel event for this first update.
+ QueuePinchUpdate(1.23, false);
+ // Before the first wheel event is acked, queue another update.
+ QueuePinchUpdate(1.23, false);
+ // Queue a third update. This will be coalesced with the second update which
+ // is currently in the queue.
+ QueuePinchUpdate(1.23, false);
+ QueuePinchEnd();
+
+ // Ack for the wheel event corresponding to the first update.
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ // Ack for the wheel event corresponding to the second and third updates.
+ SendWheelEventAck(InputEventAckSource::COMPOSITOR_THREAD,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ EXPECT_FALSE(queue_.has_pending());
+}
+
+} // namespace content
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 f2f2b661322..be7624b1be3 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
@@ -536,8 +536,12 @@ blink::WebGestureEvent WebGestureEventBuilder::Build(NSEvent* event,
switch ([event type]) {
case NSEventTypeMagnify:
+ // We don't need to set the type based on |[event phase]| as the caller
+ // must set the begin and end types in order to support older Mac
+ // versions.
result.SetType(blink::WebInputEvent::kGesturePinchUpdate);
result.data.pinch_update.scale = [event magnification] + 1.0;
+ result.SetNeedsWheelEvent(true);
break;
case NSEventTypeSmartMagnify:
// Map the Cocoa "double-tap with two fingers" zoom gesture to regular
diff --git a/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc b/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
index 0aed4733809..c2dfa603d1b 100644
--- a/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
@@ -3,12 +3,10 @@
// found in the LICENSE file.
#include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
-#include "content/public/common/content_features.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -29,62 +27,52 @@ void GiveItSomeTime() {
run_loop.Run();
}
-const char kWheelEventLatchingDataURL[] =
- "data:text/html;charset=utf-8,"
- "<!DOCTYPE html>"
- "<meta name='viewport' content='width=device-width, minimum-scale=1'>"
- "<style>"
- "body {"
- " height: 10000px;"
- "}"
- "%23scrollableDiv {"
- " position: absolute;"
- " left: 50px;"
- " top: 100px;"
- " width: 200px;"
- " height: 200px;"
- " overflow: scroll;"
- " background: red;"
- "}"
- "%23nestedDiv {"
- " width: 200px;"
- " height: 8000px;"
- " opacity: 0;"
- "}"
- "</style>"
- "<div id='scrollableDiv'>"
- " <div id='nestedDiv'></div>"
- "</div>"
- "<script>"
- " var scrollableDiv = document.getElementById('scrollableDiv');"
- " var scrollableDivWheelEventCounter = 0;"
- " var documentWheelEventCounter = 0;"
- " scrollableDiv.addEventListener('wheel',"
- " function(e) { scrollableDivWheelEventCounter++;"
- " e.stopPropagation(); });"
- " document.scrollingElement.addEventListener('wheel',"
- " function(e) { documentWheelEventCounter++; });"
- "</script>";
-
-enum WheelScrollingMode {
- kWheelScrollingModeNone,
- kWheelScrollLatching,
- kAsyncWheelEvents,
-};
+const char kWheelEventLatchingDataURL[] = R"HTML(
+ data:text/html;charset=utf-8,
+ <!DOCTYPE html>
+ <meta name='viewport' content='width=device-width, minimum-scale=1'>
+ <style>
+ body {
+ height: 10000px;
+ }
+ %23scrollableDiv {
+ position: absolute;
+ left: 50px;
+ top: 100px;
+ width: 200px;
+ height: 200px;
+ overflow: scroll;
+ background: red;
+ }
+ %23nestedDiv {
+ width: 200px;
+ height: 8000px;
+ opacity: 0;
+ }
+ </style>
+ <div id='scrollableDiv'>
+ <div id='nestedDiv'></div>
+ </div>
+ <script>
+ var scrollableDiv = document.getElementById('scrollableDiv');
+ var scrollableDivWheelEventCounter = 0;
+ var documentWheelEventCounter = 0;
+ scrollableDiv.addEventListener('wheel',
+ function(e) {
+ scrollableDivWheelEventCounter++;
+ e.stopPropagation();
+ });
+ document.scrollingElement.addEventListener('wheel',
+ function(e) { documentWheelEventCounter++; });
+ </script>)HTML";
} // namespace
namespace content {
class WheelScrollLatchingBrowserTest : public ContentBrowserTest {
public:
- WheelScrollLatchingBrowserTest(
- WheelScrollingMode wheel_scrolling_mode = kWheelScrollLatching)
- : wheel_scrolling_mode_(wheel_scrolling_mode),
- wheel_scroll_latching_enabled_(wheel_scrolling_mode_ !=
- kWheelScrollingModeNone) {
+ WheelScrollLatchingBrowserTest() {
ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
0);
-
- SetFeatureList();
}
~WheelScrollLatchingBrowserTest() override {}
@@ -110,8 +98,8 @@ class WheelScrollLatchingBrowserTest : public ContentBrowserTest {
->GetView());
}
- void LoadURL() {
- const GURL data_url(kWheelEventLatchingDataURL);
+ void LoadURL(const std::string& page_data) {
+ const GURL data_url("data:text/html," + page_data);
NavigateToURL(shell(), data_url);
RenderWidgetHostImpl* host = GetWidgetHost();
@@ -139,49 +127,16 @@ class WheelScrollLatchingBrowserTest : public ContentBrowserTest {
shell(), "domAutomationController.send(" + script + ")", &value));
return value;
}
- void SetFeatureList() {
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- feature_list_.InitWithFeatures({features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents},
- {});
- } else if (wheel_scrolling_mode_ == kWheelScrollLatching) {
- feature_list_.InitWithFeatures(
- {features::kTouchpadAndWheelScrollLatching},
- {features::kAsyncWheelEvents});
- } else if (wheel_scrolling_mode_ == kWheelScrollingModeNone) {
- feature_list_.InitWithFeatures({},
- {features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents});
- }
- }
-
- void WheelEventTargetTest();
- void WheelEventRetargetWhenTargetRemovedTest();
- void WheelScrollingRelatchWhenLatchedScrollerRemovedTest();
-
- private:
- base::test::ScopedFeatureList feature_list_;
- WheelScrollingMode wheel_scrolling_mode_;
- bool wheel_scroll_latching_enabled_;
};
-class WheelScrollLatchingDisabledBrowserTest
- : public WheelScrollLatchingBrowserTest {
- public:
- WheelScrollLatchingDisabledBrowserTest()
- : WheelScrollLatchingBrowserTest(kWheelScrollingModeNone) {}
- ~WheelScrollLatchingDisabledBrowserTest() override {}
-};
-
-class AsyncWheelEventsBrowserTest : public WheelScrollLatchingBrowserTest {
- public:
- AsyncWheelEventsBrowserTest()
- : WheelScrollLatchingBrowserTest(kAsyncWheelEvents) {}
- ~AsyncWheelEventsBrowserTest() override {}
-};
-
-void WheelScrollLatchingBrowserTest::WheelEventTargetTest() {
- LoadURL();
+// Start scrolling by mouse wheel on the document: the wheel event will be sent
+// to the document's scrolling element, the scrollable div will be under the
+// cursor after applying the scrolling. Continue scrolling by mouse wheel, since
+// wheel scroll latching is enabled the wheel event will be still sent to the
+// document's scrolling element and the document's scrolling element will
+// continue scrolling.
+IN_PROC_BROWSER_TEST_F(WheelScrollLatchingBrowserTest, WheelEventTarget) {
+ LoadURL(kWheelEventLatchingDataURL);
EXPECT_EQ(0, ExecuteScriptAndExtractInt("documentWheelEventCounter"));
EXPECT_EQ(0, ExecuteScriptAndExtractInt("scrollableDivWheelEventCounter"));
@@ -226,63 +181,18 @@ void WheelScrollLatchingBrowserTest::WheelEventTargetTest() {
GetRouter()->RouteMouseWheelEvent(GetRootView(), &wheel_event,
ui::LatencyInfo());
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- // Runs until we get the InputMsgAck callback.
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
- input_msg_watcher->WaitForAck());
- }
-
- if (wheel_scroll_latching_enabled_) {
- while (ExecuteScriptAndExtractDouble(
- "document.scrollingElement.scrollTop") < -2 * delta_y) {
- frame_observer.Wait();
- }
-
- EXPECT_EQ(0, ExecuteScriptAndExtractDouble("scrollableDiv.scrollTop"));
- EXPECT_EQ(2, ExecuteScriptAndExtractInt("documentWheelEventCounter"));
- EXPECT_EQ(0, ExecuteScriptAndExtractInt("scrollableDivWheelEventCounter"));
- } else { // !wheel_scroll_latching_enabled_
- while (ExecuteScriptAndExtractDouble("scrollableDiv.scrollTop") <
- -delta_y)
- frame_observer.Wait();
-
- EXPECT_EQ(1, ExecuteScriptAndExtractInt("documentWheelEventCounter"));
- EXPECT_EQ(1,
- ExecuteScriptAndExtractInt("scrollableDivWheelEventCounter"));
- }
+ while (ExecuteScriptAndExtractDouble("document.scrollingElement.scrollTop") <
+ -2 * delta_y) {
+ frame_observer.Wait();
}
-// Start scrolling by mouse wheel on the document: the wheel event will be sent
-// to the document's scrolling element, the scrollable div will be under the
-// cursor after applying the scrolling. Continue scrolling by mouse wheel, since
-// wheel scroll latching is enabled the wheel event will be still sent to the
-// document's scrolling element and the document's scrolling element will
-// continue scrolling.
-IN_PROC_BROWSER_TEST_F(WheelScrollLatchingBrowserTest, WheelEventTarget) {
- WheelEventTargetTest();
-}
-IN_PROC_BROWSER_TEST_F(AsyncWheelEventsBrowserTest, WheelEventTarget) {
- WheelEventTargetTest();
-}
-
-// Start scrolling by mouse wheel on the document: the wheel event will be sent
-// to the document's scrolling element, the scrollable div will be under the
-// cursor after applying the scrolloffsets. Continue scrolling by mouse wheel,
-// since wheel scroll latching is disabled the wheel event will be still sent to
-// the scrollable div which is currently under the cursor. The div will start
-// scrolling.
-IN_PROC_BROWSER_TEST_F(WheelScrollLatchingDisabledBrowserTest,
- WheelEventTarget) {
- WheelEventTargetTest();
+ EXPECT_EQ(0, ExecuteScriptAndExtractDouble("scrollableDiv.scrollTop"));
+ EXPECT_EQ(2, ExecuteScriptAndExtractInt("documentWheelEventCounter"));
+ EXPECT_EQ(0, ExecuteScriptAndExtractInt("scrollableDivWheelEventCounter"));
}
-// Tests that wheel events are retargeted if their target gets deleted in the
-// middle of scrolling.
-void WheelScrollLatchingBrowserTest::WheelEventRetargetWhenTargetRemovedTest() {
- // The test is valid only when wheel scroll latching is enabled.
- if (!wheel_scroll_latching_enabled_)
- return;
-
- LoadURL();
+IN_PROC_BROWSER_TEST_F(WheelScrollLatchingBrowserTest,
+ WheelEventRetargetWhenTargetRemoved) {
+ LoadURL(kWheelEventLatchingDataURL);
EXPECT_EQ(0, ExecuteScriptAndExtractInt("documentWheelEventCounter"));
EXPECT_EQ(0, ExecuteScriptAndExtractInt("scrollableDivWheelEventCounter"));
@@ -332,14 +242,6 @@ void WheelScrollLatchingBrowserTest::WheelEventRetargetWhenTargetRemovedTest() {
EXPECT_EQ(1, ExecuteScriptAndExtractInt("scrollableDivWheelEventCounter"));
}
-IN_PROC_BROWSER_TEST_F(WheelScrollLatchingBrowserTest,
- WheelEventRetargetWhenTargetRemoved) {
- WheelEventRetargetWhenTargetRemovedTest();
-}
-IN_PROC_BROWSER_TEST_F(AsyncWheelEventsBrowserTest,
- WheelEventRetargetWhenTargetRemoved) {
- WheelEventRetargetWhenTargetRemovedTest();
-}
// crbug.com/777258 Flaky on Android.
#if defined(OS_ANDROID)
@@ -349,13 +251,9 @@ IN_PROC_BROWSER_TEST_F(AsyncWheelEventsBrowserTest,
#define MAYBE_WheelScrollingRelatchWhenLatchedScrollerRemoved \
WheelScrollingRelatchWhenLatchedScrollerRemoved
#endif
-void WheelScrollLatchingBrowserTest::
- WheelScrollingRelatchWhenLatchedScrollerRemovedTest() {
- // The test is valid only when wheel scroll latching is enabled.
- if (!wheel_scroll_latching_enabled_)
- return;
-
- LoadURL();
+IN_PROC_BROWSER_TEST_F(WheelScrollLatchingBrowserTest,
+ MAYBE_WheelScrollingRelatchWhenLatchedScrollerRemoved) {
+ LoadURL(kWheelEventLatchingDataURL);
EXPECT_EQ(
ExecuteScriptAndExtractDouble("document.scrollingElement.scrollTop"), 0);
EXPECT_EQ(ExecuteScriptAndExtractDouble("scrollableDiv.scrollTop"), 0);
@@ -414,13 +312,83 @@ void WheelScrollLatchingBrowserTest::
GiveItSomeTime();
}
}
+
+const char kWheelRetargetIfPreventedByDefault[] = R"HTML(
+ data:text/html;charset=utf-8,
+ <!DOCTYPE html>
+ <meta name='viewport' content='width=device-width, minimum-scale=1'>
+ <style>
+ %23blueDiv {
+ position: absolute;
+ left: 50px;
+ top: 100px;
+ width: 200px;
+ height: 200px;
+ display: block;
+ background: blue;
+ }
+ %23redDiv {
+ width: 200px;
+ height: 200px;
+ display: none;
+ background: red;
+ }
+ </style>
+ <body>
+ <div id='blueDiv'>
+ <div id='redDiv'></div>
+ </div>
+ </body>
+ <script>
+ var blueDiv = document.getElementById('blueDiv');
+ var redDiv = document.getElementById('redDiv');
+ var domTarget = 'noTarget';
+ var x = (blueDiv.getBoundingClientRect().left +
+ blueDiv.getBoundingClientRect().right) / 2;
+ var y = (blueDiv.getBoundingClientRect().top +
+ blueDiv.getBoundingClientRect().bottom) /2;
+ blueDiv.addEventListener('wheel', function(e) {
+ e.preventDefault();
+ domTarget = 'blueDiv';
+ redDiv.style.display = 'block';
+ });
+ redDiv.addEventListener('wheel', function(e) {
+ domTarget = 'redDiv';
+ e.stopPropagation();
+ });
+ </script>)HTML";
+
IN_PROC_BROWSER_TEST_F(WheelScrollLatchingBrowserTest,
- MAYBE_WheelScrollingRelatchWhenLatchedScrollerRemoved) {
- WheelScrollingRelatchWhenLatchedScrollerRemovedTest();
-}
-IN_PROC_BROWSER_TEST_F(AsyncWheelEventsBrowserTest,
- MAYBE_WheelScrollingRelatchWhenLatchedScrollerRemoved) {
- WheelScrollingRelatchWhenLatchedScrollerRemovedTest();
+ WheelEventRetargetOnPreventDefault) {
+ LoadURL(kWheelRetargetIfPreventedByDefault);
+
+ float x = ExecuteScriptAndExtractDouble("x");
+ float y = ExecuteScriptAndExtractDouble("y");
+
+ // Send the first wheel event.
+ auto wheel_msg_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kMouseWheel);
+ blink::WebMouseWheelEvent wheel_event =
+ SyntheticWebMouseWheelEventBuilder::Build(x, y, x, y, 1, 1, 0, true);
+ wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
+ GetRouter()->RouteMouseWheelEvent(GetRootView(), &wheel_event,
+ ui::LatencyInfo());
+
+ // Run until we get the callback, then check the target.
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, wheel_msg_watcher->WaitForAck());
+ EXPECT_EQ("blueDiv", ExecuteScriptAndExtractString("domTarget"));
+
+ // Send the second wheel event.
+ wheel_msg_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kMouseWheel);
+ wheel_event.phase = blink::WebMouseWheelEvent::kPhaseChanged;
+ GetRouter()->RouteMouseWheelEvent(GetRootView(), &wheel_event,
+ ui::LatencyInfo());
+
+ // Run until we get the callback, then check the target.
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+ wheel_msg_watcher->WaitForAck());
+ EXPECT_EQ("redDiv", ExecuteScriptAndExtractString("domTarget"));
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_input_stream_handle.cc b/chromium/content/browser/renderer_host/media/audio_input_stream_handle.cc
index b92446bd173..159b776860a 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_stream_handle.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_stream_handle.cc
@@ -56,8 +56,9 @@ void AudioInputStreamHandle::SetOutputDeviceForAec(
stream_.SetOutputDeviceForAec(raw_output_device_id);
}
-void AudioInputStreamHandle::OnCreated(media::mojom::AudioDataPipePtr data_pipe,
- bool initially_muted) {
+void AudioInputStreamHandle::OnCreated(
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
+ bool initially_muted) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(client_);
DCHECK(deleter_callback_)
diff --git a/chromium/content/browser/renderer_host/media/audio_input_stream_handle.h b/chromium/content/browser/renderer_host/media/audio_input_stream_handle.h
index 0a30e0085d2..c36e892dc87 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_stream_handle.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_stream_handle.h
@@ -37,7 +37,7 @@ class CONTENT_EXPORT AudioInputStreamHandle {
void SetOutputDeviceForAec(const std::string& raw_output_device_id);
private:
- void OnCreated(media::mojom::AudioDataPipePtr, bool initially_muted);
+ void OnCreated(media::mojom::ReadOnlyAudioDataPipePtr, bool initially_muted);
void CallDeleter();
diff --git a/chromium/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc
index 90be42dc659..a843d538ebf 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc
@@ -49,7 +49,7 @@ class MockRendererAudioInputStreamFactoryClient
void StreamCreated(
media::mojom::AudioInputStreamPtr input_stream,
media::mojom::AudioInputStreamClientRequest client_request,
- media::mojom::AudioDataPipePtr data_pipe,
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
bool initially_muted,
const base::Optional<base::UnguessableToken>& stream_id) override {
EXPECT_TRUE(stream_id.has_value());
diff --git a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc
index 1b601ac380f..239c8be2a1e 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc
+++ b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc
@@ -253,10 +253,10 @@ void AudioOutputAuthorizationHandler::AccessChecked(
devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
media_stream_manager_->media_devices_manager()->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&AudioOutputAuthorizationHandler::TranslateDeviceID,
- weak_factory_.GetWeakPtr(), base::Passed(&trace_scope),
- base::Passed(&cb), device_id, std::move(salt),
- std::move(security_origin)));
+ base::BindOnce(&AudioOutputAuthorizationHandler::TranslateDeviceID,
+ weak_factory_.GetWeakPtr(), base::Passed(&trace_scope),
+ base::Passed(&cb), device_id, std::move(salt),
+ std::move(security_origin)));
}
void AudioOutputAuthorizationHandler::TranslateDeviceID(
diff --git a/chromium/content/browser/renderer_host/media/audio_service_listener.cc b/chromium/content/browser/renderer_host/media/audio_service_listener.cc
index 08157dce240..a97377898da 100644
--- a/chromium/content/browser/renderer_host/media/audio_service_listener.cc
+++ b/chromium/content/browser/renderer_host/media/audio_service_listener.cc
@@ -6,12 +6,16 @@
#include <utility>
+#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/default_tick_clock.h"
+#include "content/browser/media/audio_log_factory.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/child_process_termination_info.h"
+#include "content/public/common/content_features.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/audio/public/mojom/constants.mojom.h"
+#include "services/audio/public/mojom/log_factory_manager.mojom.h"
namespace content {
@@ -88,14 +92,15 @@ void AudioServiceListener::Metrics::LogServiceStartStatus(
AudioServiceListener::AudioServiceListener(
std::unique_ptr<service_manager::Connector> connector)
: binding_(this),
+ connector_(std::move(connector)),
metrics_(base::DefaultTickClock::GetInstance()) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
- if (!connector)
+ if (!connector_)
return; // Happens in unittests.
service_manager::mojom::ServiceManagerPtr service_manager;
- connector->BindInterface(service_manager::mojom::kServiceName,
- &service_manager);
+ connector_->BindInterface(service_manager::mojom::kServiceName,
+ &service_manager);
service_manager::mojom::ServiceManagerListenerPtr listener;
service_manager::mojom::ServiceManagerListenerRequest request(
mojo::MakeRequest(&listener));
@@ -123,6 +128,7 @@ void AudioServiceListener::OnInit(
if (instance->identity.name() == audio::mojom::kServiceName) {
process_id_ = instance->pid;
metrics_.ServiceAlreadyRunning();
+ MaybeSetLogFactory();
break;
}
}
@@ -134,6 +140,7 @@ void AudioServiceListener::OnServiceCreated(
if (service->identity.name() != audio::mojom::kServiceName)
return;
metrics_.ServiceCreated();
+ MaybeSetLogFactory();
}
void AudioServiceListener::OnServiceStarted(
@@ -169,6 +176,7 @@ void AudioServiceListener::OnServiceStopped(
if (identity.name() != audio::mojom::kServiceName)
return;
metrics_.ServiceStopped();
+ log_factory_is_set_ = false;
}
void AudioServiceListener::BrowserChildProcessHostDisconnected(
@@ -203,4 +211,20 @@ void AudioServiceListener::BrowserChildProcessKilled(
Metrics::ServiceProcessTerminationStatus::kKill);
}
+void AudioServiceListener::MaybeSetLogFactory() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (!base::FeatureList::IsEnabled(features::kAudioServiceOutOfProcess) ||
+ !connector_ || log_factory_is_set_)
+ return;
+
+ media::mojom::AudioLogFactoryPtr audio_log_factory_ptr;
+ mojo::MakeStrongBinding(std::make_unique<AudioLogFactory>(),
+ mojo::MakeRequest(&audio_log_factory_ptr));
+ audio::mojom::LogFactoryManagerPtr log_factory_manager_ptr;
+ connector_->BindInterface(audio::mojom::kServiceName,
+ mojo::MakeRequest(&log_factory_manager_ptr));
+ log_factory_manager_ptr->SetLogFactory(std::move(audio_log_factory_ptr));
+ log_factory_is_set_ = true;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_service_listener.h b/chromium/content/browser/renderer_host/media/audio_service_listener.h
index 60623985912..41942d5bda5 100644
--- a/chromium/content/browser/renderer_host/media/audio_service_listener.h
+++ b/chromium/content/browser/renderer_host/media/audio_service_listener.h
@@ -116,9 +116,13 @@ class CONTENT_EXPORT AudioServiceListener
void BrowserChildProcessKilled(const ChildProcessData& data,
const ChildProcessTerminationInfo& info) final;
+ void MaybeSetLogFactory();
+
mojo::Binding<service_manager::mojom::ServiceManagerListener> binding_;
+ std::unique_ptr<service_manager::Connector> connector_;
base::ProcessId process_id_ = base::kNullProcessId;
Metrics metrics_;
+ bool log_factory_is_set_ = false;
SEQUENCE_CHECKER(owning_sequence_);
DISALLOW_COPY_AND_ASSIGN(AudioServiceListener);
diff --git a/chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc b/chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc
index 2afcfb7833b..d6a66a9d5b4 100644
--- a/chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc
@@ -7,7 +7,7 @@
#include <utility>
#include "base/process/kill.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/child_process_termination_info.h"
diff --git a/chromium/content/browser/renderer_host/media/fake_video_capture_device_launcher.cc b/chromium/content/browser/renderer_host/media/fake_video_capture_device_launcher.cc
index 5874c901f67..cad67364595 100644
--- a/chromium/content/browser/renderer_host/media/fake_video_capture_device_launcher.cc
+++ b/chromium/content/browser/renderer_host/media/fake_video_capture_device_launcher.cc
@@ -78,6 +78,7 @@ void FakeVideoCaptureDeviceLauncher::LaunchDeviceAsync(
std::make_unique<media::VideoCaptureBufferTrackerFactoryImpl>(),
kMaxBufferCount));
auto device_client = std::make_unique<media::VideoCaptureDeviceClient>(
+ media::VideoCaptureBufferType::kSharedMemory,
std::make_unique<media::VideoFrameReceiverOnTaskRunner>(
receiver, base::ThreadTaskRunnerHandle::Get()),
std::move(buffer_pool), std::move(empty_jpeg_decoder_factory_cb));
diff --git a/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc b/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
index 3e68e40eed4..77742e8cd19 100644
--- a/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
+++ b/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
@@ -9,13 +9,14 @@
#include "build/build_config.h"
#include "content/browser/renderer_host/media/in_process_launched_video_capture_device.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
-#include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h"
+#include "content/browser/renderer_host/media/video_capture_dependencies.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/media_stream_request.h"
#include "media/base/bind_to_current_loop.h"
#include "media/capture/video/video_capture_buffer_pool_impl.h"
#include "media/capture/video/video_capture_buffer_tracker_factory_impl.h"
#include "media/capture/video/video_capture_device_client.h"
+#include "media/capture/video/video_capture_jpeg_decoder_impl.h"
#include "media/capture/video/video_frame_receiver.h"
#include "media/capture/video/video_frame_receiver_on_task_runner.h"
@@ -38,7 +39,11 @@ namespace {
std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder(
media::VideoCaptureJpegDecoder::DecodeDoneCB decode_done_cb,
base::Callback<void(const std::string&)> send_log_message_cb) {
- return std::make_unique<content::VideoCaptureGpuJpegDecoder>(
+ return std::make_unique<media::VideoCaptureJpegDecoderImpl>(
+ base::BindRepeating(
+ &content::VideoCaptureDependencies::CreateJpegDecodeAccelerator),
+ content::BrowserThread::GetTaskRunnerForThread(
+ content::BrowserThread::IO),
std::move(decode_done_cb), std::move(send_log_message_cb));
}
@@ -109,7 +114,8 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
&InProcessVideoCaptureDeviceLauncher::
DoStartDeviceCaptureOnDeviceThread,
base::Unretained(this), device_id, params,
- CreateDeviceClient(kMaxNumberOfBuffers, std::move(receiver),
+ CreateDeviceClient(media::VideoCaptureBufferType::kSharedMemory,
+ kMaxNumberOfBuffers, std::move(receiver),
std::move(receiver_on_io_thread)),
std::move(after_start_capture_callback));
break;
@@ -176,7 +182,8 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
&InProcessVideoCaptureDeviceLauncher::
DoStartDesktopCaptureOnDeviceThread,
base::Unretained(this), desktop_id, params,
- CreateDeviceClient(kMaxNumberOfBuffers, std::move(receiver),
+ CreateDeviceClient(media::VideoCaptureBufferType::kSharedMemory,
+ kMaxNumberOfBuffers, std::move(receiver),
std::move(receiver_on_io_thread)),
std::move(after_start_capture_callback));
break;
@@ -202,6 +209,7 @@ void InProcessVideoCaptureDeviceLauncher::AbortLaunch() {
std::unique_ptr<media::VideoCaptureDeviceClient>
InProcessVideoCaptureDeviceLauncher::CreateDeviceClient(
+ media::VideoCaptureBufferType requested_buffer_type,
int buffer_pool_max_buffer_count,
std::unique_ptr<media::VideoFrameReceiver> receiver,
base::WeakPtr<media::VideoFrameReceiver> receiver_on_io_thread) {
@@ -213,7 +221,7 @@ InProcessVideoCaptureDeviceLauncher::CreateDeviceClient(
buffer_pool_max_buffer_count);
return std::make_unique<media::VideoCaptureDeviceClient>(
- std::move(receiver), std::move(buffer_pool),
+ requested_buffer_type, std::move(receiver), std::move(buffer_pool),
base::BindRepeating(
&CreateGpuJpegDecoder,
base::BindRepeating(&media::VideoFrameReceiver::OnFrameReadyInBuffer,
diff --git a/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h b/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h
index b2919080aff..ce862c58484 100644
--- a/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h
+++ b/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h
@@ -51,6 +51,7 @@ class InProcessVideoCaptureDeviceLauncher : public VideoCaptureDeviceLauncher {
};
std::unique_ptr<media::VideoCaptureDeviceClient> CreateDeviceClient(
+ media::VideoCaptureBufferType requested_buffer_type,
int buffer_pool_max_buffer_count,
std::unique_ptr<media::VideoFrameReceiver> receiver,
base::WeakPtr<media::VideoFrameReceiver> receiver_on_io_thread);
diff --git a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
index 6818c2288c5..c87ff868818 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
@@ -36,15 +36,18 @@ std::vector<blink::mojom::AudioInputDeviceCapabilitiesPtr>
ToVectorAudioInputDeviceCapabilitiesPtr(
const std::vector<blink::mojom::AudioInputDeviceCapabilities>&
capabilities_vector,
- const url::Origin& security_origin,
- const std::string& salt) {
+ const MediaDeviceSaltAndOrigin& salt_and_origin) {
std::vector<blink::mojom::AudioInputDeviceCapabilitiesPtr> result;
result.reserve(capabilities_vector.size());
for (auto& capabilities : capabilities_vector) {
blink::mojom::AudioInputDeviceCapabilitiesPtr capabilities_ptr =
blink::mojom::AudioInputDeviceCapabilities::New();
capabilities_ptr->device_id =
- GetHMACForMediaDeviceID(salt, security_origin, capabilities.device_id);
+ GetHMACForMediaDeviceID(salt_and_origin.device_id_salt,
+ salt_and_origin.origin, capabilities.device_id);
+ capabilities_ptr->group_id =
+ GetHMACForMediaDeviceID(salt_and_origin.group_id_salt,
+ salt_and_origin.origin, capabilities.group_id);
capabilities_ptr->parameters = capabilities.parameters;
result.push_back(std::move(capabilities_ptr));
}
@@ -202,9 +205,10 @@ void MediaDevicesDispatcherHost::GotDefaultVideoInputDeviceID(
requested_types[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
media_stream_manager_->media_devices_manager()->EnumerateDevices(
requested_types,
- base::Bind(&MediaDevicesDispatcherHost::FinalizeGetVideoInputCapabilities,
- weak_factory_.GetWeakPtr(), base::Passed(&client_callback),
- std::move(salt_and_origin), std::move(default_device_id)));
+ base::BindOnce(
+ &MediaDevicesDispatcherHost::FinalizeGetVideoInputCapabilities,
+ weak_factory_.GetWeakPtr(), base::Passed(&client_callback),
+ std::move(salt_and_origin), std::move(default_device_id)));
}
void MediaDevicesDispatcherHost::FinalizeGetVideoInputCapabilities(
@@ -292,8 +296,7 @@ void MediaDevicesDispatcherHost::FinalizeGetVideoInputDeviceFormats(
}
struct MediaDevicesDispatcherHost::AudioInputCapabilitiesRequest {
- std::string device_id_salt;
- url::Origin security_origin;
+ MediaDeviceSaltAndOrigin salt_and_origin;
GetAudioInputCapabilitiesCallback client_callback;
};
@@ -302,8 +305,7 @@ void MediaDevicesDispatcherHost::GetDefaultAudioInputDeviceID(
const MediaDeviceSaltAndOrigin& salt_and_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
pending_audio_input_capabilities_requests_.push_back(
- AudioInputCapabilitiesRequest{salt_and_origin.device_id_salt,
- salt_and_origin.origin,
+ AudioInputCapabilitiesRequest{salt_and_origin,
std::move(client_callback)});
if (pending_audio_input_capabilities_requests_.size() > 1U)
return;
@@ -324,8 +326,8 @@ void MediaDevicesDispatcherHost::GotDefaultAudioInputDeviceID(
devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
media_stream_manager_->media_devices_manager()->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesDispatcherHost::GotAudioInputEnumeration,
- weak_factory_.GetWeakPtr(), default_device_id));
+ base::BindOnce(&MediaDevicesDispatcherHost::GotAudioInputEnumeration,
+ weak_factory_.GetWeakPtr(), default_device_id));
}
void MediaDevicesDispatcherHost::GotAudioInputEnumeration(
@@ -337,7 +339,7 @@ void MediaDevicesDispatcherHost::GotAudioInputEnumeration(
DCHECK_EQ(num_pending_audio_input_parameters_, 0U);
for (const auto& device_info : enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT]) {
blink::mojom::AudioInputDeviceCapabilities capabilities(
- device_info.device_id,
+ device_info.device_id, device_info.group_id,
media::AudioParameters::UnavailableDeviceParams());
if (device_info.device_id == default_device_id)
current_audio_input_capabilities_.insert(
@@ -386,8 +388,7 @@ void MediaDevicesDispatcherHost::FinalizeGetAudioInputCapabilities() {
for (auto& request : pending_audio_input_capabilities_requests_) {
std::move(request.client_callback)
.Run(ToVectorAudioInputDeviceCapabilitiesPtr(
- current_audio_input_capabilities_, request.security_origin,
- request.device_id_salt));
+ current_audio_input_capabilities_, request.salt_and_origin));
}
current_audio_input_capabilities_.clear();
diff --git a/chromium/content/browser/renderer_host/media/media_devices_manager.cc b/chromium/content/browser/renderer_host/media/media_devices_manager.cc
index 93c8f2ba585..c9fcb5e765b 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager.cc
@@ -124,6 +124,13 @@ static bool EqualDeviceAndGroupID(const MediaDeviceInfo& lhs,
return lhs == rhs && lhs.group_id == rhs.group_id;
}
+void ReplaceInvalidFrameRatesWithFallback(media::VideoCaptureFormats* formats) {
+ for (auto& format : *formats) {
+ if (format.frame_rate <= 0)
+ format.frame_rate = kFallbackVideoFrameRates[0];
+ }
+}
+
} // namespace
std::string GuessVideoGroupID(const MediaDeviceInfoArray& audio_infos,
@@ -194,8 +201,8 @@ std::string GuessVideoGroupID(const MediaDeviceInfoArray& audio_infos,
struct MediaDevicesManager::EnumerationRequest {
EnumerationRequest(const BoolDeviceTypes& requested_types,
- const EnumerationCallback& callback)
- : callback(callback) {
+ EnumerationCallback callback)
+ : callback(std::move(callback)) {
requested = requested_types;
has_seen_result.fill(false);
}
@@ -360,12 +367,14 @@ class MediaDevicesManager::AudioServiceDeviceListener
MediaDevicesManager::MediaDevicesManager(
media::AudioSystem* audio_system,
const scoped_refptr<VideoCaptureManager>& video_capture_manager,
- MediaStreamManager* media_stream_manager)
+ StopRemovedInputDeviceCallback stop_removed_input_device_cb,
+ UIInputDeviceChangeCallback ui_input_device_change_cb)
: use_fake_devices_(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseFakeDeviceForMediaStream)),
audio_system_(audio_system),
video_capture_manager_(video_capture_manager),
- media_stream_manager_(media_stream_manager),
+ stop_removed_input_device_cb_(std::move(stop_removed_input_device_cb)),
+ ui_input_device_change_cb_(std::move(ui_input_device_change_cb)),
permission_checker_(std::make_unique<MediaDevicesPermissionChecker>()),
cache_infos_(NUM_MEDIA_DEVICE_TYPES),
monitoring_started_(false),
@@ -375,6 +384,8 @@ MediaDevicesManager::MediaDevicesManager(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(audio_system_);
DCHECK(video_capture_manager_.get());
+ DCHECK(!stop_removed_input_device_cb_.is_null());
+ DCHECK(!ui_input_device_change_cb_.is_null());
cache_policies_.fill(CachePolicy::NO_CACHE);
has_seen_result_.fill(false);
}
@@ -385,11 +396,11 @@ MediaDevicesManager::~MediaDevicesManager() {
void MediaDevicesManager::EnumerateDevices(
const BoolDeviceTypes& requested_types,
- const EnumerationCallback& callback) {
+ EnumerationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
StartMonitoring();
- requests_.emplace_back(requested_types, callback);
+ requests_.emplace_back(requested_types, std::move(callback));
bool all_results_cached = true;
for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
if (requested_types[i] && cache_policies_[i] == CachePolicy::NO_CACHE) {
@@ -565,11 +576,13 @@ media::VideoCaptureFormats MediaDevicesManager::GetVideoInputFormats(
device_id);
if (format.has_value()) {
formats.push_back(format.value());
+ ReplaceInvalidFrameRatesWithFallback(&formats);
return formats;
}
}
video_capture_manager_->GetDeviceSupportedFormats(device_id, &formats);
+ ReplaceInvalidFrameRatesWithFallback(&formats);
// Remove formats that have zero resolution.
formats.erase(std::remove_if(formats.begin(), formats.end(),
[](const media::VideoCaptureFormat& format) {
@@ -651,11 +664,10 @@ void MediaDevicesManager::OnPermissionsCheckDone(
EnumerateDevices(
internal_requested_types,
- base::BindRepeating(&MediaDevicesManager::OnDevicesEnumerated,
- weak_factory_.GetWeakPtr(), requested_types,
- request_video_input_capabilities,
- base::Passed(&callback), std::move(salt_and_origin),
- has_permissions));
+ base::BindOnce(&MediaDevicesManager::OnDevicesEnumerated,
+ weak_factory_.GetWeakPtr(), requested_types,
+ request_video_input_capabilities, base::Passed(&callback),
+ std::move(salt_and_origin), has_permissions));
}
void MediaDevicesManager::OnDevicesEnumerated(
@@ -681,24 +693,27 @@ void MediaDevicesManager::OnDevicesEnumerated(
}
}
- std::move(callback).Run(
- std::move(result),
- video_input_capabilities_requested
- ? ComputeVideoInputCapabilities(result[MEDIA_DEVICE_TYPE_VIDEO_INPUT])
- : std::vector<VideoInputDeviceCapabilitiesPtr>());
+ std::move(callback).Run(std::move(result),
+ video_input_capabilities_requested
+ ? ComputeVideoInputCapabilities(
+ enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT],
+ result[MEDIA_DEVICE_TYPE_VIDEO_INPUT])
+ : std::vector<VideoInputDeviceCapabilitiesPtr>());
}
std::vector<VideoInputDeviceCapabilitiesPtr>
MediaDevicesManager::ComputeVideoInputCapabilities(
- const MediaDeviceInfoArray& device_infos) {
+ const MediaDeviceInfoArray& raw_device_infos,
+ const MediaDeviceInfoArray& translated_device_infos) {
+ DCHECK_EQ(raw_device_infos.size(), translated_device_infos.size());
std::vector<VideoInputDeviceCapabilitiesPtr> video_input_capabilities;
- for (const auto& device_info : device_infos) {
+ for (size_t i = 0; i < raw_device_infos.size(); ++i) {
VideoInputDeviceCapabilitiesPtr capabilities =
blink::mojom::VideoInputDeviceCapabilities::New();
- capabilities->device_id = device_info.device_id;
- capabilities->formats = GetVideoInputFormats(device_info.device_id,
+ capabilities->device_id = translated_device_infos[i].device_id;
+ capabilities->formats = GetVideoInputFormats(raw_device_infos[i].device_id,
false /* try_in_use_first */);
- capabilities->facing_mode = device_info.video_facing;
+ capabilities->facing_mode = translated_device_infos[i].video_facing;
video_input_capabilities.push_back(std::move(capabilities));
}
return video_input_capabilities;
@@ -804,10 +819,9 @@ void MediaDevicesManager::UpdateSnapshot(
bool need_update_device_change_subscribers = false;
MediaDeviceInfoArray& old_snapshot = current_snapshot_[type];
- if (old_snapshot.size() != new_snapshot.size() &&
- (type == MEDIA_DEVICE_TYPE_AUDIO_INPUT ||
- type == MEDIA_DEVICE_TYPE_VIDEO_INPUT)) {
- StopRemovedDevices(type, new_snapshot);
+ if (type == MEDIA_DEVICE_TYPE_AUDIO_INPUT ||
+ type == MEDIA_DEVICE_TYPE_VIDEO_INPUT) {
+ MaybeStopRemovedInputDevices(type, new_snapshot);
}
// Update the cached snapshot and send notifications only if the device list
@@ -824,9 +838,8 @@ void MediaDevicesManager::UpdateSnapshot(
bool is_video_with_good_group_ids =
type == MEDIA_DEVICE_TYPE_VIDEO_INPUT &&
(new_snapshot.size() == 0 || !new_snapshot[0].group_id.empty());
- if (type == MEDIA_DEVICE_TYPE_AUDIO_INPUT || is_video_with_good_group_ids) {
- NotifyMediaStreamManager(type, new_snapshot);
- }
+ if (type == MEDIA_DEVICE_TYPE_AUDIO_INPUT || is_video_with_good_group_ids)
+ ui_input_device_change_cb_.Run(type, new_snapshot);
// Do not notify device-change subscribers after the first enumeration
// result, since it is not due to an actual device change.
@@ -858,15 +871,16 @@ void MediaDevicesManager::ProcessRequests() {
false /* ignore_group_id */);
}
- requests_.erase(std::remove_if(requests_.begin(), requests_.end(),
- [this](const EnumerationRequest& request) {
- if (IsEnumerationRequestReady(request)) {
- request.callback.Run(current_snapshot_);
- return true;
- }
- return false;
- }),
- requests_.end());
+ requests_.erase(
+ std::remove_if(requests_.begin(), requests_.end(),
+ [this](EnumerationRequest& request) {
+ if (IsEnumerationRequestReady(request)) {
+ std::move(request.callback).Run(current_snapshot_);
+ return true;
+ }
+ return false;
+ }),
+ requests_.end());
}
bool MediaDevicesManager::IsEnumerationRequestReady(
@@ -899,16 +913,13 @@ void MediaDevicesManager::HandleDevicesChanged(MediaDeviceType type) {
DoEnumerateDevices(type);
}
-void MediaDevicesManager::StopRemovedDevices(
+void MediaDevicesManager::MaybeStopRemovedInputDevices(
MediaDeviceType type,
const MediaDeviceInfoArray& new_snapshot) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(type == MEDIA_DEVICE_TYPE_AUDIO_INPUT ||
type == MEDIA_DEVICE_TYPE_VIDEO_INPUT);
- if (!media_stream_manager_)
- return;
-
for (const auto& old_device_info : current_snapshot_[type]) {
auto it = std::find_if(new_snapshot.begin(), new_snapshot.end(),
[&old_device_info](const MediaDeviceInfo& info) {
@@ -918,23 +929,10 @@ void MediaDevicesManager::StopRemovedDevices(
// If a device was removed, notify the MediaStreamManager to stop all
// streams using that device.
if (it == new_snapshot.end())
- media_stream_manager_->StopRemovedDevice(type, old_device_info);
+ stop_removed_input_device_cb_.Run(type, old_device_info);
}
}
-void MediaDevicesManager::NotifyMediaStreamManager(
- MediaDeviceType type,
- const MediaDeviceInfoArray& new_snapshot) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(type == MEDIA_DEVICE_TYPE_AUDIO_INPUT ||
- type == MEDIA_DEVICE_TYPE_VIDEO_INPUT);
-
- if (!media_stream_manager_)
- return;
-
- media_stream_manager_->NotifyDevicesChanged(type, new_snapshot);
-}
-
void MediaDevicesManager::NotifyDeviceChangeSubscribers(
MediaDeviceType type,
const MediaDeviceInfoArray& snapshot) {
diff --git a/chromium/content/browser/renderer_host/media/media_devices_manager.h b/chromium/content/browser/renderer_host/media/media_devices_manager.h
index c0f7ae1262a..7ba5aff3293 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager.h
@@ -37,7 +37,6 @@ class Connector;
namespace content {
class MediaDevicesPermissionChecker;
-class MediaStreamManager;
class VideoCaptureManager;
// Use MediaDeviceType values to index on this type.
@@ -60,15 +59,22 @@ class CONTENT_EXPORT MediaDevicesManager
};
using EnumerationCallback =
- base::Callback<void(const MediaDeviceEnumeration&)>;
+ base::OnceCallback<void(const MediaDeviceEnumeration&)>;
using EnumerateDevicesCallback =
base::OnceCallback<void(const std::vector<MediaDeviceInfoArray>&,
std::vector<VideoInputDeviceCapabilitiesPtr>)>;
+ using StopRemovedInputDeviceCallback =
+ base::RepeatingCallback<void(MediaDeviceType type,
+ const MediaDeviceInfo& media_device_info)>;
+ using UIInputDeviceChangeCallback =
+ base::RepeatingCallback<void(MediaDeviceType stream_type,
+ const MediaDeviceInfoArray& devices)>;
MediaDevicesManager(
media::AudioSystem* audio_system,
const scoped_refptr<VideoCaptureManager>& video_capture_manager,
- MediaStreamManager* media_stream_manager);
+ StopRemovedInputDeviceCallback stop_removed_input_device_cb,
+ UIInputDeviceChangeCallback ui_input_device_change_cb);
~MediaDevicesManager() override;
// Performs a possibly cached device enumeration for the requested device
@@ -79,13 +85,16 @@ class CONTENT_EXPORT MediaDevicesManager
// another call to EnumerateDevices, it must do so by posting a task to the
// IO thread.
void EnumerateDevices(const BoolDeviceTypes& requested_types,
- const EnumerationCallback& callback);
+ EnumerationCallback callback);
// Performs a possibly cached device enumeration for the requested device
// types and reports the results to |callback|. The enumeration results are
// translated for use by the renderer process and frame identified with
// |render_process_id| and |render_frame_id|, based on the frame origin's
// permissions, an internal media-device salts.
+ // If |request_video_input_capabilities| is true, video formats supported
+ // by each device are returned in |callback|. These video formats are in
+ // no particular order and may contain duplicate entries.
void EnumerateDevices(int render_process_id,
int render_frame_id,
const BoolDeviceTypes& requested_types,
@@ -114,7 +123,8 @@ class CONTENT_EXPORT MediaDevicesManager
// changes.
void OnDevicesChanged(base::SystemMonitor::DeviceType device_type) override;
- // Returns the supported video formats for the given |device_id|.
+ // Returns the supported video formats for the given |device_id|. The returned
+ // formats are in no particular order and may contain duplicate entries.
// If |try_in_use_first| is true and the device is being used, only the format
// in use is returned. Otherwise, all formats supported by the device are
// returned.
@@ -197,7 +207,8 @@ class CONTENT_EXPORT MediaDevicesManager
const MediaDeviceEnumeration& enumeration);
std::vector<VideoInputDeviceCapabilitiesPtr> ComputeVideoInputCapabilities(
- const MediaDeviceInfoArray& device_infos);
+ const MediaDeviceInfoArray& raw_device_infos,
+ const MediaDeviceInfoArray& translated_device_infos);
// Helpers to issue low-level device enumerations.
void DoEnumerateDevices(MediaDeviceType type);
@@ -223,10 +234,8 @@ class CONTENT_EXPORT MediaDevicesManager
// Helpers to handle device-change notification.
void HandleDevicesChanged(MediaDeviceType type);
- void StopRemovedDevices(MediaDeviceType type,
- const MediaDeviceInfoArray& new_snapshot);
- void NotifyMediaStreamManager(MediaDeviceType type,
- const MediaDeviceInfoArray& new_snapshot);
+ void MaybeStopRemovedInputDevices(MediaDeviceType type,
+ const MediaDeviceInfoArray& new_snapshot);
void NotifyDeviceChangeSubscribers(MediaDeviceType type,
const MediaDeviceInfoArray& snapshot);
void CheckPermissionForDeviceChange(uint32_t subscription_id,
@@ -248,7 +257,8 @@ class CONTENT_EXPORT MediaDevicesManager
bool use_fake_devices_;
media::AudioSystem* const audio_system_; // not owned
scoped_refptr<VideoCaptureManager> video_capture_manager_;
- MediaStreamManager* const media_stream_manager_; // not owned
+ StopRemovedInputDeviceCallback stop_removed_input_device_cb_;
+ UIInputDeviceChangeCallback ui_input_device_change_cb_;
std::unique_ptr<MediaDevicesPermissionChecker> permission_checker_;
diff --git a/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc b/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc
index 761b26e26cd..6fd207bbffc 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc
@@ -13,6 +13,7 @@
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/media/media_devices_permission_checker.h"
#include "content/browser/renderer_host/media/in_process_video_capture_provider.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -149,6 +150,16 @@ class MockMediaDevicesListener : public blink::mojom::MediaDevicesListener {
mojo::BindingSet<blink::mojom::MediaDevicesListener> bindings_;
};
+class MockMediaDevicesManagerClient {
+ public:
+ MOCK_METHOD2(StopRemovedInputDevice,
+ void(MediaDeviceType type,
+ const MediaDeviceInfo& media_device_info));
+ MOCK_METHOD2(InputDevicesChangedUI,
+ void(MediaDeviceType stream_type,
+ const MediaDeviceInfoArray& devices));
+};
+
void VerifyDeviceAndGroupID(const std::vector<MediaDeviceInfoArray>& array) {
for (const auto& device_infos : array) {
for (const auto& device_info : device_infos) {
@@ -181,6 +192,27 @@ class MediaDevicesManagerTest : public ::testing::Test {
run_loop->Quit();
}
+ void EnumerateWithCapabilitiesCallback(
+ const std::vector<media::FakeVideoCaptureDeviceSettings>&
+ expected_video_capture_device_settings,
+ base::RunLoop* run_loop,
+ const std::vector<MediaDeviceInfoArray>& devices,
+ std::vector<VideoInputDeviceCapabilitiesPtr> capabilities) {
+ EXPECT_EQ(capabilities.size(),
+ expected_video_capture_device_settings.size());
+ for (size_t i = 0; i < capabilities.size(); ++i) {
+ EXPECT_EQ(
+ capabilities[i]->formats.size(),
+ expected_video_capture_device_settings[i].supported_formats.size());
+ for (size_t j = 0; j < capabilities[i]->formats.size(); ++j) {
+ EXPECT_EQ(
+ capabilities[i]->formats[j],
+ expected_video_capture_device_settings[i].supported_formats[j]);
+ }
+ }
+ run_loop->Quit();
+ }
+
protected:
void SetUp() override {
audio_manager_ = std::make_unique<MockAudioManager>();
@@ -198,9 +230,17 @@ class MediaDevicesManagerTest : public ::testing::Test {
video_capture_manager_ = new VideoCaptureManager(
std::move(video_capture_provider), kIgnoreLogMessageCB);
media_devices_manager_.reset(new MediaDevicesManager(
- audio_system_.get(), video_capture_manager_, nullptr));
+ audio_system_.get(), video_capture_manager_,
+ base::BindRepeating(
+ &MockMediaDevicesManagerClient::StopRemovedInputDevice,
+ base::Unretained(&media_devices_manager_client_)),
+ base::BindRepeating(
+ &MockMediaDevicesManagerClient::InputDevicesChangedUI,
+ base::Unretained(&media_devices_manager_client_))));
media_devices_manager_->set_salt_and_origin_callback_for_testing(
base::BindRepeating(&GetSaltAndOrigin));
+ media_devices_manager_->SetPermissionChecker(
+ std::make_unique<MediaDevicesPermissionChecker>(true));
}
void EnableCache(MediaDeviceType type) {
@@ -217,6 +257,8 @@ class MediaDevicesManagerTest : public ::testing::Test {
MockVideoCaptureDeviceFactory* video_capture_device_factory_;
std::unique_ptr<MockAudioManager> audio_manager_;
std::unique_ptr<media::AudioSystem> audio_system_;
+ testing::StrictMock<MockMediaDevicesManagerClient>
+ media_devices_manager_client_;
private:
DISALLOW_COPY_AND_ASSIGN(MediaDevicesManagerTest);
@@ -229,14 +271,15 @@ TEST_F(MediaDevicesManagerTest, EnumerateNoCacheAudioInput) {
.Times(0);
EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)).Times(0);
EXPECT_CALL(*this, MockCallback(_)).Times(kNumCalls);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _));
MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
for (int i = 0; i < kNumCalls; i++) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
}
}
@@ -247,14 +290,15 @@ TEST_F(MediaDevicesManagerTest, EnumerateNoCacheVideoInput) {
.Times(kNumCalls);
EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)).Times(0);
EXPECT_CALL(*this, MockCallback(_)).Times(kNumCalls);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _));
MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
for (int i = 0; i < kNumCalls; i++) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
}
}
@@ -272,8 +316,8 @@ TEST_F(MediaDevicesManagerTest, EnumerateNoCacheAudioOutput) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
}
}
@@ -284,6 +328,7 @@ TEST_F(MediaDevicesManagerTest, EnumerateNoCacheAudio) {
EXPECT_CALL(*audio_manager_, MockGetAudioInputDeviceNames(_))
.Times(kNumCalls);
EXPECT_CALL(*this, MockCallback(_)).Times(kNumCalls);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _));
MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
@@ -291,8 +336,8 @@ TEST_F(MediaDevicesManagerTest, EnumerateNoCacheAudio) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
}
}
@@ -303,6 +348,7 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheAudio) {
.Times(0);
EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)).Times(1);
EXPECT_CALL(*this, MockCallback(_)).Times(kNumCalls);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _));
EnableCache(MEDIA_DEVICE_TYPE_AUDIO_INPUT);
EnableCache(MEDIA_DEVICE_TYPE_AUDIO_OUTPUT);
MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
@@ -312,8 +358,8 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheAudio) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
}
}
@@ -324,6 +370,7 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheVideo) {
.Times(1);
EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)).Times(0);
EXPECT_CALL(*this, MockCallback(_)).Times(kNumCalls);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _));
EnableCache(MEDIA_DEVICE_TYPE_VIDEO_INPUT);
MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
@@ -331,22 +378,22 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheVideo) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
}
}
TEST_F(MediaDevicesManagerTest, EnumerateCacheAudioWithDeviceChanges) {
MediaDeviceEnumeration enumeration;
- EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)).Times(2);
+ EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)).Times(3);
EXPECT_CALL(*video_capture_device_factory_, MockGetDeviceDescriptors())
.Times(0);
- EXPECT_CALL(*audio_manager_, MockGetAudioInputDeviceNames(_)).Times(2);
+ EXPECT_CALL(*audio_manager_, MockGetAudioInputDeviceNames(_)).Times(3);
EXPECT_CALL(*this, MockCallback(_))
- .Times(2 * kNumCalls)
+ .Times(3 * kNumCalls)
.WillRepeatedly(SaveArg<0>(&enumeration));
-
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _));
size_t num_audio_input_devices = 5;
size_t num_audio_output_devices = 3;
audio_manager_->SetNumAudioInputDevices(num_audio_input_devices);
@@ -360,8 +407,8 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheAudioWithDeviceChanges) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
EXPECT_EQ(num_audio_input_devices,
enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT].size());
@@ -369,19 +416,49 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheAudioWithDeviceChanges) {
enumeration[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT].size());
}
- // Simulate device change
+ // Simulate removal of devices.
+ size_t old_num_audio_input_devices = num_audio_input_devices;
num_audio_input_devices = 3;
- num_audio_output_devices = 4;
+ num_audio_output_devices = 2;
+ ASSERT_LT(num_audio_input_devices, old_num_audio_input_devices);
+ size_t num_removed_audio_input_devices =
+ old_num_audio_input_devices - num_audio_input_devices;
+ EXPECT_CALL(media_devices_manager_client_, StopRemovedInputDevice(_, _))
+ .Times(num_removed_audio_input_devices);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _));
+
audio_manager_->SetNumAudioInputDevices(num_audio_input_devices);
audio_manager_->SetNumAudioOutputDevices(num_audio_output_devices);
media_devices_manager_->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO);
+ for (int i = 0; i < kNumCalls; i++) {
+ base::RunLoop run_loop;
+ media_devices_manager_->EnumerateDevices(
+ devices_to_enumerate,
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
+ run_loop.Run();
+ EXPECT_EQ(num_audio_input_devices,
+ enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT].size());
+ EXPECT_EQ(num_audio_output_devices,
+ enumeration[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT].size());
+ }
+
+ // Simulate addition of devices.
+ old_num_audio_input_devices = num_audio_input_devices;
+ num_audio_input_devices = 4;
+ num_audio_output_devices = 3;
+ ASSERT_GT(num_audio_input_devices, old_num_audio_input_devices);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _));
+ audio_manager_->SetNumAudioInputDevices(num_audio_input_devices);
+ audio_manager_->SetNumAudioOutputDevices(num_audio_output_devices);
+ media_devices_manager_->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO);
for (int i = 0; i < kNumCalls; i++) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
EXPECT_EQ(num_audio_input_devices,
enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT].size());
@@ -394,13 +471,14 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheVideoWithDeviceChanges) {
MediaDeviceEnumeration enumeration;
EXPECT_CALL(*audio_manager_, MockGetAudioOutputDeviceNames(_)).Times(0);
EXPECT_CALL(*video_capture_device_factory_, MockGetDeviceDescriptors())
- .Times(2);
+ .Times(3);
EXPECT_CALL(*audio_manager_, MockGetAudioInputDeviceNames(_)).Times(0);
EXPECT_CALL(*this, MockCallback(_))
- .Times(2 * kNumCalls)
+ .Times(3 * kNumCalls)
.WillRepeatedly(SaveArg<0>(&enumeration));
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _));
- // Simulate device change
+ // First enumeration.
size_t num_video_input_devices = 5;
video_capture_device_factory_->SetToDefaultDevicesConfig(
num_video_input_devices);
@@ -411,15 +489,43 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheVideoWithDeviceChanges) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
EXPECT_EQ(num_video_input_devices,
enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT].size());
}
- // Simulate device change
+ // Simulate addition of devices.
+ size_t old_num_video_input_devices = num_video_input_devices;
num_video_input_devices = 9;
+ ASSERT_GT(num_video_input_devices, old_num_video_input_devices);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _));
+ video_capture_device_factory_->SetToDefaultDevicesConfig(
+ num_video_input_devices);
+ media_devices_manager_->OnDevicesChanged(
+ base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
+
+ for (int i = 0; i < kNumCalls; i++) {
+ base::RunLoop run_loop;
+ media_devices_manager_->EnumerateDevices(
+ devices_to_enumerate,
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
+ run_loop.Run();
+ EXPECT_EQ(num_video_input_devices,
+ enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT].size());
+ }
+
+ // Simulate removal of devices.
+ old_num_video_input_devices = num_video_input_devices;
+ num_video_input_devices = 7;
+ ASSERT_LT(num_video_input_devices, old_num_video_input_devices);
+ size_t num_removed_video_input_devices =
+ old_num_video_input_devices - num_video_input_devices;
+ EXPECT_CALL(media_devices_manager_client_, StopRemovedInputDevice(_, _))
+ .Times(num_removed_video_input_devices);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _));
video_capture_device_factory_->SetToDefaultDevicesConfig(
num_video_input_devices);
media_devices_manager_->OnDevicesChanged(
@@ -429,8 +535,8 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheVideoWithDeviceChanges) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
EXPECT_EQ(num_video_input_devices,
enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT].size());
@@ -446,6 +552,8 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheAllWithDeviceChanges) {
EXPECT_CALL(*this, MockCallback(_))
.Times(2 * kNumCalls)
.WillRepeatedly(SaveArg<0>(&enumeration));
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _))
+ .Times(2);
size_t num_audio_input_devices = 5;
size_t num_video_input_devices = 4;
@@ -465,8 +573,8 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheAllWithDeviceChanges) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
EXPECT_EQ(num_audio_input_devices,
enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT].size());
@@ -477,9 +585,20 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheAllWithDeviceChanges) {
}
// Simulate device changes
+ size_t old_num_audio_input_devices = num_audio_input_devices;
+ size_t old_num_video_input_devices = num_video_input_devices;
num_audio_input_devices = 3;
num_video_input_devices = 2;
num_audio_output_devices = 4;
+ ASSERT_LT(num_audio_input_devices, old_num_audio_input_devices);
+ ASSERT_LT(num_video_input_devices, old_num_video_input_devices);
+ size_t num_removed_input_devices =
+ old_num_audio_input_devices - num_audio_input_devices +
+ old_num_video_input_devices - num_video_input_devices;
+ EXPECT_CALL(media_devices_manager_client_, StopRemovedInputDevice(_, _))
+ .Times(num_removed_input_devices);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _))
+ .Times(2);
audio_manager_->SetNumAudioInputDevices(num_audio_input_devices);
video_capture_device_factory_->SetToDefaultDevicesConfig(
num_video_input_devices);
@@ -492,8 +611,8 @@ TEST_F(MediaDevicesManagerTest, EnumerateCacheAllWithDeviceChanges) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
EXPECT_EQ(num_audio_input_devices,
enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT].size());
@@ -509,6 +628,8 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
EXPECT_CALL(*video_capture_device_factory_, MockGetDeviceDescriptors())
.Times(3);
EXPECT_CALL(*audio_manager_, MockGetAudioInputDeviceNames(_)).Times(3);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _))
+ .Times(2);
size_t num_audio_input_devices = 5;
size_t num_video_input_devices = 4;
@@ -528,8 +649,8 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
base::RunLoop run_loop;
media_devices_manager_->EnumerateDevices(
devices_to_enumerate,
- base::Bind(&MediaDevicesManagerTest::EnumerateCallback,
- base::Unretained(this), &run_loop));
+ base::BindOnce(&MediaDevicesManagerTest::EnumerateCallback,
+ base::Unretained(this), &run_loop));
run_loop.Run();
// Add device-change event listeners.
@@ -595,9 +716,20 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
.WillRepeatedly(SaveArg<1>(&notification_all_audio_output));
// Simulate device changes.
+ size_t old_num_audio_input_devices = num_audio_input_devices;
+ size_t old_num_video_input_devices = num_video_input_devices;
num_audio_input_devices = 3;
num_video_input_devices = 2;
num_audio_output_devices = 4;
+ ASSERT_LT(num_audio_input_devices, old_num_audio_input_devices);
+ ASSERT_LT(num_video_input_devices, old_num_video_input_devices);
+ size_t num_removed_input_devices =
+ old_num_audio_input_devices - num_audio_input_devices +
+ old_num_video_input_devices - num_video_input_devices;
+ EXPECT_CALL(media_devices_manager_client_, StopRemovedInputDevice(_, _))
+ .Times(num_removed_input_devices);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _))
+ .Times(2);
audio_manager_->SetNumAudioInputDevices(num_audio_input_devices);
video_capture_device_factory_->SetToDefaultDevicesConfig(
num_video_input_devices);
@@ -626,9 +758,20 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
// Simulate further device changes. Only the objects still subscribed to the
// device-change events will receive notifications.
+ old_num_audio_input_devices = num_audio_input_devices;
+ old_num_video_input_devices = num_video_input_devices;
num_audio_input_devices = 2;
num_video_input_devices = 1;
num_audio_output_devices = 3;
+ ASSERT_LT(num_audio_input_devices, old_num_audio_input_devices);
+ ASSERT_LT(num_video_input_devices, old_num_video_input_devices);
+ num_removed_input_devices =
+ old_num_audio_input_devices - num_audio_input_devices +
+ old_num_video_input_devices - num_video_input_devices;
+ EXPECT_CALL(media_devices_manager_client_, StopRemovedInputDevice(_, _))
+ .Times(num_removed_input_devices);
+ EXPECT_CALL(media_devices_manager_client_, InputDevicesChangedUI(_, _))
+ .Times(2);
audio_manager_->SetNumAudioInputDevices(num_audio_input_devices);
video_capture_device_factory_->SetToDefaultDevicesConfig(
num_video_input_devices);
@@ -645,6 +788,49 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
notification_all_audio_output});
}
+TEST_F(MediaDevicesManagerTest, EnumerateDevicesWithCapabilities) {
+ // Audio is enumerated due to heuristics to compute video group IDs.
+ EXPECT_CALL(*audio_manager_, MockGetAudioInputDeviceNames(_));
+ EXPECT_CALL(media_devices_manager_client_,
+ InputDevicesChangedUI(MEDIA_DEVICE_TYPE_AUDIO_INPUT, _));
+ EXPECT_CALL(*video_capture_device_factory_, MockGetDeviceDescriptors());
+ EXPECT_CALL(media_devices_manager_client_,
+ InputDevicesChangedUI(MEDIA_DEVICE_TYPE_VIDEO_INPUT, _));
+ // Configure fake devices with video formats different from the fallback
+ // formats to make sure that expected capabilities are what devices actually
+ // report.
+ media::FakeVideoCaptureDeviceSettings fake_device1;
+ fake_device1.device_id = "fake_id_1";
+ fake_device1.delivery_mode =
+ media::FakeVideoCaptureDevice::DeliveryMode::USE_DEVICE_INTERNAL_BUFFERS;
+ fake_device1.supported_formats = {
+ {{1000, 1000}, 60.0, media::PIXEL_FORMAT_I420},
+ {{2000, 2000}, 120.0, media::PIXEL_FORMAT_I420}};
+
+ media::FakeVideoCaptureDeviceSettings fake_device2;
+ fake_device2.device_id = "fake_id_2";
+ fake_device2.delivery_mode =
+ media::FakeVideoCaptureDevice::DeliveryMode::USE_DEVICE_INTERNAL_BUFFERS;
+ fake_device2.supported_formats = {
+ {{100, 100}, 6.0, media::PIXEL_FORMAT_I420},
+ {{200, 200}, 12.0, media::PIXEL_FORMAT_I420}};
+
+ std::vector<media::FakeVideoCaptureDeviceSettings>
+ fake_capture_device_settings = {fake_device1, fake_device2};
+ video_capture_device_factory_->SetToCustomDevicesConfig(
+ fake_capture_device_settings);
+
+ MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
+ base::RunLoop run_loop;
+ media_devices_manager_->EnumerateDevices(
+ -1, -1, devices_to_enumerate, true,
+ base::BindOnce(
+ &MediaDevicesManagerTest::EnumerateWithCapabilitiesCallback,
+ base::Unretained(this), fake_capture_device_settings, &run_loop));
+ run_loop.Run();
+}
+
TEST_F(MediaDevicesManagerTest, GuessVideoGroupID) {
MediaDeviceInfoArray audio_devices = {
{media::AudioDeviceDescription::kDefaultDeviceId,
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 6f59da110bf..71f785312be 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -36,6 +36,7 @@
#include "content/browser/renderer_host/media/media_devices_manager.h"
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
#include "content/browser/renderer_host/media/service_video_capture_provider.h"
+#include "content/browser/renderer_host/media/video_capture_dependencies.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/browser/renderer_host/media/video_capture_provider_switcher.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -54,7 +55,7 @@
#include "media/base/audio_parameters.h"
#include "media/base/channel_layout.h"
#include "media/base/media_switches.h"
-#include "media/capture/video/video_capture_device_factory.h"
+#include "media/capture/video/create_video_capture_device_factory.h"
#include "media/capture/video/video_capture_system_impl.h"
#include "services/video_capture/public/uma/video_capture_service_event.h"
#include "url/gurl.h"
@@ -66,6 +67,9 @@
#if defined(OS_CHROMEOS)
#include "chromeos/audio/cras_audio_handler.h"
+#include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
+#include "media/capture/video/chromeos/public/cros_features.h"
+#include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h"
#endif
namespace content {
@@ -96,42 +100,6 @@ std::string RandomLabel() {
return label;
}
-void CreateJpegDecodeAcceleratorOnIOThread(
- media::mojom::JpegDecodeAcceleratorRequest request) {
- auto* host =
- GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false);
- if (host) {
- host->gpu_service()->CreateJpegDecodeAccelerator(std::move(request));
- } else {
- LOG(ERROR) << "No GpuProcessHost";
- }
-}
-
-void CreateJpegDecodeAccelerator(
- media::mojom::JpegDecodeAcceleratorRequest request) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CreateJpegDecodeAcceleratorOnIOThread,
- std::move(request)));
-}
-
-void CreateJpegEncodeAcceleratorOnIOThread(
- media::mojom::JpegEncodeAcceleratorRequest request) {
- auto* host =
- GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false);
- if (host) {
- host->gpu_service()->CreateJpegEncodeAccelerator(std::move(request));
- } else {
- LOG(ERROR) << "No GpuProcessHost";
- }
-}
-
-void CreateJpegEncodeAccelerator(
- media::mojom::JpegEncodeAcceleratorRequest request) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CreateJpegEncodeAcceleratorOnIOThread,
- std::move(request)));
-}
-
void ParseStreamType(const StreamControls& controls,
MediaStreamType* audio_type,
MediaStreamType* video_type) {
@@ -199,13 +167,6 @@ void EnableHotwordEffect(const StreamControls& controls, int* effects) {
}
}
-bool CalledOnIOThread() {
- // Check if this function call is on the IO thread, except for unittests where
- // an IO thread might not have been created.
- return BrowserThread::CurrentlyOn(BrowserThread::IO) ||
- !BrowserThread::IsThreadInitialized(BrowserThread::IO);
-}
-
bool GetDeviceIDFromHMAC(const std::string& salt,
const url::Origin& security_origin,
const std::string& hmac_device_id,
@@ -502,6 +463,18 @@ MediaStreamManager::MediaStreamManager(
device_task_runner = video_capture_thread_->task_runner();
}
+#if defined(OS_CHROMEOS)
+ if (media::ShouldUseCrosCameraService()) {
+ media::VideoCaptureDeviceFactoryChromeOS::SetGpuBufferManager(
+ BrowserGpuMemoryBufferManager::current());
+ media::CameraHalDispatcherImpl::GetInstance()->Start(
+ base::BindRepeating(
+ &VideoCaptureDependencies::CreateJpegDecodeAccelerator),
+ base::BindRepeating(
+ &VideoCaptureDependencies::CreateJpegEncodeAccelerator));
+ }
+#endif
+
if (base::FeatureList::IsEnabled(features::kMojoVideoCapture)) {
video_capture_provider = std::make_unique<VideoCaptureProviderSwitcher>(
std::make_unique<ServiceVideoCaptureProvider>(
@@ -514,11 +487,8 @@ MediaStreamManager::MediaStreamManager(
video_capture::uma::BROWSER_USING_LEGACY_CAPTURE);
video_capture_provider = InProcessVideoCaptureProvider::CreateInstance(
std::make_unique<media::VideoCaptureSystemImpl>(
- media::VideoCaptureDeviceFactory::CreateFactory(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
- BrowserGpuMemoryBufferManager::current(),
- base::BindRepeating(&CreateJpegDecodeAccelerator),
- base::BindRepeating(&CreateJpegEncodeAccelerator))),
+ media::CreateVideoCaptureDeviceFactory(
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))),
std::move(device_task_runner),
base::BindRepeating(&SendVideoCaptureLogMessage));
}
@@ -767,6 +737,7 @@ int MediaStreamManager::VideoDeviceIdToSessionId(
}
void MediaStreamManager::StopDevice(MediaStreamType type, int session_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "StopDevice"
<< "{type = " << type << "}"
<< "{session_id = " << session_id << "}";
@@ -805,6 +776,7 @@ void MediaStreamManager::StopDevice(MediaStreamType type, int session_id) {
}
void MediaStreamManager::CloseDevice(MediaStreamType type, int session_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "CloseDevice("
<< "{type = " << type << "} "
<< "{session_id = " << session_id << "})";
@@ -1016,6 +988,7 @@ std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
MediaStreamManager::DeviceRequest* MediaStreamManager::FindRequest(
const std::string& label) const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
for (const LabeledDeviceRequest& labeled_request : requests_) {
if (labeled_request.first == label)
return labeled_request.second;
@@ -1024,6 +997,7 @@ MediaStreamManager::DeviceRequest* MediaStreamManager::FindRequest(
}
void MediaStreamManager::DeleteRequest(const std::string& label) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "DeleteRequest({label= " << label << "})";
for (DeviceRequests::iterator request_it = requests_.begin();
request_it != requests_.end(); ++request_it) {
@@ -1052,23 +1026,26 @@ void MediaStreamManager::ReadOutputParamsAndPostRequestToUI(
audio_system_->GetOutputStreamParameters(
media::AudioDeviceDescription::kDefaultDeviceId,
base::BindOnce(&MediaStreamManager::PostRequestToUI,
- base::Unretained(this), label, request, enumeration));
+ base::Unretained(this), label, enumeration));
} else {
- PostRequestToUI(label, request, enumeration,
+ PostRequestToUI(label, enumeration,
base::Optional<media::AudioParameters>());
}
}
void MediaStreamManager::PostRequestToUI(
const std::string& label,
- DeviceRequest* request,
const MediaDeviceEnumeration& enumeration,
const base::Optional<media::AudioParameters>& output_parameters) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(request->HasUIRequest());
DCHECK(!output_parameters || output_parameters->IsValid());
DVLOG(1) << "PostRequestToUI({label= " << label << "})";
+ DeviceRequest* request = FindRequest(label);
+ if (!request)
+ return;
+ DCHECK(request->HasUIRequest());
+
const MediaStreamType audio_type = request->audio_type();
const MediaStreamType video_type = request->video_type();
@@ -1254,6 +1231,7 @@ bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) {
MediaStreamDevices MediaStreamManager::GetDevicesOpenedByRequest(
const std::string& label) const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DeviceRequest* request = FindRequest(label);
if (!request)
return MediaStreamDevices();
@@ -1265,6 +1243,7 @@ bool MediaStreamManager::FindExistingRequestedDevice(
const MediaStreamDevice& new_device,
MediaStreamDevice* existing_device,
MediaRequestState* existing_request_state) const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(existing_device);
DCHECK(existing_request_state);
@@ -1364,6 +1343,7 @@ void MediaStreamManager::FinalizeMediaAccessRequest(
const std::string& label,
DeviceRequest* request,
const MediaStreamDevices& devices) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(request->media_access_request_cb);
std::move(request->media_access_request_cb)
.Run(devices, std::move(request->ui_proxy));
@@ -1405,8 +1385,14 @@ void MediaStreamManager::InitializeMaybeAsync(
base::BindRepeating(&SendVideoCaptureLogMessage));
video_capture_manager_->RegisterListener(this);
- media_devices_manager_.reset(
- new MediaDevicesManager(audio_system_, video_capture_manager_, this));
+ // Using base::Unretained(this) is safe because |this| owns and therefore
+ // outlives |media_devices_manager_|.
+ media_devices_manager_.reset(new MediaDevicesManager(
+ audio_system_, video_capture_manager_,
+ base::BindRepeating(&MediaStreamManager::StopRemovedDevice,
+ base::Unretained(this)),
+ base::BindRepeating(&MediaStreamManager::NotifyDevicesChanged,
+ base::Unretained(this))));
}
void MediaStreamManager::Opened(MediaStreamType stream_type,
@@ -1689,7 +1675,8 @@ void MediaStreamManager::StopMediaStreamFromBrowser(const std::string& label) {
void MediaStreamManager::WillDestroyCurrentMessageLoop() {
DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()";
- DCHECK(CalledOnIOThread());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) ||
+ !BrowserThread::IsThreadInitialized(BrowserThread::IO));
if (media_devices_manager_)
media_devices_manager_->StopMonitoring();
if (video_capture_manager_)
@@ -1898,6 +1885,7 @@ MediaStreamDevices MediaStreamManager::ConvertToMediaStreamDevices(
}
void MediaStreamManager::OnStreamStarted(const std::string& label) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DeviceRequest* const request = FindRequest(label);
if (!request)
return;
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 82fee09f21e..c73c8d60c26 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.h
@@ -175,19 +175,22 @@ class CONTENT_EXPORT MediaStreamManager
GenerateStreamCallback generate_stream_cb,
DeviceStoppedCallback device_stopped_cb);
+ // Cancel an open request identified by |page_request_id| for the given frame.
+ // Must be called on the IO thread.
void CancelRequest(int render_process_id,
int render_frame_id,
int page_request_id);
- // Cancel an open request identified by |label|.
+ // Cancel an open request identified by |label|. Must be called on the IO
+ // thread.
void CancelRequest(const std::string& label);
// Cancel all requests for the given |render_process_id| and
- // |render_frame_id|.
+ // |render_frame_id|. Must be called on the IO thread.
void CancelAllRequests(int render_process_id, int render_frame_id);
// Closes the stream device for a certain render frame. The stream must have
- // been opened by a call to GenerateStream.
+ // been opened by a call to GenerateStream. Must be called on the IO thread.
void StopStreamDevice(int render_process_id,
int render_frame_id,
const std::string& device_id,
@@ -218,7 +221,7 @@ class CONTENT_EXPORT MediaStreamManager
std::string* device_id) const;
// Find |device_id| in the list of |requests_|, and returns its session id,
- // or MediaStreamDevice::kNoId if not found.
+ // or MediaStreamDevice::kNoId if not found. Must be called on the IO thread.
int VideoDeviceIdToSessionId(const std::string& device_id) const;
// Called by UI to make sure the device monitor is started so that UI receive
@@ -283,6 +286,7 @@ class CONTENT_EXPORT MediaStreamManager
// Set whether the capturing is secure for the capturing session with given
// |session_id|, |render_process_id|, and the MediaStreamType |type|.
+ // Must be called on the IO thread.
void SetCapturingLinkSecured(int render_process_id,
int session_id,
content::MediaStreamType type,
@@ -295,7 +299,7 @@ class CONTENT_EXPORT MediaStreamManager
// This method is called when an audio or video device is removed. It makes
// sure all MediaStreams that use a removed device are stopped and that the
- // render process is notified.
+ // render process is notified. Must be called on the IO thread.
void StopRemovedDevice(MediaDeviceType type,
const MediaDeviceInfo& media_device_info);
@@ -370,7 +374,6 @@ class CONTENT_EXPORT MediaStreamManager
// Called when audio output parameters have been read if needed.
void PostRequestToUI(
const std::string& label,
- DeviceRequest* request,
const MediaDeviceEnumeration& enumeration,
const base::Optional<media::AudioParameters>& output_parameters);
// Returns true if a device with |device_id| has already been requested with
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 a9a89760950..0acf2f42c16 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
@@ -30,9 +30,13 @@ namespace content {
namespace {
class MockRenderFrameHostDelegate : public RenderFrameHostDelegate {
public:
+ void RequestMediaAccessPermission(const MediaStreamRequest& request,
+ MediaResponseCallback callback) {
+ return RequestMediaAccessPermission(request, &callback);
+ }
MOCK_METHOD2(RequestMediaAccessPermission,
void(const MediaStreamRequest& request,
- const MediaResponseCallback& callback));
+ MediaResponseCallback* callback));
MOCK_METHOD3(CheckMediaAccessPermission,
bool(RenderFrameHost* render_frame_host,
const url::Origin& security_origin,
@@ -122,14 +126,17 @@ TEST_F(MediaStreamUIProxyTest, MAYBE_Deny) {
base::BindOnce(&MockResponseCallback::OnAccessRequestResponse,
base::Unretained(&response_callback_)));
MediaResponseCallback callback;
- EXPECT_CALL(delegate_, RequestMediaAccessPermission(SameRequest(request_ptr),
- _))
- .WillOnce(SaveArg<1>(&callback));
+ EXPECT_CALL(delegate_,
+ RequestMediaAccessPermission(SameRequest(request_ptr), _))
+ .WillOnce([&](testing::Unused, MediaResponseCallback* cb) {
+ callback = std::move(*cb);
+ });
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(callback.is_null());
MediaStreamDevices devices;
- callback.Run(devices, MEDIA_DEVICE_OK, std::unique_ptr<MediaStreamUI>());
+ std::move(callback).Run(devices, MEDIA_DEVICE_OK,
+ std::unique_ptr<MediaStreamUI>());
MediaStreamDevices response;
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _))
@@ -150,9 +157,11 @@ TEST_F(MediaStreamUIProxyTest, MAYBE_AcceptAndStart) {
base::BindOnce(&MockResponseCallback::OnAccessRequestResponse,
base::Unretained(&response_callback_)));
MediaResponseCallback callback;
- EXPECT_CALL(delegate_, RequestMediaAccessPermission(SameRequest(request_ptr),
- _))
- .WillOnce(SaveArg<1>(&callback));
+ EXPECT_CALL(delegate_,
+ RequestMediaAccessPermission(SameRequest(request_ptr), _))
+ .WillOnce([&](testing::Unused, MediaResponseCallback* cb) {
+ callback = std::move(*cb);
+ });
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(callback.is_null());
@@ -161,7 +170,7 @@ TEST_F(MediaStreamUIProxyTest, MAYBE_AcceptAndStart) {
MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, "Mic", "Mic"));
std::unique_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
EXPECT_CALL(*ui, OnStarted(_)).WillOnce(Return(0));
- callback.Run(devices, MEDIA_DEVICE_OK, std::move(ui));
+ std::move(callback).Run(devices, MEDIA_DEVICE_OK, std::move(ui));
MediaStreamDevices response;
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _))
@@ -186,9 +195,11 @@ TEST_F(MediaStreamUIProxyTest, MAYBE_DeleteBeforeAccepted) {
base::BindOnce(&MockResponseCallback::OnAccessRequestResponse,
base::Unretained(&response_callback_)));
MediaResponseCallback callback;
- EXPECT_CALL(delegate_, RequestMediaAccessPermission(SameRequest(request_ptr)
- , _))
- .WillOnce(SaveArg<1>(&callback));
+ EXPECT_CALL(delegate_,
+ RequestMediaAccessPermission(SameRequest(request_ptr), _))
+ .WillOnce([&](testing::Unused, MediaResponseCallback* cb) {
+ callback = std::move(*cb);
+ });
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(callback.is_null());
@@ -196,7 +207,7 @@ TEST_F(MediaStreamUIProxyTest, MAYBE_DeleteBeforeAccepted) {
MediaStreamDevices devices;
std::unique_ptr<MediaStreamUI> ui;
- callback.Run(devices, MEDIA_DEVICE_OK, std::move(ui));
+ std::move(callback).Run(devices, MEDIA_DEVICE_OK, std::move(ui));
}
TEST_F(MediaStreamUIProxyTest, MAYBE_StopFromUI) {
@@ -210,9 +221,11 @@ TEST_F(MediaStreamUIProxyTest, MAYBE_StopFromUI) {
base::BindOnce(&MockResponseCallback::OnAccessRequestResponse,
base::Unretained(&response_callback_)));
MediaResponseCallback callback;
- EXPECT_CALL(delegate_, RequestMediaAccessPermission(SameRequest(request_ptr)
- , _))
- .WillOnce(SaveArg<1>(&callback));
+ EXPECT_CALL(delegate_,
+ RequestMediaAccessPermission(SameRequest(request_ptr), _))
+ .WillOnce([&](testing::Unused, MediaResponseCallback* cb) {
+ callback = std::move(*cb);
+ });
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(callback.is_null());
@@ -224,7 +237,7 @@ TEST_F(MediaStreamUIProxyTest, MAYBE_StopFromUI) {
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));
+ std::move(callback).Run(devices, MEDIA_DEVICE_OK, std::move(ui));
MediaStreamDevices response;
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _))
@@ -257,16 +270,18 @@ TEST_F(MediaStreamUIProxyTest, MAYBE_WindowIdCallbackCalled) {
base::BindOnce(&MockResponseCallback::OnAccessRequestResponse,
base::Unretained(&response_callback_)));
MediaResponseCallback callback;
- EXPECT_CALL(delegate_, RequestMediaAccessPermission(SameRequest(request_ptr),
- _))
- .WillOnce(SaveArg<1>(&callback));
+ EXPECT_CALL(delegate_,
+ RequestMediaAccessPermission(SameRequest(request_ptr), _))
+ .WillOnce([&](testing::Unused, MediaResponseCallback* cb) {
+ callback = std::move(*cb);
+ });
base::RunLoop().RunUntilIdle();
const int kWindowId = 1;
std::unique_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
EXPECT_CALL(*ui, OnStarted(_)).WillOnce(Return(kWindowId));
- callback.Run(MediaStreamDevices(), MEDIA_DEVICE_OK, std::move(ui));
+ std::move(callback).Run(MediaStreamDevices(), MEDIA_DEVICE_OK, std::move(ui));
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _));
MockStopStreamHandler handler;
@@ -332,9 +347,8 @@ class MediaStreamUIProxyFeaturePolicyTest
private:
class TestRFHDelegate : public RenderFrameHostDelegate {
- void RequestMediaAccessPermission(
- const MediaStreamRequest& request,
- const MediaResponseCallback& callback) override {
+ void RequestMediaAccessPermission(const MediaStreamRequest& request,
+ MediaResponseCallback callback) override {
MediaStreamDevices devices;
if (request.audio_type == MEDIA_DEVICE_AUDIO_CAPTURE) {
devices.push_back(
@@ -345,7 +359,7 @@ class MediaStreamUIProxyFeaturePolicyTest
MediaStreamDevice(MEDIA_DEVICE_VIDEO_CAPTURE, "Camera", "Camera"));
}
std::unique_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
- callback.Run(devices, MEDIA_DEVICE_OK, std::move(ui));
+ std::move(callback).Run(devices, MEDIA_DEVICE_OK, std::move(ui));
}
};
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc
index 0252b256dbd..6e33963efe7 100644
--- a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc
@@ -46,8 +46,8 @@ void OldEnumerateOutputDevices(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
MediaDevicesManager::BoolDeviceTypes device_types;
device_types[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
- media_devices_manager->EnumerateDevices(
- device_types, base::BindRepeating(cb, salt_and_origin));
+ media_devices_manager->EnumerateDevices(device_types,
+ base::BindOnce(cb, salt_and_origin));
}
} // namespace
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc
index 206fa9c9755..fb2e934df02 100644
--- a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc
@@ -78,7 +78,7 @@ class MockRendererAudioInputStreamFactoryClient
void StreamCreated(
media::mojom::AudioInputStreamPtr input_stream,
media::mojom::AudioInputStreamClientRequest client_request,
- media::mojom::AudioDataPipePtr data_pipe,
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
bool initially_muted,
const base::Optional<base::UnguessableToken>& stream_id) override {
EXPECT_TRUE(stream_id.has_value());
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc b/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc
index 94a1fb4c25a..b4f527af64f 100644
--- a/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc
@@ -178,7 +178,7 @@ class MockClient : public AudioOutputStreamProviderClient {
}
void Created(AudioOutputStreamPtr stream,
- media::mojom::AudioDataPipePtr data_pipe) override {
+ media::mojom::ReadWriteAudioDataPipePtr data_pipe) override {
was_called_ = true;
stream_ = std::move(stream);
}
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 9dccd399f82..2e3d9fd57ce 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
@@ -62,16 +62,19 @@ void PeerConnectionTrackerHost::OnChannelClosing() {
void PeerConnectionTrackerHost::OnAddPeerConnection(
const PeerConnectionInfo& info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
WebRTCInternals* webrtc_internals = WebRTCInternals::GetInstance();
if (webrtc_internals) {
webrtc_internals->OnAddPeerConnection(
render_process_id_, peer_pid(), info.lid, info.url,
info.rtc_configuration, info.constraints);
}
+
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
logger->PeerConnectionAdded(render_process_id_, info.lid,
- info.peer_connection_id);
+ info.peer_connection_id,
+ base::OnceCallback<void(bool)>());
}
}
@@ -89,7 +92,8 @@ void PeerConnectionTrackerHost::RemovePeerConnection(int lid) {
}
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
- logger->PeerConnectionRemoved(render_process_id_, lid);
+ logger->PeerConnectionRemoved(render_process_id_, lid,
+ base::OnceCallback<void(bool)>());
}
}
@@ -107,7 +111,8 @@ void PeerConnectionTrackerHost::UpdatePeerConnection(int lid,
if (type == "stop") {
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
- logger->PeerConnectionStopped(render_process_id_, lid);
+ logger->PeerConnectionStopped(render_process_id_, lid,
+ base::OnceCallback<void(bool)>());
}
}
@@ -157,7 +162,9 @@ void PeerConnectionTrackerHost::WebRtcEventLogWrite(int lid,
}
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
- logger->OnWebRtcEventLogWrite(render_process_id_, lid, output);
+ logger->OnWebRtcEventLogWrite(
+ render_process_id_, lid, output,
+ base::OnceCallback<void(std::pair<bool, bool>)>());
}
}
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc
index 7a264cbd8cd..a07394101ea 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc
@@ -4,6 +4,7 @@
#include "content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h"
+#include <string>
#include <utility>
#include "base/trace_event/trace_event.h"
@@ -45,8 +46,8 @@ void EnumerateOutputDevices(MediaStreamManager* media_stream_manager,
DCHECK_CURRENTLY_ON(BrowserThread::IO);
MediaDevicesManager::BoolDeviceTypes device_types;
device_types[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
- media_stream_manager->media_devices_manager()->EnumerateDevices(device_types,
- cb);
+ media_stream_manager->media_devices_manager()->EnumerateDevices(
+ device_types, std::move(cb));
}
void TranslateDeviceId(const std::string& device_id,
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc
index 312193601b3..0a78c678b37 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc
@@ -127,7 +127,7 @@ class RenderFrameAudioInputStreamFactoryTest
void StreamCreated(
media::mojom::AudioInputStreamPtr stream,
media::mojom::AudioInputStreamClientRequest client_request,
- media::mojom::AudioDataPipePtr data_pipe,
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
bool initially_muted,
const base::Optional<base::UnguessableToken>& stream_id) override {}
};
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc
index f54b3f57900..2c04a18d030 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc
@@ -40,6 +40,7 @@ class MockDeviceFactory : public video_capture::mojom::DeviceFactory {
void AddSharedMemoryVirtualDevice(
const media::VideoCaptureDeviceInfo& device_info,
video_capture::mojom::ProducerPtr producer,
+ bool send_buffer_handles_to_producer_as_raw_file_descriptors,
video_capture::mojom::SharedMemoryVirtualDeviceRequest virtual_device)
override {
DoAddVirtualDevice(device_info, producer.get(), &virtual_device);
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_provider.cc b/chromium/content/browser/renderer_host/media/service_video_capture_provider.cc
index 1211057d4b8..52ae899701f 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_provider.cc
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_provider.cc
@@ -4,11 +4,15 @@
#include "content/browser/renderer_host/media/service_video_capture_provider.h"
+#include "content/browser/gpu/gpu_client_impl.h"
#include "content/browser/renderer_host/media/service_video_capture_device_launcher.h"
+#include "content/browser/renderer_host/media/video_capture_dependencies.h"
#include "content/browser/renderer_host/media/video_capture_factory_delegate.h"
+#include "content/common/child_process_host_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/service_manager_connection.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/video_capture/public/mojom/constants.mojom.h"
#include "services/video_capture/public/uma/video_capture_service_event.h"
@@ -19,7 +23,7 @@ class ServiceConnectorImpl
: public content::ServiceVideoCaptureProvider::ServiceConnector {
public:
ServiceConnectorImpl() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// In unit test environments, there may not be any connector.
auto* connection = content::ServiceManagerConnection::GetForProcess();
if (!connection)
@@ -44,34 +48,51 @@ class ServiceConnectorImpl
std::unique_ptr<service_manager::Connector> connector_;
};
+class DelegateToBrowserGpuServiceAcceleratorFactory
+ : public video_capture::mojom::AcceleratorFactory {
+ public:
+ void CreateJpegDecodeAccelerator(
+ media::mojom::JpegDecodeAcceleratorRequest jda_request) override {
+ content::VideoCaptureDependencies::CreateJpegDecodeAccelerator(
+ std::move(jda_request));
+ }
+};
+
+std::unique_ptr<video_capture::mojom::AcceleratorFactory>
+CreateAcceleratorFactory() {
+ return std::make_unique<DelegateToBrowserGpuServiceAcceleratorFactory>();
+}
+
} // anonymous namespace
namespace content {
ServiceVideoCaptureProvider::ServiceVideoCaptureProvider(
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb)
- : ServiceVideoCaptureProvider(std::make_unique<ServiceConnectorImpl>(),
- std::move(emit_log_message_cb)) {}
+ : ServiceVideoCaptureProvider(
+ std::make_unique<ServiceConnectorImpl>(),
+ base::BindRepeating(&CreateAcceleratorFactory),
+ std::move(emit_log_message_cb)) {}
ServiceVideoCaptureProvider::ServiceVideoCaptureProvider(
std::unique_ptr<ServiceConnector> service_connector,
+ CreateAcceleratorFactoryCallback create_accelerator_factory_cb,
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb)
: service_connector_(std::move(service_connector)),
+ create_accelerator_factory_cb_(std::move(create_accelerator_factory_cb)),
emit_log_message_cb_(std::move(emit_log_message_cb)),
usage_count_(0),
launcher_has_connected_to_device_factory_(false),
- weak_ptr_factory_(this) {
- DETACH_FROM_SEQUENCE(sequence_checker_);
-}
+ weak_ptr_factory_(this) {}
ServiceVideoCaptureProvider::~ServiceVideoCaptureProvider() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
UninitializeInternal(ReasonForUninitialize::kShutdown);
}
void ServiceVideoCaptureProvider::GetDeviceInfosAsync(
GetDeviceInfosCallback result_callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
emit_log_message_cb_.Run("ServiceVideoCaptureProvider::GetDeviceInfosAsync");
IncreaseUsageCount();
LazyConnectToService();
@@ -86,7 +107,7 @@ void ServiceVideoCaptureProvider::GetDeviceInfosAsync(
std::unique_ptr<VideoCaptureDeviceLauncher>
ServiceVideoCaptureProvider::CreateDeviceLauncher() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
return std::make_unique<ServiceVideoCaptureDeviceLauncher>(
base::BindRepeating(&ServiceVideoCaptureProvider::ConnectToDeviceFactory,
weak_ptr_factory_.GetWeakPtr()));
@@ -94,7 +115,7 @@ ServiceVideoCaptureProvider::CreateDeviceLauncher() {
void ServiceVideoCaptureProvider::ConnectToDeviceFactory(
std::unique_ptr<VideoCaptureFactoryDelegate>* out_factory) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
IncreaseUsageCount();
LazyConnectToService();
launcher_has_connected_to_device_factory_ = true;
@@ -105,6 +126,7 @@ void ServiceVideoCaptureProvider::ConnectToDeviceFactory(
}
void ServiceVideoCaptureProvider::LazyConnectToService() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (device_factory_provider_.is_bound())
return;
@@ -123,7 +145,12 @@ void ServiceVideoCaptureProvider::LazyConnectToService() {
launcher_has_connected_to_device_factory_ = false;
time_of_last_connect_ = base::TimeTicks::Now();
+ video_capture::mojom::AcceleratorFactoryPtr accelerator_factory;
+ mojo::MakeStrongBinding(create_accelerator_factory_cb_.Run(),
+ mojo::MakeRequest(&accelerator_factory));
service_connector_->BindFactoryProvider(&device_factory_provider_);
+ device_factory_provider_->InjectGpuDependencies(
+ std::move(accelerator_factory));
device_factory_provider_->ConnectToDeviceFactory(
mojo::MakeRequest(&device_factory_));
// Unretained |this| is safe, because |this| owns |device_factory_|.
@@ -135,13 +162,13 @@ void ServiceVideoCaptureProvider::LazyConnectToService() {
void ServiceVideoCaptureProvider::OnDeviceInfosReceived(
GetDeviceInfosCallback result_callback,
const std::vector<media::VideoCaptureDeviceInfo>& infos) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
base::ResetAndReturn(&result_callback).Run(infos);
DecreaseUsageCount();
}
void ServiceVideoCaptureProvider::OnLostConnectionToDeviceFactory() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
emit_log_message_cb_.Run(
"ServiceVideoCaptureProvider::OnLostConnectionToDeviceFactory");
// This may indicate that the video capture service has crashed. Uninitialize
@@ -151,12 +178,12 @@ void ServiceVideoCaptureProvider::OnLostConnectionToDeviceFactory() {
}
void ServiceVideoCaptureProvider::IncreaseUsageCount() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
usage_count_++;
}
void ServiceVideoCaptureProvider::DecreaseUsageCount() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
usage_count_--;
DCHECK_GE(usage_count_, 0);
if (usage_count_ == 0)
@@ -165,7 +192,7 @@ void ServiceVideoCaptureProvider::DecreaseUsageCount() {
void ServiceVideoCaptureProvider::UninitializeInternal(
ReasonForUninitialize reason) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (!device_factory_.is_bound()) {
return;
}
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_provider.h b/chromium/content/browser/renderer_host/media/service_video_capture_provider.h
index 2ee46aae38d..7cc051d35af 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_provider.h
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_provider.h
@@ -27,14 +27,20 @@ class CONTENT_EXPORT ServiceVideoCaptureProvider : public VideoCaptureProvider {
video_capture::mojom::DeviceFactoryProviderPtr* provider) = 0;
};
- // The parameterless constructor creates a default ServiceConnector which
+ using CreateAcceleratorFactoryCallback = base::RepeatingCallback<
+ std::unique_ptr<video_capture::mojom::AcceleratorFactory>()>;
+
+ // This constructor creates a default ServiceConnector which
// uses the ServiceManager associated with the current process to connect
- // to the video capture service.
+ // to the video capture service. It uses a default factory for instances of
+ // ui::mojom::Gpu which produces instances of class content::GpuClient.
explicit ServiceVideoCaptureProvider(
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb);
- // Lets clients provide a custom ServiceConnector.
+ // Lets clients provide a custom ServiceConnector and factory method for
+ // creating instances of ui::mojom::Gpu.
ServiceVideoCaptureProvider(
std::unique_ptr<ServiceConnector> service_connector,
+ CreateAcceleratorFactoryCallback create_accelerator_factory_cb,
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb);
~ServiceVideoCaptureProvider() override;
@@ -56,6 +62,7 @@ class CONTENT_EXPORT ServiceVideoCaptureProvider : public VideoCaptureProvider {
void UninitializeInternal(ReasonForUninitialize reason);
std::unique_ptr<ServiceConnector> service_connector_;
+ CreateAcceleratorFactoryCallback create_accelerator_factory_cb_;
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb_;
// We must hold on to |device_factory_provider_| because it holds the
// service-side binding for |device_factory_|.
@@ -63,7 +70,6 @@ class CONTENT_EXPORT ServiceVideoCaptureProvider : public VideoCaptureProvider {
video_capture::mojom::DeviceFactoryPtr device_factory_;
// Used for automatically uninitializing when no longer in use.
int usage_count_;
- SEQUENCE_CHECKER(sequence_checker_);
bool launcher_has_connected_to_device_factory_;
base::TimeTicks time_of_last_connect_;
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc b/chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc
index 6a683e5f5d1..b080b096ec5 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc
@@ -6,9 +6,9 @@
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
#include "base/threading/thread.h"
#include "content/public/browser/video_capture_device_launcher.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/video_capture/public/mojom/device_factory.mojom.h"
#include "services/video_capture/public/mojom/device_factory_provider.mojom.h"
@@ -44,6 +44,14 @@ class MockDeviceFactoryProvider
DoConnectToDeviceFactory(request);
}
+ void InjectGpuDependencies(video_capture::mojom::AcceleratorFactoryPtr
+ accelerator_factory) override {
+ DoInjectGpuDependencies(accelerator_factory);
+ }
+
+ MOCK_METHOD1(
+ DoInjectGpuDependencies,
+ void(video_capture::mojom::AcceleratorFactoryPtr& accelerator_factory));
MOCK_METHOD1(SetShutdownDelayInSeconds, void(float seconds));
MOCK_METHOD1(DoConnectToDeviceFactory,
void(video_capture::mojom::DeviceFactoryRequest& request));
@@ -62,6 +70,7 @@ class MockDeviceFactory : public video_capture::mojom::DeviceFactory {
void AddSharedMemoryVirtualDevice(
const media::VideoCaptureDeviceInfo& device_info,
video_capture::mojom::ProducerPtr producer,
+ bool send_buffer_handles_to_producer_as_raw_file_descriptors,
video_capture::mojom::SharedMemoryVirtualDeviceRequest virtual_device)
override {
DoAddVirtualDevice(device_info, producer.get(), &virtual_device);
@@ -110,7 +119,10 @@ class ServiceVideoCaptureProviderTest : public testing::Test {
auto mock_service_connector = std::make_unique<MockServiceConnector>();
mock_service_connector_ = mock_service_connector.get();
provider_ = std::make_unique<ServiceVideoCaptureProvider>(
- std::move(mock_service_connector), kIgnoreLogMessageCB);
+ std::move(mock_service_connector), base::BindRepeating([]() {
+ return std::unique_ptr<video_capture::mojom::AcceleratorFactory>();
+ }),
+ kIgnoreLogMessageCB);
ON_CALL(*mock_service_connector_, BindFactoryProvider(_))
.WillByDefault(
@@ -133,7 +145,7 @@ class ServiceVideoCaptureProviderTest : public testing::Test {
void TearDown() override {}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ content::TestBrowserThreadBundle test_browser_thread_bundle_;
MockServiceConnector* mock_service_connector_;
MockDeviceFactoryProvider mock_device_factory_provider_;
mojo::Binding<video_capture::mojom::DeviceFactoryProvider>
diff --git a/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc b/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
index 59b89dc83ae..ee5dd193529 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
@@ -115,6 +115,8 @@ class VideoCaptureBrowserTest : public ContentBrowserTest,
params_ = TestParams(GetParam());
if (params_.use_mojo_service) {
scoped_feature_list_.InitAndEnableFeature(features::kMojoVideoCapture);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(features::kMojoVideoCapture);
}
}
@@ -231,11 +233,6 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest, StartAndImmediatelyStop) {
if (params_.use_mojo_service)
return;
#endif
- // Mojo video capture currently does not support accelerated jpeg decoding.
- // TODO(chfremer): Remove this as soon as https://crbug.com/720604 is
- // resolved.
- if (params_.use_mojo_service && params_.exercise_accelerated_jpeg_decoding)
- return;
SetUpRequiringBrowserMainLoopOnMainThread();
base::RunLoop run_loop;
@@ -274,21 +271,11 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest,
if (params_.use_mojo_service)
return;
#endif
- // Mojo video capture currently does not support accelerated jpeg decoding.
- // TODO(chfremer): Remove this as soon as https://crbug.com/720604 is
- // resolved.
- if (params_.use_mojo_service && params_.exercise_accelerated_jpeg_decoding)
- return;
// Only fake device with index 2 delivers MJPEG.
if (params_.exercise_accelerated_jpeg_decoding &&
- params_.device_index_to_use != 2)
- return;
- // There is an intermittent use-after-free in GpuChannelHost::Send() during
- // Browser shutdown, which causes MSan tests to fail.
- // TODO(chfremer): Remove this as soon as https://crbug.com/725271 is
- // resolved.
- if (params_.exercise_accelerated_jpeg_decoding)
+ params_.device_index_to_use != 2) {
return;
+ }
SetUpRequiringBrowserMainLoopOnMainThread();
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 26a225d1b9f..4a948b2c47f 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -225,7 +225,8 @@ void VideoCaptureController::AddClient(
// report an error immediately and punt.
if (!params.IsValid() ||
!(params.requested_format.pixel_format == media::PIXEL_FORMAT_I420 ||
- params.requested_format.pixel_format == media::PIXEL_FORMAT_Y16)) {
+ params.requested_format.pixel_format == media::PIXEL_FORMAT_Y16 ||
+ params.requested_format.pixel_format == media::PIXEL_FORMAT_ARGB)) {
// Crash in debug builds since the renderer should not have asked for
// invalid or unsupported parameters.
LOG(DFATAL) << "Invalid or unsupported video capture parameters requested: "
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 cb0e9112390..a9ae13311f3 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
@@ -22,7 +22,6 @@
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/browser/renderer_host/media/mock_video_capture_provider.h"
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
-#include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -31,6 +30,7 @@
#include "media/capture/video/video_capture_buffer_pool_impl.h"
#include "media/capture/video/video_capture_buffer_tracker_factory_impl.h"
#include "media/capture/video/video_capture_device_client.h"
+#include "media/capture/video/video_capture_jpeg_decoder_impl.h"
#include "media/capture/video/video_frame_receiver_on_task_runner.h"
#include "media/capture/video_capture_types.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -44,12 +44,6 @@ using ::testing::SaveArg;
namespace content {
-std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder(
- media::VideoCaptureJpegDecoder::DecodeDoneCB decode_done_cb) {
- return std::make_unique<content::VideoCaptureGpuJpegDecoder>(
- std::move(decode_done_cb), base::DoNothing());
-}
-
class MockVideoCaptureControllerEventHandler
: public VideoCaptureControllerEventHandler {
public:
@@ -160,13 +154,11 @@ class VideoCaptureControllerTest
std::make_unique<media::VideoCaptureBufferTrackerFactoryImpl>(),
kPoolSize);
device_client_.reset(new media::VideoCaptureDeviceClient(
+ media::VideoCaptureBufferType::kSharedMemory,
std::make_unique<media::VideoFrameReceiverOnTaskRunner>(
controller_->GetWeakPtrForIOThread(),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
- buffer_pool_,
- base::Bind(&CreateGpuJpegDecoder,
- base::Bind(&media::VideoFrameReceiver::OnFrameReadyInBuffer,
- controller_->GetWeakPtrForIOThread()))));
+ buffer_pool_, media::VideoCaptureJpegDecoderFactoryCB()));
}
void SendStubFrameToDeviceClient(const media::VideoCaptureFormat format) {
diff --git a/chromium/content/browser/renderer_host/media/video_capture_dependencies.cc b/chromium/content/browser/renderer_host/media/video_capture_dependencies.cc
new file mode 100644
index 00000000000..26567c6579b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/video_capture_dependencies.cc
@@ -0,0 +1,53 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/media/video_capture_dependencies.h"
+
+#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace content {
+
+// static
+void VideoCaptureDependencies::CreateJpegDecodeAccelerator(
+ media::mojom::JpegDecodeAcceleratorRequest accelerator) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&VideoCaptureDependencies::CreateJpegDecodeAccelerator,
+ std::move(accelerator)));
+ return;
+ }
+
+ auto* host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ true /*force_create*/);
+ if (host) {
+ host->gpu_service()->CreateJpegDecodeAccelerator(std::move(accelerator));
+ } else {
+ LOG(ERROR) << "No GpuProcessHost";
+ }
+}
+
+// static
+void VideoCaptureDependencies::CreateJpegEncodeAccelerator(
+ media::mojom::JpegEncodeAcceleratorRequest accelerator) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&VideoCaptureDependencies::CreateJpegEncodeAccelerator,
+ std::move(accelerator)));
+ return;
+ }
+
+ auto* host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ true /*force_create*/);
+ if (host) {
+ host->gpu_service()->CreateJpegEncodeAccelerator(std::move(accelerator));
+ } else {
+ LOG(ERROR) << "No GpuProcessHost";
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_dependencies.h b/chromium/content/browser/renderer_host/media/video_capture_dependencies.h
new file mode 100644
index 00000000000..5804eef9f03
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/video_capture_dependencies.h
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_DEPENDENCIES_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_DEPENDENCIES_H_
+
+#include "content/common/content_export.h"
+#include "services/video_capture/public/mojom/device_factory.mojom.h"
+#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
+
+namespace content {
+
+// Browser-provided GPU dependencies for video capture.
+class CONTENT_EXPORT VideoCaptureDependencies {
+ public:
+ static void CreateJpegDecodeAccelerator(
+ media::mojom::JpegDecodeAcceleratorRequest accelerator);
+ static void CreateJpegEncodeAccelerator(
+ media::mojom::JpegEncodeAcceleratorRequest accelerator);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_DEPENDENCIES_H_
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
deleted file mode 100644
index f97690233f2..00000000000
--- a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "content/browser/browser_main_loop.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/common/content_switches.h"
-#include "media/base/bind_to_current_loop.h"
-#include "media/base/media_switches.h"
-#include "media/base/video_frame.h"
-#include "mojo/public/cpp/system/platform_handle.h"
-#include "services/ui/public/cpp/gpu/gpu.h"
-
-namespace content {
-
-VideoCaptureGpuJpegDecoder::VideoCaptureGpuJpegDecoder(
- DecodeDoneCB decode_done_cb,
- base::Callback<void(const std::string&)> send_log_message_cb)
- : decode_done_cb_(std::move(decode_done_cb)),
- send_log_message_cb_(std::move(send_log_message_cb)),
- has_received_decoded_frame_(false),
- next_bitstream_buffer_id_(0),
- in_buffer_id_(media::JpegDecodeAccelerator::kInvalidBitstreamBufferId),
- decoder_status_(INIT_PENDING),
- weak_ptr_factory_(this) {}
-
-VideoCaptureGpuJpegDecoder::~VideoCaptureGpuJpegDecoder() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- // |this| was set as |decoder_|'s client. |decoder_| has to be deleted before
- // this destructor returns to ensure that it doesn't call back into its
- // client. Hence, we wait here while we delete |decoder_| on the IO thread.
- if (decoder_) {
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- // base::Unretained is safe because |this| will be valid until |event|
- // is signaled.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&VideoCaptureGpuJpegDecoder::DestroyDecoderOnIOThread,
- base::Unretained(this), &event));
- event.Wait();
- }
-}
-
-void VideoCaptureGpuJpegDecoder::Initialize() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- base::AutoLock lock(lock_);
- bool is_platform_supported =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kUseFakeJpegDecodeAccelerator);
-#if defined(OS_CHROMEOS)
- // Non-ChromeOS platforms do not support HW JPEG decode now. Do not establish
- // gpu channel to avoid introducing overhead.
- is_platform_supported = true;
-#endif
-
- if (!is_platform_supported ||
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableAcceleratedMjpegDecode)) {
- decoder_status_ = FAILED;
- RecordInitDecodeUMA_Locked();
- return;
- }
-
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&RequestGPUInfoOnIOThread,
- base::ThreadTaskRunnerHandle::Get(),
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-VideoCaptureGpuJpegDecoder::STATUS VideoCaptureGpuJpegDecoder::GetStatus()
- const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- base::AutoLock lock(lock_);
- return decoder_status_;
-}
-
-void VideoCaptureGpuJpegDecoder::DecodeCapturedData(
- const uint8_t* data,
- size_t in_buffer_size,
- const media::VideoCaptureFormat& frame_format,
- base::TimeTicks reference_time,
- base::TimeDelta timestamp,
- media::VideoCaptureDevice::Client::Buffer out_buffer) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(decoder_);
-
- TRACE_EVENT_ASYNC_BEGIN0("jpeg", "VideoCaptureGpuJpegDecoder decoding",
- next_bitstream_buffer_id_);
- TRACE_EVENT0("jpeg", "VideoCaptureGpuJpegDecoder::DecodeCapturedData");
-
- // TODO(kcwu): enqueue decode requests in case decoding is not fast enough
- // (say, if decoding time is longer than 16ms for 60fps 4k image)
- {
- base::AutoLock lock(lock_);
- if (IsDecoding_Locked()) {
- DVLOG(1) << "Drop captured frame. Previous jpeg frame is still decoding";
- return;
- }
- }
-
- // Enlarge input buffer if necessary.
- if (!in_shared_memory_.get() ||
- in_buffer_size > in_shared_memory_->mapped_size()) {
- // Reserve 2x space to avoid frequent reallocations for initial frames.
- const size_t reserved_size = 2 * in_buffer_size;
- in_shared_memory_.reset(new base::SharedMemory);
- if (!in_shared_memory_->CreateAndMapAnonymous(reserved_size)) {
- base::AutoLock lock(lock_);
- decoder_status_ = FAILED;
- LOG(WARNING) << "CreateAndMapAnonymous failed, size=" << reserved_size;
- return;
- }
- }
- memcpy(in_shared_memory_->memory(), data, in_buffer_size);
-
- // No need to lock for |in_buffer_id_| since IsDecoding_Locked() is false.
- in_buffer_id_ = next_bitstream_buffer_id_;
- media::BitstreamBuffer in_buffer(in_buffer_id_, in_shared_memory_->handle(),
- in_buffer_size);
- // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
- next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
-
- // The API of |decoder_| requires us to wrap the |out_buffer| in a VideoFrame.
- const gfx::Size dimensions = frame_format.frame_size;
- std::unique_ptr<media::VideoCaptureBufferHandle> out_buffer_access =
- out_buffer.handle_provider->GetHandleForInProcessAccess();
- base::SharedMemoryHandle out_handle =
- out_buffer.handle_provider->GetNonOwnedSharedMemoryHandleForLegacyIPC();
- scoped_refptr<media::VideoFrame> out_frame =
- media::VideoFrame::WrapExternalSharedMemory(
- media::PIXEL_FORMAT_I420, // format
- dimensions, // coded_size
- gfx::Rect(dimensions), // visible_rect
- dimensions, // natural_size
- out_buffer_access->data(), // data
- out_buffer_access->mapped_size(), // data_size
- out_handle, // handle
- 0, // shared_memory_offset
- timestamp); // timestamp
- if (!out_frame) {
- base::AutoLock lock(lock_);
- decoder_status_ = FAILED;
- LOG(ERROR) << "DecodeCapturedData: WrapExternalSharedMemory failed";
- return;
- }
- // Hold onto the buffer access handle for the lifetime of the VideoFrame, to
- // ensure the data pointers remain valid.
- out_frame->AddDestructionObserver(base::BindOnce(
- [](std::unique_ptr<media::VideoCaptureBufferHandle> handle) {},
- std::move(out_buffer_access)));
- out_frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE,
- frame_format.frame_rate);
-
- out_frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
- reference_time);
-
- media::mojom::VideoFrameInfoPtr out_frame_info =
- media::mojom::VideoFrameInfo::New();
- out_frame_info->timestamp = timestamp;
- out_frame_info->pixel_format = media::PIXEL_FORMAT_I420;
- out_frame_info->coded_size = dimensions;
- out_frame_info->visible_rect = gfx::Rect(dimensions);
- out_frame_info->metadata = out_frame->metadata()->GetInternalValues().Clone();
-
- {
- base::AutoLock lock(lock_);
- decode_done_closure_ =
- base::Bind(decode_done_cb_, out_buffer.id, out_buffer.frame_feedback_id,
- base::Passed(&out_buffer.access_permission),
- base::Passed(&out_frame_info));
- }
-
- // base::Unretained is safe because |decoder_| is deleted on the IO thread.
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&media::JpegDecodeAccelerator::Decode,
- base::Unretained(decoder_.get()),
- in_buffer, std::move(out_frame)));
-}
-
-void VideoCaptureGpuJpegDecoder::VideoFrameReady(int32_t bitstream_buffer_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- TRACE_EVENT0("jpeg", "VideoCaptureGpuJpegDecoder::VideoFrameReady");
- if (!has_received_decoded_frame_) {
- send_log_message_cb_.Run("Received decoded frame from Gpu Jpeg decoder");
- has_received_decoded_frame_ = true;
- }
- base::AutoLock lock(lock_);
-
- if (!IsDecoding_Locked()) {
- LOG(ERROR) << "Got decode response while not decoding";
- return;
- }
-
- if (bitstream_buffer_id != in_buffer_id_) {
- LOG(ERROR) << "Unexpected bitstream_buffer_id " << bitstream_buffer_id
- << ", expected " << in_buffer_id_;
- return;
- }
- in_buffer_id_ = media::JpegDecodeAccelerator::kInvalidBitstreamBufferId;
-
- decode_done_closure_.Run();
- decode_done_closure_.Reset();
-
- TRACE_EVENT_ASYNC_END0("jpeg", "VideoCaptureGpuJpegDecoder decoding",
- bitstream_buffer_id);
-}
-
-void VideoCaptureGpuJpegDecoder::NotifyError(
- int32_t bitstream_buffer_id,
- media::JpegDecodeAccelerator::Error error) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- LOG(ERROR) << "Decode error, bitstream_buffer_id=" << bitstream_buffer_id
- << ", error=" << error;
- send_log_message_cb_.Run("Gpu Jpeg decoder failed");
- base::AutoLock lock(lock_);
- decode_done_closure_.Reset();
- decoder_status_ = FAILED;
-}
-
-// static
-void VideoCaptureGpuJpegDecoder::RequestGPUInfoOnIOThread(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- GpuProcessHost* host =
- GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false);
- if (host) {
- host->RequestGPUInfo(
- base::Bind(&VideoCaptureGpuJpegDecoder::DidReceiveGPUInfoOnIOThread,
- task_runner, weak_this));
- } else {
- DidReceiveGPUInfoOnIOThread(std::move(task_runner), std::move(weak_this),
- gpu::GPUInfo());
- }
-}
-
-// static
-void VideoCaptureGpuJpegDecoder::DidReceiveGPUInfoOnIOThread(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this,
- const gpu::GPUInfo& gpu_info) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- media::mojom::JpegDecodeAcceleratorPtr remote_decoder;
-
- if (gpu_info.jpeg_decode_accelerator_supported) {
- GpuProcessHost* host =
- GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false);
- if (host) {
- host->gpu_service()->CreateJpegDecodeAccelerator(
- mojo::MakeRequest(&remote_decoder));
- }
- }
-
- task_runner->PostTask(
- FROM_HERE,
- base::BindOnce(&VideoCaptureGpuJpegDecoder::FinishInitialization,
- weak_this, remote_decoder.PassInterface()));
-}
-
-void VideoCaptureGpuJpegDecoder::FinishInitialization(
- media::mojom::JpegDecodeAcceleratorPtrInfo unbound_remote_decoder) {
- TRACE_EVENT0("gpu", "VideoCaptureGpuJpegDecoder::FinishInitialization");
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- if (unbound_remote_decoder.is_valid()) {
- base::AutoLock lock(lock_);
- decoder_ = std::make_unique<media::MojoJpegDecodeAccelerator>(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- std::move(unbound_remote_decoder));
-
- // base::Unretained is safe because |decoder_| is deleted on the IO thread.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&media::JpegDecodeAccelerator::InitializeAsync,
- base::Unretained(decoder_.get()), this,
- media::BindToCurrentLoop(base::Bind(
- &VideoCaptureGpuJpegDecoder::OnInitializationDone,
- weak_ptr_factory_.GetWeakPtr()))));
- } else {
- OnInitializationDone(false);
- }
-}
-
-void VideoCaptureGpuJpegDecoder::OnInitializationDone(bool success) {
- TRACE_EVENT0("gpu", "VideoCaptureGpuJpegDecoder::OnInitializationDone");
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- base::AutoLock lock(lock_);
- if (!success) {
- BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, decoder_.release());
- DLOG(ERROR) << "Failed to initialize JPEG decoder";
- }
-
- decoder_status_ = success ? INIT_PASSED : FAILED;
- RecordInitDecodeUMA_Locked();
-}
-
-bool VideoCaptureGpuJpegDecoder::IsDecoding_Locked() const {
- lock_.AssertAcquired();
- return !decode_done_closure_.is_null();
-}
-
-void VideoCaptureGpuJpegDecoder::RecordInitDecodeUMA_Locked() {
- UMA_HISTOGRAM_BOOLEAN("Media.VideoCaptureGpuJpegDecoder.InitDecodeSuccess",
- decoder_status_ == INIT_PASSED);
-}
-
-void VideoCaptureGpuJpegDecoder::DestroyDecoderOnIOThread(
- base::WaitableEvent* event) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- decoder_.reset();
- event->Signal();
-}
-
-} // namespace content
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
deleted file mode 100644
index bf089ba6e83..00000000000
--- a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_GPU_JPEG_DECODER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_GPU_JPEG_DECODER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequence_checker.h"
-#include "content/common/content_export.h"
-#include "gpu/config/gpu_info.h"
-#include "media/capture/video/video_capture_jpeg_decoder.h"
-#include "media/mojo/clients/mojo_jpeg_decode_accelerator.h"
-
-namespace base {
-class WaitableEvent;
-}
-
-namespace content {
-
-// Adapter to GpuJpegDecodeAccelerator for VideoCaptureDevice::Client. It takes
-// care of GpuJpegDecodeAccelerator creation, shared memory, and threading
-// issues.
-//
-// All public methods except JpegDecodeAccelerator::Client ones should be called
-// on the same thread. JpegDecodeAccelerator::Client methods should be called on
-// the IO thread.
-class CONTENT_EXPORT VideoCaptureGpuJpegDecoder
- : public media::VideoCaptureJpegDecoder,
- public media::JpegDecodeAccelerator::Client {
- public:
- // |decode_done_cb| is called on the IO thread when decode succeeds. This can
- // be on any thread. |decode_done_cb| is never called after
- // VideoCaptureGpuJpegDecoder is destroyed.
- VideoCaptureGpuJpegDecoder(
- DecodeDoneCB decode_done_cb,
- base::Callback<void(const std::string&)> send_log_message_cb);
- ~VideoCaptureGpuJpegDecoder() override;
-
- // Implementation of VideoCaptureJpegDecoder:
- void Initialize() override;
- STATUS GetStatus() const override;
- void DecodeCapturedData(
- const uint8_t* data,
- size_t in_buffer_size,
- const media::VideoCaptureFormat& frame_format,
- base::TimeTicks reference_time,
- base::TimeDelta timestamp,
- media::VideoCaptureDevice::Client::Buffer out_buffer) override;
-
- // JpegDecodeAccelerator::Client implementation.
- // These will be called on IO thread.
- void VideoFrameReady(int32_t buffer_id) override;
- void NotifyError(int32_t buffer_id,
- media::JpegDecodeAccelerator::Error error) override;
-
- private:
- static void RequestGPUInfoOnIOThread(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this);
-
- static void DidReceiveGPUInfoOnIOThread(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this,
- const gpu::GPUInfo& gpu_info);
-
- void FinishInitialization(
- media::mojom::JpegDecodeAcceleratorPtrInfo unbound_remote_decoder);
- void OnInitializationDone(bool success);
-
- // Returns true if the decoding of last frame is not finished yet.
- bool IsDecoding_Locked() const;
-
- // Records |decoder_status_| to histogram.
- void RecordInitDecodeUMA_Locked();
-
- void DestroyDecoderOnIOThread(base::WaitableEvent* event);
-
- // The underlying JPEG decode accelerator.
- std::unique_ptr<media::JpegDecodeAccelerator> decoder_;
-
- // The callback to run when decode succeeds.
- const DecodeDoneCB decode_done_cb_;
-
- const base::Callback<void(const std::string&)> send_log_message_cb_;
- bool has_received_decoded_frame_;
-
- // Guards |decode_done_closure_| and |decoder_status_|.
- mutable base::Lock lock_;
-
- // The closure of |decode_done_cb_| with bound parameters.
- base::Closure decode_done_closure_;
-
- // Next id for input BitstreamBuffer.
- int32_t next_bitstream_buffer_id_;
-
- // The id for current input BitstreamBuffer being decoded.
- int32_t in_buffer_id_;
-
- // Shared memory to store JPEG stream buffer. The input BitstreamBuffer is
- // backed by this.
- std::unique_ptr<base::SharedMemory> in_shared_memory_;
-
- STATUS decoder_status_;
-
- SEQUENCE_CHECKER(sequence_checker_);
-
- base::WeakPtrFactory<VideoCaptureGpuJpegDecoder> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(VideoCaptureGpuJpegDecoder);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_GPU_JPEG_DECODER_H_
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.cc b/chromium/content/browser/renderer_host/overscroll_controller.cc
index a4bb1af79d3..73c7bbe0e26 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller.cc
@@ -46,9 +46,7 @@ float ClampAbsoluteValue(float value, float max_abs) {
} // namespace
-OverscrollController::OverscrollController()
- : wheel_scroll_latching_enabled_(base::FeatureList::IsEnabled(
- features::kTouchpadAndWheelScrollLatching)) {}
+OverscrollController::OverscrollController() {}
OverscrollController::~OverscrollController() {}
@@ -343,14 +341,8 @@ bool OverscrollController::ProcessEventForOverscroll(
bool event_processed = false;
switch (event.GetType()) {
case blink::WebInputEvent::kGestureScrollBegin: {
- // When wheel scroll latching is disabled avoid resetting the state on
- // GestureScrollBegin generated from the touchpad since it is sent for
- // every wheel event.
- if (overscroll_mode_ != OVERSCROLL_NONE &&
- (!IsGestureEventFromTouchpad(event) ||
- wheel_scroll_latching_enabled_)) {
+ if (overscroll_mode_ != OVERSCROLL_NONE)
SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE);
- }
break;
}
case blink::WebInputEvent::kGestureScrollEnd: {
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.h b/chromium/content/browser/renderer_host/overscroll_controller.h
index dbc94c174bd..d876007493c 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller.h
@@ -163,8 +163,6 @@ class CONTENT_EXPORT OverscrollController {
// owned by this controller.
OverscrollControllerDelegate* delegate_ = nullptr;
- bool wheel_scroll_latching_enabled_;
-
// A inertial scroll (fling) event may complete an overscroll gesture and
// navigate to a new page or cancel the overscroll animation. In both cases
// inertial scroll can continue to generate scroll-update events. These events
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 c8bfe794b21..270b2aaee40 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/browser/renderer_host/p2p/socket_host.h"
#include "content/common/p2p_messages.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/resource_context.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
#include "net/base/net_errors.h"
@@ -26,6 +25,7 @@
#include "net/socket/client_socket_factory.h"
#include "net/socket/datagram_client_socket.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/proxy_resolving_client_socket_factory.h"
@@ -119,10 +119,8 @@ class P2PSocketDispatcherHost::DnsRequest {
};
P2PSocketDispatcherHost::P2PSocketDispatcherHost(
- content::ResourceContext* resource_context,
net::URLRequestContextGetter* url_context)
: BrowserMessageFilter(P2PMsgStart),
- resource_context_(resource_context),
url_context_(url_context),
monitoring_networks_(false),
dump_incoming_rtp_packet_(false),
@@ -140,6 +138,8 @@ void P2PSocketDispatcherHost::OnChannelClosing() {
net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
monitoring_networks_ = false;
}
+
+ proxy_resolving_socket_factory_.reset();
}
void P2PSocketDispatcherHost::OnDestruct() const {
@@ -241,7 +241,7 @@ void P2PSocketDispatcherHost::OnStopNetworkNotifications() {
void P2PSocketDispatcherHost::OnGetHostAddress(const std::string& host_name,
int32_t request_id) {
std::unique_ptr<DnsRequest> request = std::make_unique<DnsRequest>(
- request_id, resource_context_->GetHostResolver());
+ request_id, url_context_->GetURLRequestContext()->host_resolver());
DnsRequest* request_ptr = request.get();
dns_requests_.insert(std::move(request));
request_ptr->Resolve(host_name,
@@ -270,7 +270,7 @@ void P2PSocketDispatcherHost::OnCreateSocket(
if (!proxy_resolving_socket_factory_) {
proxy_resolving_socket_factory_ =
std::make_unique<network::ProxyResolvingClientSocketFactory>(
- nullptr, url_context_->GetURLRequestContext());
+ url_context_->GetURLRequestContext());
}
if (sockets_.size() > kMaxSimultaneousSockets) {
LOG(ERROR) << "Too many sockets created";
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 120adbe8a13..288c834e422 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
@@ -36,14 +36,12 @@ class ProxyResolvingClientSocketFactory;
namespace content {
class P2PSocketHost;
-class ResourceContext;
class P2PSocketDispatcherHost
: public content::BrowserMessageFilter,
public net::NetworkChangeNotifier::NetworkChangeObserver {
public:
- P2PSocketDispatcherHost(content::ResourceContext* resource_context,
- net::URLRequestContextGetter* url_context);
+ explicit P2PSocketDispatcherHost(net::URLRequestContextGetter* url_context);
// content::BrowserMessageFilter overrides.
void OnChannelClosing() override;
@@ -111,7 +109,6 @@ class P2PSocketDispatcherHost
void StopRtpDumpOnIOThread(bool incoming, bool outgoing);
- content::ResourceContext* resource_context_;
scoped_refptr<net::URLRequestContextGetter> url_context_;
// Initialized on browser IO thread.
std::unique_ptr<network::ProxyResolvingClientSocketFactory>
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 5a5ba5d953b..efc6c63a375 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -123,10 +123,8 @@ bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address,
// find a way to inject this into ProxyResolvingClientSocket. This could be
// a problem on multi-homed host.
- // The default SSLConfig is good enough for us for now.
- const net::SSLConfig ssl_config;
socket_ = proxy_resolving_socket_factory_->CreateSocket(
- ssl_config, GURL("https://" + dest_host_port_pair.ToString()),
+ GURL("https://" + dest_host_port_pair.ToString()),
IsTlsClientSocket(type_));
if (IsPseudoTlsClientSocket(type_)) {
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
index 37dd69132e0..1017d6bb1d9 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
@@ -487,8 +487,7 @@ TEST(P2PSocketHostTcpWithPseudoTlsTest, Basic) {
net::MockClientSocketFactory mock_socket_factory;
context.set_client_socket_factory(&mock_socket_factory);
context.Init();
- network::ProxyResolvingClientSocketFactory factory(&mock_socket_factory,
- &context);
+ network::ProxyResolvingClientSocketFactory factory(&context);
base::StringPiece ssl_client_hello =
jingle_glue::FakeSSLClientSocket::GetSslClientHello();
@@ -544,8 +543,7 @@ TEST_P(P2PSocketHostTcpWithTlsTest, Basic) {
net::MockClientSocketFactory mock_socket_factory;
context.set_client_socket_factory(&mock_socket_factory);
context.Init();
- network::ProxyResolvingClientSocketFactory factory(&mock_socket_factory,
- &context);
+ network::ProxyResolvingClientSocketFactory factory(&context);
const net::IoMode io_mode = std::get<0>(GetParam());
const P2PSocketType socket_type = std::get<1>(GetParam());
// OnOpen() calls DoRead(), so populate the mock socket with a pending read.
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 925e600eb16..dafc06ba0fa 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
@@ -13,6 +13,7 @@
#include "base/sys_byteorder.h"
#include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
+#include "net/base/completion_once_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
@@ -90,7 +91,7 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
int RecvFrom(net::IOBuffer* buf,
int buf_len,
net::IPEndPoint* address,
- const net::CompletionCallback& callback) override {
+ net::CompletionOnceCallback callback) override {
CHECK(recv_callback_.is_null());
if (incoming_packets_.size() > 0) {
scoped_refptr<net::IOBuffer> buffer(buf);
@@ -101,7 +102,7 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
incoming_packets_.pop_front();
return size;
} else {
- recv_callback_ = callback;
+ recv_callback_ = std::move(callback);
recv_buffer_ = buf;
recv_size_ = buf_len;
recv_address_ = address;
@@ -112,7 +113,7 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
int SendTo(net::IOBuffer* buf,
int buf_len,
const net::IPEndPoint& address,
- const net::CompletionCallback& callback) override {
+ net::CompletionOnceCallback callback) override {
scoped_refptr<net::IOBuffer> buffer(buf);
std::vector<char> data_vector(buffer->data(), buffer->data() + buf_len);
sent_packets_->push_back(UDPPacket(address, data_vector));
@@ -132,10 +133,8 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
int size = std::min(recv_size_, static_cast<int>(data.size()));
memcpy(recv_buffer_->data(), &*data.begin(), size);
*recv_address_ = address;
- net::CompletionCallback cb = recv_callback_;
- recv_callback_.Reset();
recv_buffer_ = nullptr;
- std::move(cb).Run(size);
+ std::move(recv_callback_).Run(size);
} else {
incoming_packets_.push_back(UDPPacket(address, data));
}
@@ -188,7 +187,7 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
scoped_refptr<net::IOBuffer> recv_buffer_;
net::IPEndPoint* recv_address_;
int recv_size_;
- net::CompletionCallback recv_callback_;
+ net::CompletionOnceCallback recv_callback_;
std::vector<uint16_t>* used_ports_;
};
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 dd9483958d0..474c1683dcd 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
@@ -514,7 +514,7 @@ bool PepperFileIOHost::AddFileToReplyContext(
// A non-zero resource id signals NaClIPCAdapter to create a NaClQuotaDesc.
PP_Resource quota_file_io = check_quota_ ? pp_resource() : 0;
file_handle.set_file_handle(transit_file, open_flags, quota_file_io);
- reply_context->params.AppendHandle(file_handle);
+ reply_context->params.AppendHandle(std::move(file_handle));
return true;
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.cc
index 94059da48e9..d4140d9d49e 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.cc
@@ -68,11 +68,12 @@ int32_t PepperGamepadHost::OnRequestMemory(
void PepperGamepadHost::GotUserGesture(
const ppapi::host::ReplyMessageContext& context) {
- base::SharedMemoryHandle handle =
- gamepad_service_->DuplicateSharedMemoryHandle();
+ base::ReadOnlySharedMemoryRegion region =
+ gamepad_service_->DuplicateSharedMemoryRegion();
context.params.AppendHandle(ppapi::proxy::SerializedHandle(
- handle, sizeof(device::GamepadHardwareBuffer)));
+ base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
+ std::move(region))));
host()->SendReply(context, PpapiPluginMsg_Gamepad_SendMemory());
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
index abe26a38266..61e40743228 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
@@ -90,15 +90,18 @@ TEST_F(PepperGamepadHostTest, WaitForReply) {
ASSERT_TRUE(sink().GetFirstResourceReplyMatching(
PpapiPluginMsg_Gamepad_SendMemory::ID, &reply_params, &reply_msg));
- // Extract the shared memory handle.
- base::SharedMemoryHandle reply_handle;
- EXPECT_TRUE(reply_params.TakeSharedMemoryHandleAtIndex(0, &reply_handle));
+ // Extract the shared memory region.
+ base::ReadOnlySharedMemoryRegion shared_memory_region;
+ EXPECT_TRUE(reply_params.TakeReadOnlySharedMemoryRegionAtIndex(
+ 0, &shared_memory_region));
// Validate the shared memory.
- base::SharedMemory shared_memory(reply_handle, true);
- EXPECT_TRUE(shared_memory.Map(sizeof(device::GamepadHardwareBuffer)));
+ base::ReadOnlySharedMemoryMapping shared_memory_mapping =
+ shared_memory_region.Map();
+ EXPECT_TRUE(shared_memory_mapping.IsValid());
const device::GamepadHardwareBuffer* buffer =
- static_cast<const device::GamepadHardwareBuffer*>(shared_memory.memory());
+ static_cast<const device::GamepadHardwareBuffer*>(
+ shared_memory_mapping.memory());
EXPECT_EQ(button_down_data.items[0].buttons_length,
buffer->data.items[0].buttons_length);
for (size_t i = 0; i < device::Gamepad::kButtonsLengthCap; i++) {
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 a7eb91795c4..94a1f646ba9 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
@@ -15,10 +15,12 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/resource_context.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/common/socket_permission_request.h"
#include "net/base/address_list.h"
#include "net/dns/host_resolver.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_host_resolver_private.h"
#include "ppapi/c/private/ppb_net_address_private.h"
@@ -138,15 +140,14 @@ int32_t PepperHostResolverMessageFilter::OnMsgResolve(
RenderProcessHost::FromID(render_process_id_);
if (!render_process_host)
return PP_ERROR_FAILED;
- BrowserContext* browser_context = render_process_host->GetBrowserContext();
- if (!browser_context || !browser_context->GetResourceContext())
- return PP_ERROR_FAILED;
+ auto* storage_partition = render_process_host->GetStoragePartition();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PepperHostResolverMessageFilter::DoResolve, this,
- context->MakeReplyMessageContext(), host_port, hint,
- browser_context->GetResourceContext()));
+ base::BindOnce(
+ &PepperHostResolverMessageFilter::DoResolve, this,
+ context->MakeReplyMessageContext(), host_port, hint,
+ base::WrapRefCounted(storage_partition->GetURLRequestContext())));
return PP_OK_COMPLETIONPENDING;
}
@@ -154,10 +155,17 @@ void PepperHostResolverMessageFilter::DoResolve(
const ReplyMessageContext& context,
const ppapi::HostPortPair& host_port,
const PP_HostResolver_Private_Hint& hint,
- ResourceContext* resource_context) {
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- net::HostResolver* host_resolver = resource_context->GetHostResolver();
+ auto* url_request_context =
+ url_request_context_getter->GetURLRequestContext();
+ if (!url_request_context) {
+ SendResolveError(PP_ERROR_FAILED, context);
+ return;
+ }
+
+ net::HostResolver* host_resolver = url_request_context->host_resolver();
if (!host_resolver) {
SendResolveError(PP_ERROR_FAILED, context);
return;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h
index 42f75696e13..cd9f2121322 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h
@@ -22,6 +22,7 @@ struct PP_NetAddress_Private;
namespace net {
class AddressList;
+class URLRequestContextGetter;
}
namespace ppapi {
@@ -35,7 +36,6 @@ struct HostMessageContext;
namespace content {
class BrowserPpapiHostImpl;
-class ResourceContext;
class CONTENT_EXPORT PepperHostResolverMessageFilter
: public ppapi::host::ResourceMessageFilter {
@@ -63,10 +63,11 @@ class CONTENT_EXPORT PepperHostResolverMessageFilter
// Backend for OnMsgResolve(). Delegates host resolution to the
// Browser's HostResolver. Must be called on the IO thread.
- void DoResolve(const ppapi::host::ReplyMessageContext& context,
- const ppapi::HostPortPair& host_port,
- const PP_HostResolver_Private_Hint& hint,
- ResourceContext* resource_context);
+ void DoResolve(
+ const ppapi::host::ReplyMessageContext& context,
+ const ppapi::HostPortPair& host_port,
+ const PP_HostResolver_Private_Hint& hint,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
void OnLookupFinished(int net_result,
const net::AddressList& addresses,
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 81c7cc8958e..17d9f021651 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
@@ -19,7 +19,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/resource_context.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/common/socket_permission_request.h"
#include "net/base/address_family.h"
#include "net/base/host_port_pair.h"
@@ -33,6 +33,8 @@
#include "net/socket/ssl_client_socket.h"
#include "net/socket/tcp_client_socket.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/error_conversion.h"
#include "ppapi/host/ppapi_host.h"
@@ -264,15 +266,14 @@ int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
RenderProcessHost::FromID(render_process_id_);
if (!render_process_host)
return PP_ERROR_FAILED;
- BrowserContext* browser_context = render_process_host->GetBrowserContext();
- if (!browser_context || !browser_context->GetResourceContext())
- return PP_ERROR_FAILED;
+ auto* storage_partition = render_process_host->GetStoragePartition();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PepperTCPSocketMessageFilter::DoConnect, this,
- context->MakeReplyMessageContext(), host, port,
- browser_context->GetResourceContext()));
+ base::BindOnce(
+ &PepperTCPSocketMessageFilter::DoConnect, this,
+ context->MakeReplyMessageContext(), host, port,
+ base::WrapRefCounted(storage_partition->GetURLRequestContext())));
return PP_OK_COMPLETIONPENDING;
}
@@ -624,7 +625,7 @@ void PepperTCPSocketMessageFilter::DoConnect(
const ppapi::host::ReplyMessageContext& context,
const std::string& host,
uint16_t port,
- ResourceContext* resource_context) {
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
@@ -632,12 +633,25 @@ void PepperTCPSocketMessageFilter::DoConnect(
return;
}
+ auto* url_request_context =
+ url_request_context_getter->GetURLRequestContext();
+ if (!url_request_context) {
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ net::HostResolver* host_resolver = url_request_context->host_resolver();
+ if (!host_resolver) {
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
state_.SetPendingTransition(TCPSocketState::CONNECT);
address_index_ = 0;
address_list_.clear();
net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
- net::HostResolver* resolver = resource_context->GetHostResolver();
- int net_result = resolver->Resolve(
+
+ int net_result = host_resolver->Resolve(
request_info, net::DEFAULT_PRIORITY, &address_list_,
base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
base::Unretained(this), context),
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
index 936dd339ebe..fec0b7cbf0c 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
@@ -38,6 +38,7 @@ namespace net {
class DrainableIOBuffer;
class IOBuffer;
class SSLClientSocket;
+class URLRequestContextGetter;
}
namespace ppapi {
@@ -52,7 +53,6 @@ namespace content {
class BrowserPpapiHostImpl;
class ContentBrowserPepperHostFactory;
-class ResourceContext;
class CONTENT_EXPORT PepperTCPSocketMessageFilter
: public ppapi::host::ResourceMessageFilter,
@@ -119,10 +119,11 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
void DoBind(const ppapi::host::ReplyMessageContext& context,
const PP_NetAddress_Private& net_addr);
- void DoConnect(const ppapi::host::ReplyMessageContext& context,
- const std::string& host,
- uint16_t port,
- ResourceContext* resource_context);
+ void DoConnect(
+ const ppapi::host::ReplyMessageContext& context,
+ const std::string& host,
+ uint16_t port,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
void DoConnectWithNetAddress(const ppapi::host::ReplyMessageContext& context,
const PP_NetAddress_Private& net_addr);
void DoWrite(const ppapi::host::ReplyMessageContext& context);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_android.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_android.cc
deleted file mode 100644
index d259aae2526..00000000000
--- a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_android.cc
+++ /dev/null
@@ -1,16 +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 "base/logging.h"
-#include "content/browser/renderer_host/pepper/pepper_truetype_font.h"
-
-namespace content {
-
-// static
-PepperTrueTypeFont* PepperTrueTypeFont::Create() {
- NOTIMPLEMENTED(); // Not implemented on Android.
- return NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc
index c9a8d3fd8c6..c71954e48c5 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc
@@ -14,8 +14,10 @@
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/sys_byteorder.h"
-#include "content/browser/renderer_host/font_utils_linux.h"
+#include "build/build_config.h"
+#include "components/services/font/ppapi_fontconfig_matching.h"
#include "content/public/common/common_sandbox_support_linux.h"
+#include "ppapi/buildflags/buildflags.h"
#include "ppapi/c/dev/ppb_truetype_font_dev.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
@@ -74,12 +76,10 @@ int32_t PepperTrueTypeFontLinux::Initialize(
}
}
- fd_.reset(
- MatchFontFaceWithFallback(desc->family,
- desc->weight >= PP_TRUETYPEFONTWEIGHT_BOLD,
- desc->style & PP_TRUETYPEFONTSTYLE_ITALIC,
- desc->charset,
- PP_BROWSERFONT_TRUSTED_FAMILY_DEFAULT));
+ fd_.reset(font_service::MatchFontFaceWithFallback(
+ desc->family, desc->weight >= PP_TRUETYPEFONTWEIGHT_BOLD,
+ desc->style & PP_TRUETYPEFONTSTYLE_ITALIC, desc->charset,
+ PP_BROWSERFONT_TRUSTED_FAMILY_DEFAULT));
// TODO(bbudge) Modify content API to return results of font matching and
// fallback, so we can update |desc| to reflect that.
return fd_.is_valid() ? PP_OK : PP_ERROR_FAILED;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_android.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_android.cc
deleted file mode 100644
index 28db24f7ffa..00000000000
--- a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_android.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/logging.h"
-#include "content/browser/renderer_host/pepper/pepper_truetype_font_list.h"
-
-namespace content {
-
-void GetFontFamilies_SlowBlocking(std::vector<std::string>* font_families) {
- NOTIMPLEMENTED(); // Font API isn't implemented on Android.
-}
-
-void GetFontsInFamily_SlowBlocking(
- const std::string& family,
- std::vector<ppapi::proxy::SerializedTrueTypeFontDesc>* fonts_in_family) {
- NOTIMPLEMENTED(); // Font API isn't implemented on Android.
-}
-
-} // namespace content
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 03ade3604d1..204ed5af76e 100644
--- a/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
@@ -21,6 +21,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "storage/browser/fileapi/quota/quota_reservation.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/origin.h"
using storage::QuotaReservationManager;
@@ -44,7 +45,7 @@ class FakeBackend : public QuotaReservationManager::QuotaBackend {
~FakeBackend() override {}
void ReserveQuota(
- const GURL& origin,
+ const url::Origin& origin,
storage::FileSystemType type,
int64_t delta,
const QuotaReservationManager::ReserveQuotaCallback& callback) override {
@@ -53,17 +54,17 @@ class FakeBackend : public QuotaReservationManager::QuotaBackend {
base::File::FILE_OK, delta));
}
- void ReleaseReservedQuota(const GURL& origin,
+ void ReleaseReservedQuota(const url::Origin& origin,
storage::FileSystemType type,
int64_t size) override {}
- void CommitQuotaUsage(const GURL& origin,
+ void CommitQuotaUsage(const url::Origin& origin,
storage::FileSystemType type,
int64_t delta) override {}
- void IncrementDirtyCount(const GURL& origin,
+ void IncrementDirtyCount(const url::Origin& origin,
storage::FileSystemType type) override {}
- void DecrementDirtyCount(const GURL& origin,
+ void DecrementDirtyCount(const url::Origin& origin,
storage::FileSystemType type) override {}
private:
@@ -160,7 +161,8 @@ TEST_F(QuotaReservationTest, ReserveQuota) {
storage::FileSystemType type = kType;
scoped_refptr<storage::QuotaReservation> reservation(
- reservation_manager()->CreateReservation(origin, type));
+ reservation_manager()->CreateReservation(url::Origin::Create(origin),
+ type));
scoped_refptr<QuotaReservation> test =
CreateQuotaReservation(reservation, origin, type);
@@ -201,7 +203,8 @@ TEST_F(QuotaReservationTest, MultipleFiles) {
storage::FileSystemType type = kType;
scoped_refptr<storage::QuotaReservation> reservation(
- reservation_manager()->CreateReservation(origin, type));
+ reservation_manager()->CreateReservation(url::Origin::Create(origin),
+ type));
scoped_refptr<QuotaReservation> test =
CreateQuotaReservation(reservation, origin, type);
diff --git a/chromium/content/browser/renderer_host/plugin_registry_impl.cc b/chromium/content/browser/renderer_host/plugin_registry_impl.cc
new file mode 100644
index 00000000000..ec071f3b89c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/plugin_registry_impl.cc
@@ -0,0 +1,87 @@
+// Copyright 2018 The Chromium Authors. All rights 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/plugin_registry_impl.h"
+
+#include "base/no_destructor.h"
+#include "content/browser/plugin_service_impl.h"
+#include "content/public/browser/plugin_service_filter.h"
+
+namespace content {
+
+namespace {
+constexpr auto kPluginRefreshThreshold = base::TimeDelta::FromSeconds(3);
+} // namespace
+
+PluginRegistryImpl::PluginRegistryImpl(ResourceContext* resource_context)
+ : resource_context_(resource_context), weak_factory_(this) {}
+
+PluginRegistryImpl::~PluginRegistryImpl() {}
+
+void PluginRegistryImpl::Bind(blink::mojom::PluginRegistryRequest request) {
+ bindings_.AddBinding(this, std::move(request));
+}
+
+void PluginRegistryImpl::GetPlugins(bool refresh,
+ const url::Origin& main_frame_origin,
+ GetPluginsCallback callback) {
+ auto* plugin_service = PluginServiceImpl::GetInstance();
+
+ // Don't refresh if the specified threshold has not been passed. Note that
+ // this check is performed before off-loading to the file thread. The reason
+ // we do this is that some pages tend to request that the list of plugins be
+ // refreshed at an excessive rate. This instigates disk scanning, as the list
+ // is accumulated by doing multiple reads from disk. This effect is
+ // multiplied when we have several pages requesting this operation.
+ if (refresh) {
+ const base::TimeTicks now = base::TimeTicks::Now();
+ if (now - last_plugin_refresh_time_ >= kPluginRefreshThreshold) {
+ // Only refresh if the threshold hasn't been exceeded yet.
+ plugin_service->RefreshPlugins();
+ last_plugin_refresh_time_ = now;
+ }
+ }
+
+ plugin_service->GetPlugins(base::BindOnce(
+ &PluginRegistryImpl::GetPluginsComplete, weak_factory_.GetWeakPtr(),
+ main_frame_origin, std::move(callback)));
+}
+
+void PluginRegistryImpl::GetPluginsComplete(
+ const url::Origin& main_frame_origin,
+ GetPluginsCallback callback,
+ const std::vector<WebPluginInfo>& all_plugins) {
+ PluginServiceFilter* filter = PluginServiceImpl::GetInstance()->GetFilter();
+ std::vector<blink::mojom::PluginInfoPtr> plugins;
+
+ const int child_process_id = -1;
+ const int routing_id = MSG_ROUTING_NONE;
+ // In this loop, copy the WebPluginInfo (and do not use a reference) because
+ // the filter might mutate it.
+ for (WebPluginInfo plugin : all_plugins) {
+ // TODO(crbug.com/621724): Pass an url::Origin instead of a GURL.
+ if (!filter ||
+ filter->IsPluginAvailable(child_process_id, routing_id,
+ resource_context_, main_frame_origin.GetURL(),
+ main_frame_origin, &plugin)) {
+ auto plugin_blink = blink::mojom::PluginInfo::New();
+ plugin_blink->name = plugin.name;
+ plugin_blink->description = plugin.desc;
+ plugin_blink->filename = plugin.path.BaseName();
+ plugin_blink->background_color = plugin.background_color;
+ for (const auto& mime_type : plugin.mime_types) {
+ auto mime_type_blink = blink::mojom::PluginMimeType::New();
+ mime_type_blink->mime_type = mime_type.mime_type;
+ mime_type_blink->description = mime_type.description;
+ mime_type_blink->file_extensions = mime_type.file_extensions;
+ plugin_blink->mime_types.push_back(std::move(mime_type_blink));
+ }
+ plugins.push_back(std::move(plugin_blink));
+ }
+ }
+
+ std::move(callback).Run(std::move(plugins));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/plugin_registry_impl.h b/chromium/content/browser/renderer_host/plugin_registry_impl.h
new file mode 100644
index 00000000000..3009401dac6
--- /dev/null
+++ b/chromium/content/browser/renderer_host/plugin_registry_impl.h
@@ -0,0 +1,43 @@
+// Copyright 2018 The Chromium Authors. All 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_PLUGIN_REGISTRY_IMPL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PLUGIN_REGISTRY_IMPL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "third_party/blink/public/mojom/plugins/plugin_registry.mojom.h"
+
+namespace content {
+
+class ResourceContext;
+struct WebPluginInfo;
+
+class PluginRegistryImpl : public blink::mojom::PluginRegistry {
+ public:
+ explicit PluginRegistryImpl(ResourceContext* resource_context);
+ ~PluginRegistryImpl() override;
+
+ void Bind(blink::mojom::PluginRegistryRequest request);
+
+ // blink::mojom::PluginRegistry
+ void GetPlugins(bool refresh,
+ const url::Origin& main_frame_origin,
+ GetPluginsCallback callback) override;
+
+ private:
+ void GetPluginsComplete(const url::Origin& main_frame_origin,
+ GetPluginsCallback callback,
+ const std::vector<WebPluginInfo>& all_plugins);
+
+ ResourceContext* const resource_context_;
+ mojo::BindingSet<PluginRegistry> bindings_;
+ base::TimeTicks last_plugin_refresh_time_;
+ base::WeakPtrFactory<PluginRegistryImpl> weak_factory_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PLUGIN_REGISTRY_IMPL_H_
diff --git a/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc b/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
index 025702c926a..c78d73722dd 100644
--- a/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
+++ b/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
@@ -48,11 +48,12 @@ RenderFrameMetadataProviderImpl::LastRenderFrameMetadata() const {
return last_render_frame_metadata_;
}
-void RenderFrameMetadataProviderImpl::OnFrameTokenRenderFrameMetadataChanged(
- cc::RenderFrameMetadata metadata) {
+void RenderFrameMetadataProviderImpl::
+ OnRenderFrameMetadataChangedAfterActivation(
+ cc::RenderFrameMetadata metadata) {
last_render_frame_metadata_ = std::move(metadata);
for (Observer& observer : observers_)
- observer.OnRenderFrameMetadataChanged();
+ observer.OnRenderFrameMetadataChangedAfterActivation();
}
void RenderFrameMetadataProviderImpl::OnFrameTokenFrameSubmissionForTesting() {
@@ -68,19 +69,25 @@ void RenderFrameMetadataProviderImpl::SetLastRenderFrameMetadataForTest(
void RenderFrameMetadataProviderImpl::OnRenderFrameMetadataChanged(
uint32_t frame_token,
const cc::RenderFrameMetadata& metadata) {
+ for (Observer& observer : observers_)
+ observer.OnRenderFrameMetadataChangedBeforeActivation(metadata);
+
if (metadata.local_surface_id != last_local_surface_id_) {
last_local_surface_id_ = metadata.local_surface_id;
for (Observer& observer : observers_)
observer.OnLocalSurfaceIdChanged(metadata);
}
+ if (!frame_token)
+ return;
+
// Both RenderFrameMetadataProviderImpl and FrameTokenMessageQueue are owned
// by the same RenderWidgetHostImpl. During shutdown the queue is cleared
// without running the callbacks.
frame_token_message_queue_->EnqueueOrRunFrameTokenCallback(
frame_token,
base::BindOnce(&RenderFrameMetadataProviderImpl::
- OnFrameTokenRenderFrameMetadataChanged,
+ OnRenderFrameMetadataChangedAfterActivation,
weak_factory_.GetWeakPtr(), std::move(metadata)));
}
diff --git a/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h b/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h
index ff93d903d41..fe6117100bf 100644
--- a/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h
+++ b/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h
@@ -51,7 +51,8 @@ class CONTENT_EXPORT RenderFrameMetadataProviderImpl
// methods are enqueued in |frame_token_message_queue_|. They are invoked when
// the browser process receives their associated frame tokens. These then
// notify any |observers_|.
- void OnFrameTokenRenderFrameMetadataChanged(cc::RenderFrameMetadata metadata);
+ void OnRenderFrameMetadataChangedAfterActivation(
+ cc::RenderFrameMetadata metadata);
void OnFrameTokenFrameSubmissionForTesting();
// Set |last_render_frame_metadata_| to the given |metadata| for testing
diff --git a/chromium/content/browser/renderer_host/render_message_filter.cc b/chromium/content/browser/renderer_host/render_message_filter.cc
index 765a4664465..8ca3b5ed1ff 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.cc
+++ b/chromium/content/browser/renderer_host/render_message_filter.cc
@@ -29,8 +29,6 @@
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
-#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
-#include "content/browser/dom_storage/session_storage_namespace_impl.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"
@@ -98,7 +96,6 @@ RenderMessageFilter::RenderMessageFilter(
net::URLRequestContextGetter* request_context,
RenderWidgetHelper* render_widget_helper,
MediaInternals* media_internals,
- DOMStorageContextWrapper* dom_storage_context,
CacheStorageContextImpl* cache_storage_context)
: BrowserMessageFilter(kRenderFilteredMessageClasses,
arraysize(kRenderFilteredMessageClasses)),
@@ -107,7 +104,6 @@ RenderMessageFilter::RenderMessageFilter(
request_context_(request_context),
resource_context_(browser_context->GetResourceContext()),
render_widget_helper_(render_widget_helper),
- dom_storage_context_(dom_storage_context),
render_process_id_(render_process_id),
media_internals_(media_internals),
cache_storage_context_(cache_storage_context),
diff --git a/chromium/content/browser/renderer_host/render_message_filter.h b/chromium/content/browser/renderer_host/render_message_filter.h
index d22da30d122..b90944a9f34 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.h
+++ b/chromium/content/browser/renderer_host/render_message_filter.h
@@ -18,7 +18,6 @@
#include "base/sequenced_task_runner_helpers.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
-#include "components/viz/common/resources/shared_bitmap_manager.h"
#include "content/common/render_message_filter.mojom.h"
#include "content/public/browser/browser_associated_interface.h"
#include "content/public/browser/browser_message_filter.h"
@@ -55,7 +54,6 @@ namespace content {
class BrowserContext;
class CacheStorageContextImpl;
class CacheStorageCacheHandle;
-class DOMStorageContextWrapper;
class MediaInternals;
class RenderWidgetHelper;
class ResourceContext;
@@ -74,7 +72,6 @@ class CONTENT_EXPORT RenderMessageFilter
net::URLRequestContextGetter* request_context,
RenderWidgetHelper* render_widget_helper,
MediaInternals* media_internals,
- DOMStorageContextWrapper* dom_storage_context,
CacheStorageContextImpl* cache_storage_context);
// BrowserMessageFilter methods:
@@ -149,8 +146,6 @@ class CONTENT_EXPORT RenderMessageFilter
scoped_refptr<RenderWidgetHelper> render_widget_helper_;
- scoped_refptr<DOMStorageContextWrapper> dom_storage_context_;
-
int render_process_id_;
MediaInternals* media_internals_;
diff --git a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
index a2106f21629..c81f8ed3587 100644
--- a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -1056,7 +1056,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, ConstructedButNotInitializedYet) {
EXPECT_FALSE(process->IsForGuestsOnly());
// There should be no OS process before Init() method is called.
- EXPECT_FALSE(process->HasConnection());
+ EXPECT_FALSE(process->IsInitializedAndNotDead());
EXPECT_FALSE(process->IsReady());
EXPECT_FALSE(process->GetProcess().IsValid());
EXPECT_EQ(base::kNullProcessHandle, process->GetProcess().Handle());
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 5ccfa4398c7..05e0ee79e5a 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -34,6 +34,7 @@
#include "base/memory/shared_memory.h"
#include "base/memory/shared_memory_handle.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/persistent_histogram_allocator.h"
@@ -41,6 +42,7 @@
#include "base/metrics/statistics_recorder.h"
#include "base/metrics/user_metrics.h"
#include "base/no_destructor.h"
+#include "base/numerics/ranges.h"
#include "base/process/process_handle.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
@@ -72,7 +74,6 @@
#include "content/browser/bad_message.h"
#include "content/browser/blob_storage/blob_dispatcher_host.h"
#include "content/browser/blob_storage/blob_registry_wrapper.h"
-#include "content/browser/blob_storage/blob_url_loader_factory.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/broadcast_channel/broadcast_channel_provider.h"
#include "content/browser/browser_child_process_host_impl.h"
@@ -117,6 +118,7 @@
#include "content/browser/renderer_host/p2p/socket_dispatcher_host.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/plugin_registry_impl.h"
#include "content/browser/renderer_host/render_message_filter.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -144,6 +146,7 @@
#include "content/common/resource_messages.h"
#include "content/common/service_manager/child_connection.h"
#include "content/common/service_manager/service_manager_connection_impl.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
@@ -169,7 +172,6 @@
#include "content/public/common/service_names.mojom.h"
#include "content/public/common/url_constants.h"
#include "device/gamepad/gamepad_haptics_manager.h"
-#include "device/gamepad/gamepad_monitor.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gpu_switches.h"
#include "gpu/command_buffer/common/context_creation_attribs.h"
@@ -183,7 +185,6 @@
#include "media/base/media_switches.h"
#include "media/media_buildflags.h"
#include "media/mojo/services/video_decode_perf_history.h"
-#include "mojo/edk/embedder/embedder.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
@@ -220,10 +221,12 @@
#include "content/public/browser/android/java_interfaces.h"
#include "ipc/ipc_sync_channel.h"
#include "media/audio/android/audio_manager_android.h"
+#else
+#include "content/browser/compositor/image_transport_factory.h"
#endif
-#if !defined(OS_ANDROID)
-#include "content/browser/compositor/image_transport_factory.h"
+#if defined(OS_MACOSX)
+#include "content/browser/mach_broker_mac.h"
#endif
#if defined(OS_WIN)
@@ -234,12 +237,8 @@
#include "ui/display/win/dpi.h"
#endif
-#if defined(OS_MACOSX)
-#include "content/browser/mach_broker_mac.h"
-#endif
-
-#if defined(USE_OZONE)
-#include "ui/ozone/public/ozone_switches.h"
+#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
+#include "content/browser/media/key_system_support_impl.h"
#endif
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -247,14 +246,18 @@
#include "ppapi/shared_impl/ppapi_switches.h" // nogncheck
#endif
-#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
-#include "content/browser/media/key_system_support_impl.h"
+#if BUILDFLAG(ENABLE_REPORTING)
+#include "content/browser/net/reporting_service_proxy.h"
#endif
#if BUILDFLAG(USE_MINIKIN_HYPHENATION)
#include "content/browser/hyphenation/hyphenation_impl.h"
#endif
+#if defined(USE_OZONE)
+#include "ui/ozone/public/ozone_switches.h"
+#endif
+
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
#include "services/service_manager/zygote/common/zygote_handle.h" // nogncheck
#endif
@@ -265,10 +268,6 @@
#define IntToStringType base::IntToString
#endif
-#if BUILDFLAG(ENABLE_REPORTING)
-#include "content/browser/net/reporting_service_proxy.h"
-#endif // BUILDFLAG(ENABLE_REPORTING)
-
namespace content {
using CheckOriginLockResult =
@@ -276,6 +275,18 @@ using CheckOriginLockResult =
namespace {
+// Stores the maximum number of renderer processes the content module can
+// create. Only applies if it is set to a non-zero value.
+size_t g_max_renderer_count_override = 0;
+
+bool g_run_renderer_in_process = false;
+
+RendererMainThreadFactoryFunction g_renderer_main_thread_factory = nullptr;
+RenderProcessHostImpl::CreateStoragePartitionServiceFunction
+ g_create_storage_partition = nullptr;
+
+base::MessageLoop* g_in_process_thread;
+
const RenderProcessHostFactory* g_render_process_host_factory_ = nullptr;
const char kSiteProcessMapKeyName[] = "content_site_process_map";
@@ -418,12 +429,12 @@ class SiteProcessMap : public base::SupportsUserData::Data {
// them.
std::set<std::string> sites;
for (SiteToProcessMap::const_iterator i = map_.begin(); i != map_.end();
- i++) {
+ ++i) {
if (i->second == host)
sites.insert(i->first);
}
for (std::set<std::string>::iterator i = sites.begin(); i != sites.end();
- i++) {
+ ++i) {
SiteToProcessMap::iterator iter = map_.find(*i);
if (iter != map_.end()) {
DCHECK_EQ(iter->second, host);
@@ -439,13 +450,15 @@ class SiteProcessMap : public base::SupportsUserData::Data {
// Find the SiteProcessMap specific to the given context.
SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) {
DCHECK(context);
- SiteProcessMap* map = static_cast<SiteProcessMap*>(
+ SiteProcessMap* existing_map = static_cast<SiteProcessMap*>(
context->GetUserData(kSiteProcessMapKeyName));
- if (!map) {
- map = new SiteProcessMap();
- context->SetUserData(kSiteProcessMapKeyName, base::WrapUnique(map));
- }
- return map;
+ if (existing_map)
+ return existing_map;
+
+ auto new_map = std::make_unique<SiteProcessMap>();
+ auto* new_map_ptr = new_map.get();
+ context->SetUserData(kSiteProcessMapKeyName, std::move(new_map));
+ return new_map_ptr;
}
// NOTE: changes to this class need to be reviewed by the security team.
@@ -619,7 +632,7 @@ class SpareRenderProcessHostManager : public RenderProcessHostObserver {
// If the spare process ends up getting killed, the spare manager should
// discard the spare RPH, so if one exists, it should always be live here.
- CHECK(spare_render_process_host_->HasConnection());
+ CHECK(spare_render_process_host_->IsInitializedAndNotDead());
DCHECK_EQ(SpareProcessMaybeTakeAction::kSpareTaken, action);
returned_process = spare_render_process_host_;
@@ -688,12 +701,6 @@ class SpareRenderProcessHostManager : public RenderProcessHostObserver {
}
}
- // RenderProcessHostObserver::RenderProcessWillExit is not overriden because:
- // 1. This simplifies reasoning when Cleanup can be called.
- // 2. In practice the spare shouldn't go through graceful shutdown.
- // 3. Handling RenderProcessExited and RenderProcessHostDestroyed is
- // sufficient from correctness perspective.
-
void RenderProcessExited(RenderProcessHost* host,
const ChildProcessTerminationInfo& info) override {
if (host == spare_render_process_host_)
@@ -771,7 +778,7 @@ class DefaultSubframeProcessHostHolder : public base::SupportsUserData::Data,
RenderProcessHost* host_ = nullptr;
};
-void CreateMemoryCoordinatorHandle(
+void CreateMemoryCoordinatorHandleForRenderProcess(
int render_process_id,
mojom::MemoryCoordinatorHandleRequest request) {
MemoryCoordinatorImpl::GetInstance()->CreateHandle(render_process_id,
@@ -1132,6 +1139,66 @@ class UnmatchedServiceWorkerProcessTracker
SiteProcessIDPairSet site_process_set_;
};
+bool ShouldBoostPriorityForPendingViews() {
+#if defined(OS_ANDROID)
+ // On Android, renderer processes with pending views get an extra boost.
+ return true;
+#else
+ // On desktop platforms, new renderer processes have been considered
+ // foreground regardless of visibility since r385608. This is because it was
+ // previously discovered that backgrounding processes that weren't responsible
+ // for visible content resulted in running foreground navigations at
+ // background priority until the main frame was committed (and became a
+ // visible widget)... Thus new processes responsible for hidden content are
+ // now foreground until explicitly made visible and hidden again. Full details
+ // @ https://crbug.com/560446.
+ //
+ // The experiment below will attempt to use the new "pending views" signal to
+ // go back to pre r385608 behavior while still boosting priority of processes
+ // with pending views (until widgets are created and visibility kicks in).
+ // This will however not keep the nice side-effect of r385608 which was to
+ // boost new page loads happening in background tabs (example use case of a
+ // foreground action in a background tab : ctrl+click link of interest and
+ // actively wait for spinner to stop before switching tabs). If we decide that
+ // the latter use case is relevant, we should support it cross-platform.
+ //
+ // Thus, while this is a "boosting" experiment, it's really a "consider the
+ // initial foreground state a boost so we can unboost and background sooner".
+ //
+ // Returning true here triggers the experiment because it will cause the
+ // initial |ChildProcessLauncherPriority::boost_for_pending_views| value to be
+ // |true| which will in turn result in a call to UpdateProcessPriority() when
+ // RemovePendingView() is invoked (without the experiment the initial state
+ // has no pending view and although UpdateProcessPriority() is invoked from
+ // RemovePendingView(), it no-ops per "no change" compared to the initial
+ // ChildProcessLauncherPriority).
+ //
+ // Furthermore, it has been discovered that there is a priority inversion in
+ // foreground navigation without this experiment, the reason being that
+ // ChildProcessLauncherPriority::operator==() notices a difference in
+ // UpdateProcessPriority() when only |boost_for_pending_views| has changed. On
+ // desktop it would start in the |false| state and AddPendingView() would
+ // toggle it. This would result in UpdateProcessPriority() but desktop not
+ // handling the presence of |boost_for_pending_views|, would look at |!visible
+ // && !has_media_stream| and decide that it's time to background (bringing
+ // back the OP of https://crbug.com/560446 but worse because actual background
+ // tabs are running as foreground per r385608 -- so during a big session
+ // restore it's possible to end up with all processes foreground except for
+ // the foreground tab's process...). Full details @
+ // https://crbug.com/560446#c74.
+ //
+ // Hence this experiment is definitely the desired behavior, running it as an
+ // experiment on Canary merely to see what was impacted by existing bugs.
+ // TODO(gab): End the experiment and turn ShouldBoostPriorityForPendingViews()
+ // into a constant when results are in.
+ static bool should_boost_for_pending_views =
+ base::StartsWith(base::FieldTrialList::FindFullName(
+ "BoostRendererPriorityForPendingViews"),
+ "Enabled", base::CompareCase::SENSITIVE);
+ return should_boost_for_pending_views;
+#endif
+}
+
void CopyFeatureSwitch(const base::CommandLine& src,
base::CommandLine* dest,
const char* switch_name) {
@@ -1142,19 +1209,6 @@ void CopyFeatureSwitch(const base::CommandLine& src,
} // namespace
-RendererMainThreadFactoryFunction g_renderer_main_thread_factory = nullptr;
-RenderProcessHostImpl::CreateStoragePartitionServiceFunction
- g_create_storage_partition = nullptr;
-
-base::MessageLoop* g_in_process_thread;
-
-// Stores the maximum number of renderer processes the content module can
-// create.
-static size_t g_max_renderer_count_override = 0;
-
-// static
-bool g_run_renderer_in_process_ = false;
-
// Held by the RPH and used to control an (unowned) ConnectionFilterImpl from
// any thread.
class RenderProcessHostImpl::ConnectionFilterController
@@ -1278,25 +1332,30 @@ size_t RenderProcessHost::GetMaxRendererProcessCount() {
return 100;
#endif
- // On other platforms, we calculate the maximum number of renderer process
- // hosts according to the amount of installed memory as reported by the OS.
- // The calculation assumes that you want the renderers to use half of the
- // installed RAM and assuming that each WebContents uses ~40MB. If you modify
- // this assumption, you need to adjust the ThirtyFourTabs test to match the
- // expected number of processes.
+ // On other platforms, calculate the maximum number of renderer process hosts
+ // according to the amount of installed memory as reported by the OS, along
+ // with some hard-coded limits. The calculation assumes that the renderers
+ // will use up to half of the installed RAM and assumes that each WebContents
+ // uses |kEstimatedWebContentsMemoryUsage| MB. If this assumption changes, the
+ // ThirtyFourTabs test needs to be adjusted to match the expected number of
+ // processes.
//
- // With the given amounts of installed memory below on a 32-bit CPU, the
- // maximum renderer count will roughly be as follows:
+ // Using the above assumptions, with the given amounts of installed memory
+ // below on a 64-bit CPU, the maximum renderer count based on available RAM
+ // alone will be as follows:
//
- // 128 MB -> 3
- // 512 MB -> 6
- // 1024 MB -> 12
- // 4096 MB -> 51
- // 16384 MB -> 82 (kMaxRendererProcessCount)
+ // 128 MB -> 1
+ // 512 MB -> 4
+ // 1024 MB -> 8
+ // 4096 MB -> 34
+ // 16384 MB -> 136
+ //
+ // Then the calculated value will be clamped by |kMinRendererProcessCount| and
+ // |kMaxRendererProcessCount|.
static size_t max_count = 0;
if (!max_count) {
- const size_t kEstimatedWebContentsMemoryUsage =
+ static constexpr size_t kEstimatedWebContentsMemoryUsage =
#if defined(ARCH_CPU_64_BITS)
60; // In MB
#else
@@ -1305,9 +1364,9 @@ size_t RenderProcessHost::GetMaxRendererProcessCount() {
max_count = base::SysInfo::AmountOfPhysicalMemoryMB() / 2;
max_count /= kEstimatedWebContentsMemoryUsage;
- const size_t kMinRendererProcessCount = 3;
- max_count = std::max(max_count, kMinRendererProcessCount);
- max_count = std::min(max_count, kMaxRendererProcessCount);
+ static constexpr size_t kMinRendererProcessCount = 3;
+ max_count = base::ClampToRange(max_count, kMinRendererProcessCount,
+ kMaxRendererProcessCount);
}
return max_count;
}
@@ -1321,12 +1380,11 @@ void RenderProcessHost::SetMaxRendererProcessCount(size_t count) {
// static
int RenderProcessHost::GetCurrentRenderProcessCountForTesting() {
- content::RenderProcessHost::iterator it =
- content::RenderProcessHost::AllHostsIterator();
+ RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
int count = 0;
while (!it.IsAtEnd()) {
RenderProcessHost* host = it.GetCurrentValue();
- if (host->HasConnection() &&
+ if (host->IsInitializedAndNotDead() &&
host != RenderProcessHostImpl::GetSpareRenderProcessHostForTesting()) {
count++;
}
@@ -1385,13 +1443,32 @@ RenderProcessHostImpl::RenderProcessHostImpl(
is_keep_alive_ref_count_disabled_(false),
route_provider_binding_(this),
visible_clients_(0),
- priority_({
- blink::kLaunchingProcessIsBackgrounded, frame_depth_,
- blink::kLaunchingProcessIsBoostedForPendingView,
+ priority_(!blink::kLaunchingProcessIsBackgrounded,
+ false /* has_media_stream */,
+ frame_depth_,
+ ShouldBoostPriorityForPendingViews(),
#if defined(OS_ANDROID)
- ChildProcessImportance::NORMAL,
+ // Only use |boost_for_pending_views| to infer is_background()
+ // on non-Android platforms for now to avoid changing the
+ // old behavior while the experiment is under way.
+ // Without this, the following tests were failing on Android
+ // (they assume that toggling WidgetHidden() is sufficient to
+ // toggle backgrounding):
+ // NavigationControllerBrowserTest.
+ // NoDialogsFromSwappedOutFrames
+ // SitePerProcessBrowserTest.
+ // CommitTimeoutForHungRenderer
+ // HiddenOOPIFWillNotGenerateCompositorFrames
+ // TODO(gab): Clean this up as soon as the experiment is over.
+ false
+#else
+ ShouldBoostPriorityForPendingViews()
#endif
- }),
+#if defined(OS_ANDROID)
+ ,
+ ChildProcessImportance::NORMAL
+#endif
+ ),
id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
browser_context_(browser_context),
storage_partition_impl_(storage_partition_impl),
@@ -1408,6 +1485,9 @@ RenderProcessHostImpl::RenderProcessHostImpl(
storage_partition_impl_->GetURLRequestContext(),
storage_partition_impl_->GetIndexedDBContext(),
ChromeBlobStorageContext::GetFor(browser_context_))),
+ service_worker_dispatcher_host_(new ServiceWorkerDispatcherHost(
+ storage_partition_impl_->GetServiceWorkerContext(),
+ id_)),
channel_connected_(false),
sent_render_process_ready_(false),
#if defined(OS_ANDROID)
@@ -1444,21 +1524,28 @@ RenderProcessHostImpl::RenderProcessHostImpl(
GetID(), storage_partition_impl_->GetServiceWorkerContext()));
AddObserver(indexed_db_factory_.get());
+ AddObserver(service_worker_dispatcher_host_.get());
#if defined(OS_MACOSX)
AddObserver(MachBroker::GetInstance());
#endif
InitializeChannelProxy();
- if (!base::FeatureList::IsEnabled(features::kMash))
- gpu_client_.reset(new GpuClientImpl(GetID()));
+ if (features::IsAshInBrowserProcess()) {
+ const int id = GetID();
+ const uint64_t tracing_id =
+ ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(id);
+ gpu_client_.reset(new GpuClientImpl(
+ id, tracing_id,
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
+ }
GetMemoryDumpProvider().AddHost(this);
}
// static
void RenderProcessHostImpl::ShutDownInProcessRenderer() {
- DCHECK(g_run_renderer_in_process_);
+ DCHECK(g_run_renderer_in_process);
switch (g_all_hosts.Pointer()->size()) {
case 0:
@@ -1524,11 +1611,9 @@ RenderProcessHostImpl::~RenderProcessHostImpl() {
bool RenderProcessHostImpl::Init() {
// calling Init() more than once does nothing, this makes it more convenient
// for the view host which may not be sure in some cases
- if (HasConnection())
+ if (IsInitializedAndNotDead())
return true;
- is_dead_ = false;
-
base::CommandLine::StringType renderer_prefix;
// A command prefix is something prepended to the command line of the spawned
// process.
@@ -1550,17 +1635,18 @@ bool RenderProcessHostImpl::Init() {
if (renderer_path.empty())
return false;
+ is_initialized_ = true;
+ is_dead_ = false;
+ sent_render_process_ready_ = false;
+
if (gpu_client_)
gpu_client_->PreEstablishGpuChannel();
- sent_render_process_ready_ = false;
-
// We may reach Init() during process death notification (e.g.
// RenderProcessExited on some observer). In this case the Channel may be
// null, so we re-initialize it here.
if (!channel_)
InitializeChannelProxy();
- DCHECK(broker_client_invitation_);
// Unpause the Channel briefly. This will be paused again below if we launch a
// real child process. Note that messages may be sent in the short window
@@ -1612,8 +1698,7 @@ bool RenderProcessHostImpl::Init() {
in_process_renderer_.reset(
g_renderer_main_thread_factory(InProcessChildThreadParams(
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- broker_client_invitation_.get(),
- child_connection_->service_token())));
+ &mojo_invitation_, child_connection_->service_token())));
base::Thread::Options options;
#if defined(OS_WIN) && !defined(OS_MACOSX)
@@ -1649,11 +1734,10 @@ bool RenderProcessHostImpl::Init() {
// Spawn the child process asynchronously to avoid blocking the UI thread.
// As long as there's no renderer prefix, we can use the zygote process
// at this stage.
- child_process_launcher_.reset(new ChildProcessLauncher(
+ child_process_launcher_ = std::make_unique<ChildProcessLauncher>(
std::make_unique<RendererSandboxedProcessLauncherDelegate>(),
- std::move(cmd_line), GetID(), this,
- std::move(broker_client_invitation_),
- base::Bind(&RenderProcessHostImpl::OnMojoError, id_)));
+ std::move(cmd_line), GetID(), this, std::move(mojo_invitation_),
+ base::BindRepeating(&RenderProcessHostImpl::OnMojoError, id_));
channel_->Pause();
fast_shutdown_started_ = false;
@@ -1664,9 +1748,6 @@ bool RenderProcessHostImpl::Init() {
ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
}
- GetRendererInterface()->SetUserAgent(GetContentClient()->GetUserAgent());
-
- is_initialized_ = true;
init_time_ = base::TimeTicks::Now();
return true;
}
@@ -1700,15 +1781,13 @@ void RenderProcessHostImpl::InitializeChannelProxy() {
}
// Establish a ServiceManager connection for the new render service instance.
- broker_client_invitation_ =
- std::make_unique<mojo::edk::OutgoingBrokerClientInvitation>();
+ mojo_invitation_ = {};
service_manager::Identity child_identity(
mojom::kRendererServiceName,
BrowserContext::GetServiceUserIdFor(GetBrowserContext()),
base::StringPrintf("%d_%d", id_, instance_id_++));
- child_connection_.reset(new ChildConnection(child_identity,
- broker_client_invitation_.get(),
- connector, io_task_runner));
+ child_connection_ = std::make_unique<ChildConnection>(
+ child_identity, &mojo_invitation_, connector, io_task_runner);
// Send an interface request to bootstrap the IPC::Channel. Note that this
// request will happily sit on the pipe until the process is launched and
@@ -1736,9 +1815,10 @@ void RenderProcessHostImpl::InitializeChannelProxy() {
&never_signaled_);
}
#endif // OS_ANDROID
- if (!channel_)
- channel_.reset(new IPC::ChannelProxy(this, io_task_runner.get(),
- base::ThreadTaskRunnerHandle::Get()));
+ if (!channel_) {
+ channel_ = std::make_unique<IPC::ChannelProxy>(
+ this, io_task_runner.get(), base::ThreadTaskRunnerHandle::Get());
+ }
channel_->Init(std::move(channel_factory), true /* create_pipe_now */);
// Note that Channel send is effectively paused and unpaused at various points
@@ -1774,7 +1854,6 @@ void RenderProcessHostImpl::ResetChannelProxy() {
void RenderProcessHostImpl::CreateMessageFilters() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- AddFilter(new ResourceSchedulerFilter(GetID()));
MediaInternals* media_internals = MediaInternals::GetInstance();
// Add BrowserPluginMessageFilter to ensure it gets the first stab at messages
// from guests.
@@ -1783,12 +1862,11 @@ void RenderProcessHostImpl::CreateMessageFilters() {
scoped_refptr<net::URLRequestContextGetter> request_context(
storage_partition_impl_->GetURLRequestContext());
- scoped_refptr<RenderMessageFilter> render_message_filter(
- new RenderMessageFilter(
+ scoped_refptr<RenderMessageFilter> render_message_filter =
+ base::MakeRefCounted<RenderMessageFilter>(
GetID(), GetBrowserContext(), request_context.get(),
widget_helper_.get(), media_internals,
- storage_partition_impl_->GetDOMStorageContext(),
- storage_partition_impl_->GetCacheStorageContext()));
+ storage_partition_impl_->GetCacheStorageContext());
AddFilter(render_message_filter.get());
render_frame_message_filter_ = new RenderFrameMessageFilter(
@@ -1844,14 +1922,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(new TextInputClientMessageFilter());
#endif
- auto service_worker_filter =
- base::MakeRefCounted<ServiceWorkerDispatcherHost>(GetID());
- service_worker_filter->Init(
- storage_partition_impl_->GetServiceWorkerContext());
- AddFilter(service_worker_filter.get());
-
- p2p_socket_dispatcher_host_ = new P2PSocketDispatcherHost(
- resource_context, request_context.get());
+ p2p_socket_dispatcher_host_ =
+ new P2PSocketDispatcherHost(request_context.get());
AddFilter(p2p_socket_dispatcher_host_.get());
AddFilter(new TraceMessageFilter(GetID()));
@@ -1910,6 +1982,10 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
base::Bind(&IndexedDBDispatcherHost::AddBinding,
base::Unretained(indexed_db_factory_.get())));
+ channel_->AddAssociatedInterfaceForIOThread(base::BindRepeating(
+ &ServiceWorkerDispatcherHost::AddBinding,
+ base::Unretained(service_worker_dispatcher_host_.get())));
+
AddUIThreadInterface(
registry.get(), base::Bind(&ForwardRequest<device::mojom::BatteryMonitor>,
device::mojom::kServiceName));
@@ -1944,7 +2020,8 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
storage_partition_impl_->GetBroadcastChannelProvider())));
if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) {
AddUIThreadInterface(
- registry.get(), base::Bind(&CreateMemoryCoordinatorHandle, GetID()));
+ registry.get(),
+ base::Bind(&CreateMemoryCoordinatorHandleForRenderProcess, GetID()));
}
if (resource_coordinator::IsResourceCoordinatorEnabled()) {
AddUIThreadInterface(
@@ -1952,13 +2029,8 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
base::Bind(&CreateProcessResourceCoordinator, base::Unretained(this)));
}
- BrowserContext* browser_context = GetBrowserContext();
- scoped_refptr<ChromeBlobStorageContext> blob_storage_context =
- ChromeBlobStorageContext::GetFor(browser_context);
-
AddUIThreadInterface(registry.get(),
- base::BindRepeating(&ClipboardHostImpl::Create,
- std::move(blob_storage_context)));
+ base::BindRepeating(&ClipboardHostImpl::Create));
media::VideoDecodePerfHistory* video_perf_history =
GetBrowserContext()->GetVideoDecodePerfHistory();
@@ -1979,8 +2051,6 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
registry->AddInterface(base::Bind(&device::GamepadHapticsManager::Create));
- registry->AddInterface(base::Bind(&device::GamepadMonitor::Create));
-
registry->AddInterface(
base::Bind(&PushMessagingManager::BindRequest,
base::Unretained(push_messaging_manager_.get())));
@@ -1988,8 +2058,8 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
if (gpu_client_) {
// |gpu_client_| outlives the registry, because its destruction is posted to
// IO thread from the destructor of |this|.
- registry->AddInterface(
- base::Bind(&GpuClientImpl::Add, base::Unretained(gpu_client_.get())));
+ registry->AddInterface(base::BindRepeating(
+ &GpuClientImpl::Add, base::Unretained(gpu_client_.get())));
}
registry->AddInterface(
@@ -2028,7 +2098,7 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
AddUIThreadInterface(registry.get(), base::Bind(&FieldTrialRecorder::Create));
- associated_interfaces_.reset(new AssociatedInterfaceRegistryImpl());
+ associated_interfaces_ = std::make_unique<AssociatedInterfaceRegistryImpl>();
blink::AssociatedInterfaceRegistry* associated_registry =
associated_interfaces_.get();
associated_registry->AddInterface(base::Bind(
@@ -2047,6 +2117,17 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
base::BindRepeating(&BlobRegistryWrapper::Bind,
storage_partition_impl_->GetBlobRegistry(), GetID()));
+#if BUILDFLAG(ENABLE_PLUGINS)
+ // Initialization can happen more than once (in the case of a child process
+ // crash), but we don't want to lose the plugin registry in this case.
+ if (!plugin_registry_) {
+ plugin_registry_.reset(
+ new PluginRegistryImpl(GetBrowserContext()->GetResourceContext()));
+ }
+ registry->AddInterface(base::BindRepeating(
+ &PluginRegistryImpl::Bind, base::Unretained(plugin_registry_.get())));
+#endif
+
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
registry->AddInterface(base::BindRepeating(&KeySystemSupportImpl::Create));
#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS)
@@ -2066,9 +2147,9 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
connection_filter_controller_->DisableFilter();
service_manager_connection->RemoveConnectionFilter(connection_filter_id_);
}
- std::unique_ptr<ConnectionFilterImpl> connection_filter(
- new ConnectionFilterImpl(child_connection_->child_identity(),
- std::move(registry)));
+ std::unique_ptr<ConnectionFilterImpl> connection_filter =
+ std::make_unique<ConnectionFilterImpl>(
+ child_connection_->child_identity(), std::move(registry));
connection_filter_controller_ = connection_filter->controller();
connection_filter_id_ = service_manager_connection->AddConnectionFilter(
std::move(connection_filter));
@@ -2099,16 +2180,6 @@ void RenderProcessHostImpl::GetAssociatedInterface(
listener->OnAssociatedInterfaceRequest(name, request.PassHandle());
}
-void RenderProcessHostImpl::GetBlobURLLoaderFactory(
- network::mojom::URLLoaderFactoryRequest request) {
- if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- NOTREACHED();
- return;
- }
- storage_partition_impl_->GetBlobURLLoaderFactory()->HandleRequest(
- std::move(request));
-}
-
void RenderProcessHostImpl::CreateEmbeddedFrameSinkProvider(
blink::mojom::EmbeddedFrameSinkProviderRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -2134,7 +2205,7 @@ void RenderProcessHostImpl::BindCompositingModeReporter(
}
void RenderProcessHostImpl::CreateStoragePartitionService(
- mojom::StoragePartitionServiceRequest request) {
+ blink::mojom::StoragePartitionServiceRequest request) {
if (g_create_storage_partition) {
g_create_storage_partition(this, std::move(request));
return;
@@ -2148,21 +2219,6 @@ void RenderProcessHostImpl::CreateRendererHost(
renderer_host_binding_.Bind(std::move(request));
}
-void RenderProcessHostImpl::CreateURLLoaderFactory(
- network::mojom::URLLoaderFactoryRequest request) {
- if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- NOTREACHED();
- return;
- }
- network::mojom::URLLoaderFactoryParamsPtr params =
- network::mojom::URLLoaderFactoryParams::New();
- params->process_id = id_;
- // TODO(lukasza): https://crbug.com/792546: Start using CORB.
- params->is_corb_enabled = false;
- storage_partition_impl_->GetNetworkContext()->CreateURLLoaderFactory(
- std::move(request), std::move(params));
-}
-
int RenderProcessHostImpl::GetNextRoutingID() {
return widget_helper_->GetNextRoutingID();
}
@@ -2175,6 +2231,11 @@ void RenderProcessHostImpl::BindInterface(
const service_manager::Identity& RenderProcessHostImpl::GetChildIdentity()
const {
+ // GetChildIdentity should only be called if the RPH is (or soon will be)
+ // backed by an actual renderer process. This helps prevent leaks similar to
+ // the ones raised in https://crbug.com/813045.
+ DCHECK(IsInitializedAndNotDead());
+
return child_connection_->child_identity();
}
@@ -2189,7 +2250,7 @@ const base::TimeTicks& RenderProcessHostImpl::GetInitTimeForNavigationMetrics()
}
bool RenderProcessHostImpl::IsProcessBackgrounded() const {
- return priority_.background;
+ return priority_.is_background();
}
void RenderProcessHostImpl::IncrementKeepAliveRefCount(
@@ -2310,6 +2371,26 @@ RenderProcessHostImpl::GetProcessResourceCoordinator() {
return process_resource_coordinator_.get();
}
+void RenderProcessHostImpl::CreateURLLoaderFactory(
+ network::mojom::URLLoaderFactoryRequest request) {
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&ResourceMessageFilter::Clone, resource_message_filter_,
+ std::move(request)));
+ return;
+ }
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = id_;
+ params->disable_web_security =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity);
+ SiteIsolationPolicy::PopulateURLLoaderFactoryParamsPtrForCORB(params.get());
+ storage_partition_impl_->GetNetworkContext()->CreateURLLoaderFactory(
+ std::move(request), std::move(params));
+}
+
void RenderProcessHostImpl::SetIsNeverSuitableForReuse() {
is_never_suitable_for_reuse_ = true;
}
@@ -2374,8 +2455,9 @@ void RenderProcessHostImpl::ShutdownForBadMessage(
if (crash_report_mode == CrashReportMode::GENERATE_CRASH_DUMP) {
// Set crash keys to understand renderer kills related to site isolation.
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ std::string lock_url = policy->GetOriginLock(GetID()).spec();
base::debug::SetCrashKeyString(bad_message::GetKilledProcessOriginLockKey(),
- policy->GetOriginLock(GetID()).spec());
+ lock_url.empty() ? "(none)" : lock_url);
std::string site_isolation_mode;
if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
@@ -2384,6 +2466,8 @@ void RenderProcessHostImpl::ShutdownForBadMessage(
site_isolation_mode += "tdi ";
if (SiteIsolationPolicy::AreIsolatedOriginsEnabled())
site_isolation_mode += "io ";
+ if (site_isolation_mode.empty())
+ site_isolation_mode = "(none)";
static auto* isolation_mode_key = base::debug::AllocateCrashKeyString(
"site_isolation_mode", base::debug::CrashKeySize::Size32);
@@ -2579,6 +2663,30 @@ bool RenderProcessHostImpl::HostHasNotBeenUsed() {
pending_views_ == 0;
}
+void RenderProcessHostImpl::LockToOrigin(const GURL& lock_url) {
+ ChildProcessSecurityPolicyImpl::GetInstance()->LockToOrigin(GetID(),
+ lock_url);
+
+ // Note that LockToOrigin is only called once per RenderProcessHostImpl (when
+ // committing a navigation into an empty renderer). Therefore, the call to
+ // NotifyRendererIfLockedToSite below is insufficient for setting up renderers
+ // respawned after crashing - this is handled by another call to
+ // NotifyRendererIfLockedToSite from OnProcessLaunched.
+ NotifyRendererIfLockedToSite();
+}
+
+void RenderProcessHostImpl::NotifyRendererIfLockedToSite() {
+ GURL lock_url =
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(GetID());
+ if (!lock_url.is_valid())
+ return;
+
+ if (!SiteInstanceImpl::IsOriginLockASite(lock_url))
+ return;
+
+ GetRendererInterface()->SetIsLockedToSite();
+}
+
bool RenderProcessHostImpl::IsForGuestsOnly() const {
return is_for_guests_only_;
}
@@ -2723,6 +2831,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableV8IdleTasks,
switches::kDisableWebGLImageChromium,
switches::kDomAutomationController,
+ switches::kEnableAccessibilityObjectModel,
switches::kEnableAutomation,
switches::kEnableBlinkGenPropertyTrees,
switches::kEnableExperimentalWebPlatformFeatures,
@@ -2732,28 +2841,29 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableGPUServiceLogging,
switches::kEnableLowResTiling,
switches::kEnableMediaSuspend,
- switches::kEnableInbandTextTracks,
switches::kEnableLCDText,
switches::kEnableLogging,
switches::kEnableNetworkInformationDownlinkMax,
- switches::kEnableOOPRasterization,
switches::kEnablePluginPlaceholderTesting,
switches::kEnablePreciseMemoryInfo,
switches::kEnablePrintBrowser,
switches::kEnablePreferCompositingToLCDText,
switches::kEnableRGBA4444Textures,
switches::kEnableSkiaBenchmarking,
- switches::kEnableSlimmingPaintV175,
switches::kEnableSlimmingPaintV2,
switches::kEnableThreadedCompositing,
switches::kEnableTouchDragDrop,
+ switches::kEnableUnsafeWebGPU,
switches::kEnableUseZoomForDSF,
switches::kEnableViewport,
switches::kEnableVtune,
+ switches::kEnableWebGL2ComputeContext,
switches::kEnableWebGLDraftExtensions,
switches::kEnableWebGLImageChromium,
switches::kEnableWebVR,
switches::kExplicitlyAllowedPorts,
+ switches::kFileUrlPathAlias,
+ switches::kFMPNetworkQuietTimeout,
switches::kForceColorProfile,
switches::kForceDeviceScaleFactor,
switches::kForceGpuMemAvailableMb,
@@ -2766,8 +2876,8 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kLoggingLevel,
switches::kMaxUntiledLayerWidth,
switches::kMaxUntiledLayerHeight,
- switches::kMSEAudioBufferSizeLimit,
- switches::kMSEVideoBufferSizeLimit,
+ switches::kMSEAudioBufferSizeLimitMb,
+ switches::kMSEVideoBufferSizeLimitMb,
switches::kNoZygote,
switches::kOverridePluginPowerSaverForTesting,
switches::kPassiveListenersDefault,
@@ -2988,7 +3098,9 @@ bool RenderProcessHostImpl::FastShutdownIfPossible(size_t page_count,
}
bool RenderProcessHostImpl::Send(IPC::Message* msg) {
- TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::Send");
+ TRACE_EVENT2("renderer_host", "RenderProcessHostImpl::Send", "class",
+ IPC_MESSAGE_ID_CLASS(msg->type()), "line",
+ IPC_MESSAGE_ID_LINE(msg->type()));
std::unique_ptr<IPC::Message> message(msg);
@@ -3003,7 +3115,7 @@ bool RenderProcessHostImpl::Send(IPC::Message* msg) {
if (message->is_sync()) {
// If Init() hasn't been called yet since construction or the last
// ProcessDied() we avoid blocking on sync IPC.
- if (!HasConnection())
+ if (!IsInitializedAndNotDead())
return false;
// Likewise if we've done Init(), but process launch has not yet completed,
@@ -3118,7 +3230,7 @@ int RenderProcessHostImpl::GetID() const {
return id_;
}
-bool RenderProcessHostImpl::HasConnection() const {
+bool RenderProcessHostImpl::IsInitializedAndNotDead() const {
return is_initialized_ && !is_dead_;
}
@@ -3185,7 +3297,7 @@ void RenderProcessHostImpl::Cleanup() {
// notify all observers that the process has exited cleanly, even though it
// will be destroyed a bit later. Observers shouldn't rely on this process
// anymore.
- if (HasConnection()) {
+ if (IsInitializedAndNotDead()) {
// Populates Android-only fields and closes the underlying base::Process.
ChildProcessTerminationInfo info =
child_process_launcher_->GetChildTerminationInfo(
@@ -3232,19 +3344,21 @@ void RenderProcessHostImpl::Cleanup() {
// reused in between now and when the Delete task runs.
UnregisterHost(GetID());
- instance_weak_factory_.reset(
- new base::WeakPtrFactory<RenderProcessHostImpl>(this));
+ instance_weak_factory_ =
+ std::make_unique<base::WeakPtrFactory<RenderProcessHostImpl>>(this);
}
void RenderProcessHostImpl::AddPendingView() {
- pending_views_++;
- UpdateProcessPriority();
+ const bool had_pending_views = pending_views_++;
+ if (!had_pending_views)
+ UpdateProcessPriority();
}
void RenderProcessHostImpl::RemovePendingView() {
DCHECK(pending_views_);
- pending_views_--;
- UpdateProcessPriority();
+ --pending_views_;
+ if (!pending_views_)
+ UpdateProcessPriority();
}
void RenderProcessHostImpl::AddWidget(RenderWidgetHost* widget) {
@@ -3492,12 +3606,12 @@ void RenderProcessHost::WarmupSpareRenderProcessHost(
// static
bool RenderProcessHost::run_renderer_in_process() {
- return g_run_renderer_in_process_;
+ return g_run_renderer_in_process;
}
// static
void RenderProcessHost::SetRunRendererInProcess(bool value) {
- g_run_renderer_in_process_ = value;
+ g_run_renderer_in_process = value;
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (value) {
@@ -3530,10 +3644,9 @@ RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
// static
RenderProcessHost* RenderProcessHost::FromRendererIdentity(
const service_manager::Identity& identity) {
- for (content::RenderProcessHost::iterator i(
- content::RenderProcessHost::AllHostsIterator());
+ for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
!i.IsAtEnd(); i.Advance()) {
- content::RenderProcessHost* process = i.GetCurrentValue();
+ RenderProcessHost* process = i.GetCurrentValue();
if (process->GetChildIdentity() == identity)
return process;
}
@@ -3805,11 +3918,12 @@ void RenderProcessHostImpl::CreateSharedRendererHistogramAllocator() {
// it. Memory that is not actualy used won't be physically mapped by the
// system. RendererMetrics usage, as reported in UMA, peaked around 0.7MiB
// as of 2016-12-20.
- std::unique_ptr<base::SharedMemory> shm(new base::SharedMemory());
+ auto shm = std::make_unique<base::SharedMemory>();
if (!shm->CreateAndMapAnonymous(2 << 20)) // 2 MiB
return;
- metrics_allocator_.reset(new base::SharedPersistentMemoryAllocator(
- std::move(shm), GetID(), "RendererMetrics", /*readonly=*/false));
+ metrics_allocator_ =
+ std::make_unique<base::SharedPersistentMemoryAllocator>(
+ std::move(shm), GetID(), "RendererMetrics", /*readonly=*/false);
}
HistogramController::GetInstance()->SetHistogramMemory<RenderProcessHost>(
@@ -3982,11 +4096,6 @@ void RenderProcessHostImpl::ShutdownRequest() {
return;
}
- // Notify any contents that might have swapped out renderers from this
- // process. They should not attempt to swap them back in.
- for (auto& observer : observers_) {
- observer.RenderProcessWillExit(this);
- }
child_control_interface_->ProcessShutdown();
}
@@ -4026,13 +4135,14 @@ void RenderProcessHostImpl::UpdateProcessPriorityInputs() {
}
bool inputs_changed = new_visible_widgets_count != visible_clients_;
-#if defined(OS_ANDROID)
- // OS_ANDROID in order to maintain the workaround on desktop to avoid
- // backgrounding a new process. See the comment in OnProcessLaunched and
- // https://crbug.com/560446. Only android uses frame_depth for now, so
- // not a huge change.
- inputs_changed = inputs_changed || frame_depth_ != new_frame_depth;
-#endif
+
+ // Hide this update behind the ShouldBoostPriorityForPendingViews() experiment
+ // at the moment to avoid causing an undesired early UpdateProcessPriority().
+ // See the comment in OnProcessLaunched() and https://crbug.com/560446.
+ if (ShouldBoostPriorityForPendingViews()) {
+ inputs_changed = inputs_changed || frame_depth_ != new_frame_depth;
+ }
+
visible_clients_ = new_visible_widgets_count;
frame_depth_ = new_frame_depth;
#if defined(OS_ANDROID)
@@ -4047,35 +4157,40 @@ void RenderProcessHostImpl::UpdateProcessPriorityInputs() {
void RenderProcessHostImpl::UpdateProcessPriority() {
if (!run_renderer_in_process() && (!child_process_launcher_.get() ||
child_process_launcher_->IsStarting())) {
- priority_.background = blink::kLaunchingProcessIsBackgrounded;
- priority_.boost_for_pending_views =
- blink::kLaunchingProcessIsBoostedForPendingView;
+ // This path can be hit early (no-op) or on ProcessDied(). Reset |priority_|
+ // to defaults in case this RenderProcessHostImpl is re-used.
+ priority_.visible = !blink::kLaunchingProcessIsBackgrounded;
+ priority_.boost_for_pending_views = ShouldBoostPriorityForPendingViews();
return;
}
- const ChildProcessLauncherPriority priority = {
- // We background a process as soon as it hosts no active audio/video streams
- // and no visible widgets -- the callers must call this function whenever we
- // transition in/out of those states.
- visible_clients_ == 0 && media_stream_count_ == 0 &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableRendererBackgrounding),
- frame_depth_,
- // boost_for_pending_views
- !!pending_views_,
+ const ChildProcessLauncherPriority priority(
+ visible_clients_ > 0 || base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableRendererBackgrounding),
+ media_stream_count_ > 0, frame_depth_,
+ !!pending_views_ /* boost_for_pending_views */,
#if defined(OS_ANDROID)
- GetEffectiveImportance(),
+ // Same hack as in RenderProcessHostImpl::RenderProcessHostImpl.
+ // TODO(gab): Clean this up after ShouldBoostPriorityForPendingViews()
+ // experiment.
+ false
+#else
+ ShouldBoostPriorityForPendingViews()
#endif
- };
+#if defined(OS_ANDROID)
+ ,
+ GetEffectiveImportance()
+#endif
+ );
const bool should_background_changed =
- priority_.background != priority.background;
+ priority_.is_background() != priority.is_background();
if (priority_ == priority)
return;
TRACE_EVENT2("renderer_host", "RenderProcessHostImpl::UpdateProcessPriority",
- "should_background", priority.background, "has_pending_views",
- priority.boost_for_pending_views);
+ "should_background", priority.is_background(),
+ "has_pending_views", priority.boost_for_pending_views);
priority_ = priority;
#if defined(OS_WIN)
@@ -4100,11 +4215,9 @@ void RenderProcessHostImpl::UpdateProcessPriority() {
child_process_launcher_->SetProcessPriority(priority_);
}
- // Notify the child process of background state. Note
- // |priority_.boost_for_pending_views| state is not sent to renderer simply
- // due to lack of need.
+ // Notify the child process of background state.
if (should_background_changed) {
- GetRendererInterface()->SetProcessBackgrounded(priority.background);
+ GetRendererInterface()->SetProcessBackgrounded(priority_.is_background());
}
}
@@ -4118,7 +4231,9 @@ void RenderProcessHostImpl::OnProcessLaunched() {
if (child_process_launcher_) {
DCHECK(child_process_launcher_->GetProcess().IsValid());
- DCHECK_EQ(blink::kLaunchingProcessIsBackgrounded, priority_.background);
+ // TODO(https://crbug.com/875933): This should be based on
+ // |priority_.is_background()|, see similar check below.
+ DCHECK_EQ(blink::kLaunchingProcessIsBackgrounded, !priority_.visible);
// Unpause the channel now that the process is launched. We don't flush it
// yet to ensure that any initialization messages sent here (e.g., things
@@ -4131,37 +4246,42 @@ void RenderProcessHostImpl::OnProcessLaunched() {
child_process_launcher_->GetProcess().Handle());
}
- // Not all platforms launch processes in the same backgrounded state. Make
- // sure |priority_.background| reflects this platform's initial process
- // state.
+// Not all platforms launch processes in the same backgrounded state. Make
+// sure |priority_.visible| reflects this platform's initial process
+// state.
#if defined(OS_MACOSX)
- priority_.background =
- child_process_launcher_->GetProcess().IsProcessBackgrounded(
+ priority_.visible =
+ !child_process_launcher_->GetProcess().IsProcessBackgrounded(
MachBroker::GetInstance());
#elif defined(OS_ANDROID)
// Android child process priority works differently and cannot be queried
// directly from base::Process.
- DCHECK_EQ(blink::kLaunchingProcessIsBackgrounded, priority_.background);
+ // TODO(https://crbug.com/875933): Fix initial priority on Android to
+ // reflect |priority_.is_background()|.
+ DCHECK_EQ(blink::kLaunchingProcessIsBackgrounded, !priority_.visible);
#else
- priority_.background =
- child_process_launcher_->GetProcess().IsProcessBackgrounded();
+ priority_.visible =
+ !child_process_launcher_->GetProcess().IsProcessBackgrounded();
#endif // defined(OS_MACOSX)
- // Disable updating process priority on startup on desktop platforms 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.
- // This is still needed on Android which uses
- // |priority_.boost_for_pending_views| and requires RenderProcessHostImpl to
- // propagate priority changes immediately to ChildProcessLauncher.
-#if defined(OS_ANDROID)
- UpdateProcessPriority();
-#endif
+ // Only update the priority on startup if boosting is enabled (to avoid
+ // reintroducing https://crbug.com/560446#c13 while pending views only
+ // experimentally result in a boost).
+ if (priority_.boost_for_pending_views)
+ UpdateProcessPriority();
// Share histograms between the renderer and this process.
CreateSharedRendererHistogramAllocator();
}
+ // Pass bits of global renderer state to the renderer.
+ GetRendererInterface()->SetUserAgent(GetContentClient()->GetUserAgent());
+ NotifyRendererIfLockedToSite();
+ if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites() &&
+ base::FeatureList::IsEnabled(features::kV8LowMemoryModeForSubframes)) {
+ GetRendererInterface()->EnableV8LowMemoryMode();
+ }
+
// NOTE: This needs to be before flushing queued messages, because
// ExtensionService uses this notification to initialize the renderer process
// with state that must be there before any JavaScript executes.
@@ -4278,7 +4398,7 @@ RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite(
auto iterator = eligible_foreground_hosts.begin();
for (int i = 0; i < index; ++i)
++iterator;
- return (*iterator);
+ return *iterator;
}
if (!eligible_background_hosts.empty()) {
@@ -4286,7 +4406,7 @@ RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite(
auto iterator = eligible_background_hosts.begin();
for (int i = 0; i < index; ++i)
++iterator;
- return (*iterator);
+ return *iterator;
}
return nullptr;
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 b418b4c8a0a..582d8037c2b 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -40,22 +40,22 @@
#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
#include "content/common/renderer.mojom.h"
#include "content/common/renderer_host.mojom.h"
-#include "content/common/storage_partition_service.mojom.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/service_manager_connection.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_platform_file.h"
#include "media/media_buildflags.h"
-#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/system/invitation.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/mojom/service.mojom.h"
#include "services/ui/public/interfaces/gpu.mojom.h"
#include "services/viz/public/interfaces/compositing/compositing_mode_watcher.mojom.h"
+#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gl/gpu_switching_observer.h"
@@ -79,6 +79,7 @@ class MediaStreamTrackMetricsHost;
class P2PSocketDispatcherHost;
class PermissionServiceContext;
class PeerConnectionTrackerHost;
+class PluginRegistryImpl;
class PushMessagingManager;
class RenderFrameMessageFilter;
class RenderProcessHostFactory;
@@ -86,6 +87,7 @@ class RenderWidgetHelper;
class RenderWidgetHost;
class RenderWidgetHostImpl;
class ResourceMessageFilter;
+class ServiceWorkerDispatcherHost;
class SiteInstance;
class SiteInstanceImpl;
class StoragePartition;
@@ -160,7 +162,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
BrowserContext* GetBrowserContext() const override;
bool InSameStoragePartition(StoragePartition* partition) const override;
int GetID() const override;
- bool HasConnection() const override;
+ bool IsInitializedAndNotDead() const override;
void SetIgnoreInputEvents(bool ignore_input_events) override;
bool IgnoreInputEvents() const override;
void Cleanup() override;
@@ -206,6 +208,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
mojom::Renderer* GetRendererInterface() override;
resource_coordinator::ProcessResourceCoordinator*
GetProcessResourceCoordinator() override;
+ void CreateURLLoaderFactory(
+ network::mojom::URLLoaderFactoryRequest request) override;
void SetIsNeverSuitableForReuse() override;
bool MayReuseHost() override;
@@ -213,6 +217,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
void SetIsUsed() override;
bool HostHasNotBeenUsed() override;
+ void LockToOrigin(const GURL& lock_url) override;
void BindCacheStorage(blink::mojom::CacheStorageRequest request,
const url::Origin& origin) override;
@@ -323,7 +328,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
// service.
using CreateStoragePartitionServiceFunction =
void (*)(RenderProcessHostImpl* rph,
- mojom::StoragePartitionServiceRequest request);
+ blink::mojom::StoragePartitionServiceRequest request);
static void SetCreateStoragePartitionServiceFunction(
CreateStoragePartitionServiceFunction function);
@@ -466,8 +471,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
mojom::AssociatedInterfaceAssociatedRequest request) override;
// mojom::RendererHost
- void GetBlobURLLoaderFactory(
- network::mojom::URLLoaderFactoryRequest request) override;
using BrowserHistogramCallback =
mojom::RendererHost::GetBrowserHistogramCallback;
void GetBrowserHistogram(const std::string& name,
@@ -483,9 +486,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
void BindCompositingModeReporter(
viz::mojom::CompositingModeReporterRequest request);
void CreateStoragePartitionService(
- mojom::StoragePartitionServiceRequest request);
+ blink::mojom::StoragePartitionServiceRequest request);
void CreateRendererHost(mojom::RendererHostAssociatedRequest request);
- void CreateURLLoaderFactory(network::mojom::URLLoaderFactoryRequest request);
// Control message handlers.
void OnUserMetricsRecordAction(const std::string& action);
@@ -574,6 +576,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
base::FilePath GetAecDumpFilePathWithExtensions(const base::FilePath& file);
base::SequencedTaskRunner& GetAecDumpFileTaskRunner();
void OnAec3Enabled();
+ void NotifyRendererIfLockedToSite();
static void OnMojoError(int render_process_id, const std::string& error);
@@ -612,8 +615,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
// execute.
void CancelProcessShutdownDelayForUnload();
- std::unique_ptr<mojo::edk::OutgoingBrokerClientInvitation>
- broker_client_invitation_;
+ mojo::OutgoingInvitation mojo_invitation_;
std::unique_ptr<ChildConnection> child_connection_;
int connection_filter_id_ =
@@ -788,6 +790,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
std::unique_ptr<IndexedDBDispatcherHost, BrowserThread::DeleteOnIOThread>
indexed_db_factory_;
+ std::unique_ptr<ServiceWorkerDispatcherHost, BrowserThread::DeleteOnIOThread>
+ service_worker_dispatcher_host_;
+
scoped_refptr<CacheStorageDispatcherHost> cache_storage_dispatcher_host_;
bool channel_connected_;
@@ -808,6 +813,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
push_messaging_manager_;
std::unique_ptr<EmbeddedFrameSinkProviderImpl> embedded_frame_sink_provider_;
+ std::unique_ptr<PluginRegistryImpl, BrowserThread::DeleteOnIOThread>
+ plugin_registry_;
mojom::ChildControlPtr child_control_interface_;
mojom::RouteProviderAssociatedPtr remote_route_provider_;
diff --git a/chromium/content/browser/renderer_host/render_process_host_unittest.cc b/chromium/content/browser/renderer_host/render_process_host_unittest.cc
index 1ed8e6caccc..b036f1a9a31 100644
--- a/chromium/content/browser/renderer_host/render_process_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_unittest.cc
@@ -11,7 +11,7 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "content/common/frame_messages.h"
#include "content/common/frame_owner_properties.h"
@@ -57,9 +57,6 @@ TEST_F(RenderProcessHostUnitTest, RendererProcessLimit) {
if (AreAllSitesIsolatedForTesting())
return;
- // Disable any overrides.
- RenderProcessHostImpl::SetMaxRendererProcessCount(0);
-
// Verify that the limit is between 1 and kMaxRendererProcessCount.
EXPECT_GT(RenderProcessHostImpl::GetMaxRendererProcessCount(), 0u);
EXPECT_LE(RenderProcessHostImpl::GetMaxRendererProcessCount(),
@@ -81,9 +78,6 @@ TEST_F(RenderProcessHostUnitTest, RendererProcessLimit) {
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
TEST_F(RenderProcessHostUnitTest, NoRendererProcessLimitOnAndroidOrChromeOS) {
- // Disable any overrides.
- RenderProcessHostImpl::SetMaxRendererProcessCount(0);
-
// Add a few dummy process hosts.
ASSERT_NE(0u, kMaxRendererProcessCount);
std::vector<std::unique_ptr<MockRenderProcessHost>> hosts;
@@ -888,9 +882,35 @@ TEST_F(RenderProcessHostUnitTest,
SetBrowserClientForTesting(regular_client);
}
+// Check whether we notify the renderer that it has been locked to a site or
+// not. This should depend on the URL from the SiteInstance.
+TEST_F(RenderProcessHostUnitTest, RendererLockedToSite) {
+ struct TestData {
+ GURL test_url;
+ bool should_lock_renderer;
+ } tests[] = {{GURL("http://"), false},
+ {GURL("http://foo.com"), true},
+ {GURL("http://bar.foo.com"), true},
+ {GURL(""), false},
+ {GURL("google.com"), false},
+ {GURL("http:"), false},
+ {GURL("http://user:pass@google.com:99/foo;bar?q=a#ref"), true}};
+ for (const auto& test : tests) {
+ scoped_refptr<SiteInstanceImpl> site_instance =
+ SiteInstanceImpl::CreateForURL(browser_context(), test.test_url);
+ auto* host =
+ static_cast<MockRenderProcessHost*>(site_instance->GetProcess());
+ if (AreAllSitesIsolatedForTesting())
+ EXPECT_EQ(test.should_lock_renderer, host->is_renderer_locked_to_site());
+ else
+ EXPECT_EQ(false, host->is_renderer_locked_to_site());
+ }
+}
+
class SpareRenderProcessHostUnitTest : public RenderViewHostImplTestHarness {
public:
SpareRenderProcessHostUnitTest() {}
+ ~SpareRenderProcessHostUnitTest() override = default;
protected:
void SetUp() override {
@@ -903,6 +923,13 @@ class SpareRenderProcessHostUnitTest : public RenderViewHostImplTestHarness {
}
}
+ void TearDown() override {
+ // Important: Reset the max renderer count to leave this process in a
+ // pristine state.
+ RenderProcessHost::SetMaxRendererProcessCount(0);
+ RenderViewHostImplTestHarness::TearDown();
+ }
+
MockRenderProcessHostFactory rph_factory_;
private:
@@ -1056,7 +1083,9 @@ TEST_F(SpareRenderProcessHostUnitTest,
// in this scenario would put us over the process limit and is therefore
// undesirable.
TEST_F(SpareRenderProcessHostUnitTest, JustBelowProcessLimit) {
- RenderProcessHostImpl::SetMaxRendererProcessCount(1);
+ // Override a global. TearDown() will call SetMaxRendererProcessCount() again
+ // to clean up.
+ RenderProcessHost::SetMaxRendererProcessCount(1);
// No spare or any other renderer process at the start of the test.
EXPECT_FALSE(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
@@ -1078,7 +1107,9 @@ TEST_F(SpareRenderProcessHostUnitTest, JustBelowProcessLimit) {
// This unit test verifies that a mismatched spare RenderProcessHost is dropped
// before considering process reuse due to the process limit.
TEST_F(SpareRenderProcessHostUnitTest, AtProcessLimit) {
- RenderProcessHostImpl::SetMaxRendererProcessCount(2);
+ // Override a global. TearDown() will call SetMaxRendererProcessCount() again
+ // to clean up.
+ RenderProcessHost::SetMaxRendererProcessCount(2);
// Create and navigate the 1st WebContents.
const GURL kUrl1("http://foo.com");
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate.cc b/chromium/content/browser/renderer_host/render_view_host_delegate.cc
index 6ceb1543e01..8aa0ca33809 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.cc
@@ -37,10 +37,6 @@ FrameTree* RenderViewHostDelegate::GetFrameTree() {
return nullptr;
}
-double RenderViewHostDelegate::GetPendingPageZoomLevel() {
- return 0.0;
-}
-
bool RenderViewHostDelegate::IsNeverVisible() {
return false;
}
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate.h b/chromium/content/browser/renderer_host/render_view_host_delegate.h
index cec02574757..f2d59fbd1f4 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.h
@@ -94,7 +94,7 @@ class CONTENT_EXPORT RenderViewHostDelegate {
virtual void Close(RenderViewHost* render_view_host) {}
// The page is trying to move the RenderView's representation in the client.
- virtual void RequestMove(const gfx::Rect& new_bounds) {}
+ virtual void RequestSetBounds(const gfx::Rect& new_bounds) {}
// The RenderView's main frame document element is ready. This happens when
// the document has finished parsing.
@@ -155,11 +155,6 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// to this view.
virtual SessionStorageNamespaceMap GetSessionStorageNamespaceMap();
- // Returns the zoom level for the pending navigation for the page. If there
- // is no pending navigation, this returns the zoom level for the current
- // page.
- virtual double GetPendingPageZoomLevel();
-
// Returns true if the RenderViewHost will never be visible.
virtual bool IsNeverVisible();
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 7dc57079eb4..a7532fa393c 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.cc
@@ -26,6 +26,7 @@ RenderViewHost* RenderViewHostFactory::Create(
RenderWidgetHostDelegate* widget_delegate,
int32_t routing_id,
int32_t main_frame_routing_id,
+ int32_t widget_routing_id,
bool swapped_out,
bool hidden) {
// RenderViewHost creation can be either browser-driven (by the user opening a
@@ -34,7 +35,9 @@ RenderViewHost* RenderViewHostFactory::Create(
// In the browser-driven case, the routing ID of the view is lazily assigned:
// this is signified by passing MSG_ROUTING_NONE for |routing_id|.
if (routing_id == MSG_ROUTING_NONE) {
+ DCHECK_EQ(widget_routing_id, MSG_ROUTING_NONE);
routing_id = instance->GetProcess()->GetNextRoutingID();
+ widget_routing_id = instance->GetProcess()->GetNextRoutingID();
} else {
// Otherwise, in the renderer-driven case, the routing ID of the view is
// already set. This is due to the fact that a sync render->browser IPC is
@@ -46,14 +49,14 @@ RenderViewHost* RenderViewHostFactory::Create(
if (factory_) {
return factory_->CreateRenderViewHost(instance, delegate, widget_delegate,
routing_id, main_frame_routing_id,
- swapped_out);
+ widget_routing_id, swapped_out);
}
return new RenderViewHostImpl(
instance,
base::WrapUnique(RenderWidgetHostFactory::Create(
- widget_delegate, instance->GetProcess(), routing_id, nullptr,
+ widget_delegate, instance->GetProcess(), widget_routing_id, nullptr,
hidden)),
- delegate, main_frame_routing_id, swapped_out,
+ delegate, routing_id, main_frame_routing_id, swapped_out,
true /* has_initialized_audio_host */);
}
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 51babd49079..6987d4e84e0 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.h
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.h
@@ -29,6 +29,7 @@ class RenderViewHostFactory {
RenderWidgetHostDelegate* widget_delegate,
int32_t routing_id,
int32_t main_frame_routing_id,
+ int32_t widget_routing_id,
bool swapped_out,
bool hidden);
@@ -61,6 +62,7 @@ class RenderViewHostFactory {
RenderWidgetHostDelegate* widget_delegate,
int32_t routing_id,
int32_t main_frame_routing_id,
+ int32_t widget_routing_id,
bool swapped_out) = 0;
// Registers your factory to be called when new RenderViewHosts are created.
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 e8aa2e41e8a..1f491537c8f 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -112,6 +112,12 @@ using blink::WebPluginAction;
namespace content {
namespace {
+// <process id, routing id>
+using RenderViewHostID = std::pair<int32_t, int32_t>;
+using RoutingIDViewMap = base::hash_map<RenderViewHostID, RenderViewHostImpl*>;
+base::LazyInstance<RoutingIDViewMap>::Leaky g_routing_id_view_map =
+ LAZY_INSTANCE_INITIALIZER;
+
void GetPlatformSpecificPrefs(RendererPreferences* prefs) {
#if defined(OS_WIN)
NONCLIENTMETRICS_XP metrics = {0};
@@ -173,13 +179,12 @@ RenderViewHost* RenderViewHost::From(RenderWidgetHost* rwh) {
// RenderViewHostImpl, public:
// static
-RenderViewHostImpl* RenderViewHostImpl::FromID(int render_process_id,
- int render_view_id) {
- RenderWidgetHost* widget =
- RenderWidgetHost::FromID(render_process_id, render_view_id);
- if (!widget)
- return nullptr;
- return From(widget);
+RenderViewHostImpl* RenderViewHostImpl::FromID(int process_id, int routing_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RoutingIDViewMap* views = g_routing_id_view_map.Pointer();
+ RoutingIDViewMap::iterator it =
+ views->find(RenderViewHostID(process_id, routing_id));
+ return it == views->end() ? nullptr : it->second;
}
// static
@@ -198,6 +203,7 @@ RenderViewHostImpl::RenderViewHostImpl(
SiteInstance* instance,
std::unique_ptr<RenderWidgetHostImpl> widget,
RenderViewHostDelegate* delegate,
+ int32_t routing_id,
int32_t main_frame_routing_id,
bool swapped_out,
bool has_initialized_audio_host)
@@ -207,6 +213,7 @@ RenderViewHostImpl::RenderViewHostImpl(
instance_(static_cast<SiteInstanceImpl*>(instance)),
is_active_(!swapped_out),
is_swapped_out_(swapped_out),
+ routing_id_(routing_id),
main_frame_routing_id_(main_frame_routing_id),
is_waiting_for_close_ack_(false),
sudden_termination_allowed_(false),
@@ -216,6 +223,13 @@ RenderViewHostImpl::RenderViewHostImpl(
weak_factory_(this) {
DCHECK(instance_.get());
CHECK(delegate_); // http://crbug.com/82827
+ DCHECK_NE(GetRoutingID(), render_widget_host_->GetRoutingID());
+
+ std::pair<RoutingIDViewMap::iterator, bool> result =
+ g_routing_id_view_map.Get().emplace(
+ RenderViewHostID(GetProcess()->GetID(), routing_id_), this);
+ CHECK(result.second) << "Inserting a duplicate item!";
+ GetProcess()->AddRoute(routing_id_, this);
GetWidget()->set_owner_delegate(this);
@@ -255,6 +269,12 @@ RenderViewHostImpl::~RenderViewHostImpl() {
base::Unretained(ResourceDispatcherHostImpl::Get()),
GetProcess()->GetID(), GetRoutingID()));
}
+
+ // Detach the routing ID as the object is going away.
+ GetProcess()->RemoveRoute(GetRoutingID());
+ g_routing_id_view_map.Get().erase(
+ RenderViewHostID(GetProcess()->GetID(), GetRoutingID()));
+
delegate_->RenderViewDeleted(this);
GetProcess()->RemoveObserver(this);
}
@@ -283,7 +303,7 @@ bool RenderViewHostImpl::CreateRenderView(
// ignored, so this is safe.
if (!GetProcess()->Init())
return false;
- DCHECK(GetProcess()->HasConnection());
+ DCHECK(GetProcess()->IsInitializedAndNotDead());
DCHECK(GetProcess()->GetBrowserContext());
CHECK(main_frame_routing_id_ != MSG_ROUTING_NONE ||
proxy_route_id != MSG_ROUTING_NONE);
@@ -314,6 +334,7 @@ bool RenderViewHostImpl::CreateRenderView(
params->web_preferences = GetWebkitPreferences();
params->view_id = GetRoutingID();
params->main_frame_routing_id = main_frame_routing_id_;
+ params->main_frame_widget_routing_id = render_widget_host_->GetRoutingID();
if (main_rfh) {
main_rfh->BindInterfaceProviderRequest(
mojo::MakeRequest(&params->main_frame_interface_provider));
@@ -335,7 +356,6 @@ bool RenderViewHostImpl::CreateRenderView(
params->has_committed_real_load =
main_rfh->frame_tree_node()->has_committed_real_load();
}
- params->page_zoom_level = delegate_->GetPendingPageZoomLevel();
params->devtools_main_frame_token = devtools_frame_token;
// GuestViews in the same StoragePartition need to find each other's frames.
params->renderer_wide_named_frame_lookup =
@@ -368,7 +388,8 @@ void RenderViewHostImpl::SetIsActive(bool is_active) {
}
bool RenderViewHostImpl::IsRenderViewLive() const {
- return GetProcess()->HasConnection() && GetWidget()->renderer_initialized();
+ return GetProcess()->IsInitializedAndNotDead() &&
+ GetWidget()->renderer_initialized();
}
void RenderViewHostImpl::SyncRendererPrefs() {
@@ -558,9 +579,6 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
prefs.background_video_track_optimization_enabled =
base::FeatureList::IsEnabled(media::kBackgroundVideoTrackOptimization);
- prefs.picture_in_picture_enabled =
- base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo);
-
GetContentClient()->browser()->OverrideWebkitPrefs(this, &prefs);
return prefs;
}
@@ -644,7 +662,7 @@ RenderProcessHost* RenderViewHostImpl::GetProcess() const {
}
int RenderViewHostImpl::GetRoutingID() const {
- return GetWidget()->GetRoutingID();
+ return routing_id_;
}
RenderFrameHost* RenderViewHostImpl::GetMainFrame() {
@@ -758,7 +776,7 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
OnShowFullscreenWidget)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTargetURL, OnUpdateTargetURL)
IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
- IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RequestSetBounds, OnRequestSetBounds)
IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentAvailableInMainFrame,
OnDocumentAvailableInMainFrame)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange,
@@ -781,7 +799,7 @@ void RenderViewHostImpl::RenderWidgetDidInit() {
void RenderViewHostImpl::ShutdownAndDestroy() {
// We can't release the SessionStorageNamespace until our peer
// in the renderer has wound down.
- if (GetProcess()->HasConnection()) {
+ if (GetProcess()->IsInitializedAndNotDead()) {
RenderProcessHostImpl::ReleaseOnCloseACK(
GetProcess(),
delegate_->GetSessionStorageNamespaceMap(),
@@ -808,12 +826,12 @@ void RenderViewHostImpl::CreateNewFullscreenWidget(int32_t route_id,
void RenderViewHostImpl::OnShowWidget(int route_id,
const gfx::Rect& initial_rect) {
delegate_->ShowCreatedWidget(GetProcess()->GetID(), route_id, initial_rect);
- Send(new ViewMsg_Move_ACK(route_id));
+ Send(new ViewMsg_SetBounds_ACK(route_id));
}
void RenderViewHostImpl::OnShowFullscreenWidget(int route_id) {
delegate_->ShowCreatedFullscreenWidget(GetProcess()->GetID(), route_id);
- Send(new ViewMsg_Move_ACK(route_id));
+ Send(new ViewMsg_SetBounds_ACK(route_id));
}
void RenderViewHostImpl::OnRenderProcessGone(int status, int exit_code) {
@@ -837,10 +855,10 @@ void RenderViewHostImpl::OnClose() {
ClosePageIgnoringUnloadEvents();
}
-void RenderViewHostImpl::OnRequestMove(const gfx::Rect& pos) {
+void RenderViewHostImpl::OnRequestSetBounds(const gfx::Rect& bounds) {
if (is_active_)
- delegate_->RequestMove(pos);
- Send(new ViewMsg_Move_ACK(GetRoutingID()));
+ delegate_->RequestSetBounds(bounds);
+ Send(new ViewMsg_SetBounds_ACK(GetRoutingID()));
}
void RenderViewHostImpl::OnDocumentAvailableInMainFrame(
@@ -907,6 +925,11 @@ bool RenderViewHostImpl::ShouldContributePriorityToProcess() {
return is_active_;
}
+void RenderViewHostImpl::RenderWidgetDidShutdown() {
+ bool rv = Send(new ViewMsg_Close(GetRoutingID()));
+ DCHECK(rv);
+}
+
WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
if (!web_preferences_.get()) {
OnWebkitPreferencesChanged();
@@ -941,13 +964,6 @@ void RenderViewHostImpl::EnablePreferredSizeMode() {
Send(new ViewMsg_EnablePreferredSizeChangedMode(GetRoutingID()));
}
-void RenderViewHostImpl::ExecuteMediaPlayerActionAtLocation(
- const gfx::Point& location, const blink::WebMediaPlayerAction& action) {
- // TODO(wjmaclean): See if coordinate transforms need to be done for OOPIFs
- // and guest views. https://crbug.com/776807
- Send(new ViewMsg_MediaPlayerActionAt(GetRoutingID(), location, action));
-}
-
void RenderViewHostImpl::ExecutePluginActionAtLocation(
const gfx::Point& location, const blink::WebPluginAction& action) {
// TODO(wjmaclean): See if this needs to be done for OOPIFs as well.
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 f80c4c4330b..af7f7b0d580 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -63,10 +63,11 @@ class TimeoutMonitor;
// https://www.chromium.org/developers/design-documents/site-isolation.
class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
public RenderWidgetHostOwnerDelegate,
- public RenderProcessHostObserver {
+ public RenderProcessHostObserver,
+ public IPC::Listener {
public:
// Convenience function, just like RenderViewHost::FromID.
- static RenderViewHostImpl* FromID(int render_process_id, int render_view_id);
+ static RenderViewHostImpl* FromID(int process_id, int routing_id);
// Convenience function, just like RenderViewHost::From.
static RenderViewHostImpl* From(RenderWidgetHost* rwh);
@@ -74,9 +75,12 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
RenderViewHostImpl(SiteInstance* instance,
std::unique_ptr<RenderWidgetHostImpl> widget,
RenderViewHostDelegate* delegate,
+ int32_t routing_id,
int32_t main_frame_routing_id,
bool swapped_out,
bool has_initialized_audio_host);
+ // TODO(ajwong): Make destructor private. Deletion of this object should only
+ // be done via ShutdownAndDestroy(). https://crbug.com/545684
~RenderViewHostImpl() override;
// Shuts down this RenderViewHost and deletes it.
@@ -93,9 +97,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
const std::vector<base::FilePath>& files) override;
void DisableScrollbarsForThreshold(const gfx::Size& size) override;
void EnablePreferredSizeMode() override;
- void ExecuteMediaPlayerActionAtLocation(
- const gfx::Point& location,
- const blink::WebMediaPlayerAction& action) override;
void ExecutePluginActionAtLocation(
const gfx::Point& location,
const blink::WebPluginAction& action) override;
@@ -238,6 +239,7 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
bool MayRenderWidgetForwardKeyboardEvent(
const NativeWebKeyboardEvent& key_event) override;
bool ShouldContributePriorityToProcess() override;
+ void RenderWidgetDidShutdown() override;
// IPC message handlers.
void OnShowView(int route_id,
@@ -249,7 +251,7 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
void OnRenderProcessGone(int status, int error_code);
void OnUpdateTargetURL(const GURL& url);
void OnClose();
- void OnRequestMove(const gfx::Rect& pos);
+ void OnRequestSetBounds(const gfx::Rect& bounds);
void OnDocumentAvailableInMainFrame(bool uses_temporary_zoom_level);
void OnDidContentsPreferredSizeChange(const gfx::Size& new_size);
void OnPasteFromSelectionClipboard();
@@ -315,6 +317,9 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// See https://crbug.com/745091.
bool is_swapped_out_;
+ // Routing ID for this RenderViewHost.
+ const int routing_id_;
+
// Routing ID for the main frame's RenderFrameHost.
int main_frame_routing_id_;
diff --git a/chromium/content/browser/renderer_host/render_view_host_unittest.cc b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
index 5a0fe447e12..9eaeefd55b4 100644
--- a/chromium/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
@@ -288,6 +288,7 @@ class TestSaveImageFromDataURL : public RenderFrameMessageFilter {
const url::Origin& initiator,
const base::string16& suggested_name,
const bool use_prompt,
+ const bool follow_cross_origin_redirects,
blink::mojom::BlobURLTokenPtrInfo blob_url_token) const override {
url_string_ = url.spec();
is_downloaded_ = true;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
index 2b5a683eb0c..373ecd28b14 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -15,6 +15,8 @@
#include "components/viz/common/quads/render_pass.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "content/browser/bad_message.h"
+#include "content/browser/renderer_host/input/input_router_impl.h"
+#include "content/browser/renderer_host/input/touch_action_filter.h"
#include "content/browser/renderer_host/input/touch_emulator.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
@@ -22,10 +24,13 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_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 "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_mouse_event.h"
@@ -37,7 +42,31 @@
namespace content {
-class RenderWidgetHostBrowserTest : public ContentBrowserTest {};
+class RenderWidgetHostBrowserTest : public ContentBrowserTest {
+ protected:
+ WebContentsImpl* web_contents() const {
+ return static_cast<WebContentsImpl*>(shell()->web_contents());
+ }
+
+ TouchActionFilter* GetTouchActionFilterForWidget(RenderWidgetHostImpl* rwhi) {
+ return &static_cast<InputRouterImpl*>(rwhi->input_router())
+ ->touch_action_filter_;
+ }
+};
+
+// The --site-per-porcess version of RenderWidgetHostBrowserTest.
+class RenderWidgetHostSitePerProcessTest : public RenderWidgetHostBrowserTest {
+ public:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ IsolateAllSitesForTesting(command_line);
+ }
+
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+};
IN_PROC_BROWSER_TEST_F(RenderWidgetHostBrowserTest,
ProhibitsCopyRequestsFromRenderer) {
@@ -370,4 +399,55 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostTouchEmulatorBrowserTest,
host()->RemoveInputEventObserver(&observer);
}
+// Observes the WebContents until a frame finishes loading the contents of a
+// given GURL.
+class DocumentLoadObserver : WebContentsObserver {
+ public:
+ DocumentLoadObserver(WebContents* contents, const GURL& url)
+ : WebContentsObserver(contents), document_origin_(url) {}
+
+ void Wait() {
+ if (loaded_)
+ return;
+ run_loop_.reset(new base::RunLoop());
+ run_loop_->Run();
+ }
+
+ private:
+ void DidFinishLoad(RenderFrameHost* rfh, const GURL& url) override {
+ loaded_ |= (url == document_origin_);
+ if (loaded_ && run_loop_)
+ run_loop_->Quit();
+ }
+
+ bool loaded_ = false;
+ const GURL document_origin_;
+ std::unique_ptr<base::RunLoop> run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(DocumentLoadObserver);
+};
+
+// This test verifies that when a cross-process child frame loads, the initial
+// updates for touch event handlers are sent from the renderer.
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostSitePerProcessTest,
+ OnHasTouchEventHandlers) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ GURL::Replacements replacement;
+ replacement.SetHostStr("b.com");
+ replacement.SetQueryStr("b()");
+ GURL target_child_url = main_url.ReplaceComponents(replacement);
+ DocumentLoadObserver child_frame_observer(shell()->web_contents(),
+ target_child_url);
+ NavigateToURL(shell(), main_url);
+ child_frame_observer.Wait();
+ auto* filter = GetTouchActionFilterForWidget(web_contents()
+ ->GetFrameTree()
+ ->root()
+ ->child_at(0)
+ ->current_frame_host()
+ ->GetRenderWidgetHost());
+ EXPECT_TRUE(filter->allowed_touch_action().has_value());
+}
+
} // namespace content
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 b41e5f828d2..00c3a8c727d 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -27,6 +27,10 @@ bool RenderWidgetHostDelegate::PreHandleGestureEvent(
return false;
}
+double RenderWidgetHostDelegate::GetPendingPageZoomLevel() const {
+ return 0.0;
+}
+
BrowserAccessibilityManager*
RenderWidgetHostDelegate::GetRootBrowserAccessibilityManager() {
return nullptr;
@@ -114,9 +118,10 @@ bool RenderWidgetHostDelegate::AddDomainInfoToRapporSample(
return false;
}
-void RenderWidgetHostDelegate::UpdateUrlForUkmSource(
- ukm::UkmRecorder* service,
- ukm::SourceId ukm_source_id) {}
+ukm::SourceId RenderWidgetHostDelegate::GetUkmSourceIdForLastCommittedSource()
+ const {
+ return ukm::kInvalidSourceId;
+}
gfx::Size RenderWidgetHostDelegate::GetAutoResizeSize() {
return gfx::Size();
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 f8a97cb4381..b054514ea74 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
@@ -10,6 +10,7 @@
#include <string>
#include <vector>
+#include "base/callback.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/common/drag_event_source_info.h"
@@ -19,6 +20,7 @@
#include "third_party/blink/public/platform/web_drag_operation.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/range/range.h"
namespace blink {
class WebMouseWheelEvent;
@@ -34,10 +36,6 @@ namespace rappor {
class Sample;
}
-namespace ukm {
-class UkmRecorder;
-}
-
namespace content {
class BrowserAccessibilityManager;
@@ -66,6 +64,12 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// The RenderWidgetHost got the focus.
virtual void RenderWidgetGotFocus(RenderWidgetHostImpl* render_widget_host) {}
+ // If a main frame navigation is in progress, this will return the zoom level
+ // for the pending page. Otherwise, this returns the zoom level for the
+ // current page. Note that subframe navigations do not affect the zoom level,
+ // which is tracked at the level of the page.
+ virtual double GetPendingPageZoomLevel() const;
+
// The RenderWidgetHost lost the focus.
virtual void RenderWidgetLostFocus(
RenderWidgetHostImpl* render_widget_host) {}
@@ -132,6 +136,11 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// currently focused frame.
virtual void SelectRange(const gfx::Point& base, const gfx::Point& extent) {}
+#if defined(OS_MACOSX)
+ virtual void DidChangeTextSelection(const base::string16& text,
+ const gfx::Range& range) {}
+#endif
+
// Request the renderer to Move the caret to the new position.
virtual void MoveCaret(const gfx::Point& extent) {}
@@ -155,7 +164,10 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// Notification that the renderer has become unresponsive. The
// delegate can use this notification to show a warning to the user.
- virtual void RendererUnresponsive(RenderWidgetHostImpl* render_widget_host) {}
+ // See also WebContentsDelegate::RendererUnresponsive.
+ virtual void RendererUnresponsive(
+ RenderWidgetHostImpl* render_widget_host,
+ base::RepeatingClosure hang_monitor_restarter) {}
// Notification that a previously unresponsive renderer has become
// responsive again. The delegate can use this notification to end the
@@ -258,10 +270,9 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// if the eTLD+1 is not known for |render_widget_host|.
virtual bool AddDomainInfoToRapporSample(rappor::Sample* sample);
- // Update UkmRecorder for the given source with the URL. This is used for
- // URL-keyed metrics to set the url for a report.
- virtual void UpdateUrlForUkmSource(ukm::UkmRecorder* service,
- ukm::SourceId ukm_source_id);
+ // Get the UKM source ID for current content. This is used for providing
+ // data about the content to the URL-keyed metrics service.
+ virtual ukm::SourceId GetUkmSourceIdForLastCommittedSource() const;
// Notifies the delegate that a focused editable element has been touched
// inside this RenderWidgetHost. If |editable| is true then the focused
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 213f32e0891..9ab96c3f933 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -115,6 +115,7 @@
#include "ui/snapshot/snapshot.h"
#if defined(OS_ANDROID)
+#include "content/browser/renderer_host/input/fling_scheduler_android.h"
#include "ui/android/view_android.h"
#endif
@@ -382,8 +383,9 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
base::checked_cast<uint32_t>(routing_id_)),
weak_factory_(this) {
#if defined(OS_MACOSX)
- auto fling_scheduler = std::make_unique<FlingSchedulerMac>(this);
- fling_scheduler_ = std::move(fling_scheduler);
+ fling_scheduler_ = std::make_unique<FlingSchedulerMac>(this);
+#elif defined(OS_ANDROID)
+ fling_scheduler_ = std::make_unique<FlingSchedulerAndroid>(this);
#else
fling_scheduler_ = std::make_unique<FlingScheduler>(this);
#endif
@@ -399,14 +401,12 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
process_->AddRoute(routing_id_, this);
process_->AddWidget(this);
- latency_tracker_.Initialize(routing_id_, GetProcess()->GetID());
-
SetupInputRouter();
SetWidget(std::move(widget));
const auto* command_line = base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(switches::kDisableHangMonitor)) {
- hang_monitor_timeout_.reset(new TimeoutMonitor(
+ input_event_ack_timeout_.reset(new TimeoutMonitor(
base::Bind(&RenderWidgetHostImpl::RendererIsUnresponsive,
weak_factory_.GetWeakPtr())));
}
@@ -420,6 +420,17 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
enable_surface_synchronization_ = features::IsSurfaceSynchronizationEnabled();
enable_viz_ = base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
+ if (!enable_viz_) {
+#if !defined(OS_ANDROID)
+ // Software compositing is not supported or used on Android.
+ //
+ // The BrowserMainLoop is null in unit tests, but they do not use
+ // compositing and report SharedBitmapIds.
+ if (BrowserMainLoop* main_loop = BrowserMainLoop::GetInstance())
+ shared_bitmap_manager_ = main_loop->GetServerSharedBitmapManager();
+#endif
+ }
+
delegate_->RenderWidgetCreated(this);
render_frame_metadata_provider_.AddObserver(this);
}
@@ -565,7 +576,7 @@ void RenderWidgetHostImpl::UpdatePriority() {
}
void RenderWidgetHostImpl::Init() {
- DCHECK(process_->HasConnection());
+ DCHECK(process_->IsInitializedAndNotDead());
renderer_initialized_ = true;
@@ -580,7 +591,7 @@ void RenderWidgetHostImpl::Init() {
}
void RenderWidgetHostImpl::InitForFrame() {
- DCHECK(process_->HasConnection());
+ DCHECK(process_->IsInitializedAndNotDead());
renderer_initialized_ = true;
if (view_)
@@ -591,10 +602,42 @@ void RenderWidgetHostImpl::ShutdownAndDestroyWidget(bool also_delete) {
CancelKeyboardLock();
RejectMouseLockOrUnlockIfNecessary();
- if (process_->HasConnection()) {
- // Tell the renderer object to close.
- bool rv = Send(new ViewMsg_Close(routing_id_));
- DCHECK(rv);
+ if (process_->IsInitializedAndNotDead()) {
+ // This logic below simulates the routing behavior from when RenderWidget
+ // associated with RenderViews shared the same routing IDs.
+ //
+ // In the original code, the sharing of the routing ID yielded a bastardized
+ // version of dynamic dispatch wherein the ultimate static code path that
+ // handled a ViewMsg_Close changed based on if
+ //
+ // (a) the RenderWidgetImpl was also a RenderViewImpl
+ // (b) the RenderViewImpl hooked the message in OnMessageReceived
+ //
+ // In the current code, if RenderWidgetImpl IS NOT a RenderViewImpl,
+ // RenderWidgetHost WILL NOT have a |owner_delegate_| and the message can
+ // be dispatched directly. This is the simplest case.
+ //
+ // If RenderWidgetImpl IS is a RenderViewImpl, then on some platforms
+ // (seems like only Mac?) RenderViewImpl overrides ViewMsg::OnClose to do
+ // additional processing before passing it up to RenderWidgetImpl::OnClose.
+ //
+ // When it is not overridden, the message delegated up via
+ // IPC_MESSAGE_UNHANDLED to the RenderWidget's message dispatching.
+ //
+ // Basically, there are 2 overlapping hand-written implementations of
+ // dynamic dispatch occuring: one via IPC_MESSAGE_UNHANDLED, and another
+ // via calling the super-class method.
+ //
+ // TODO(ajwong): Once the routing_id split CL lands, remove one of these
+ // implementaions of hand-written dyanmic dispatch. The world does not
+ // need so many implementations of what's effectively "virtual."
+ if (owner_delegate_) {
+ owner_delegate_->RenderWidgetDidShutdown();
+ } else {
+ // Tell the non-view RendererWidget to close.
+ bool rv = Send(new ViewMsg_Close(routing_id_));
+ DCHECK(rv);
+ }
}
Destroy(also_delete);
@@ -619,7 +662,7 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateScreenRects_ACK,
OnUpdateScreenRectsAck)
- IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RequestSetBounds, OnRequestSetBounds)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnSetTooltipText)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
IPC_MESSAGE_HANDLER(ViewHostMsg_AutoscrollStart, OnAutoscrollStart)
@@ -636,6 +679,7 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ForceRedrawComplete, OnForceRedrawComplete)
IPC_MESSAGE_HANDLER(ViewHostMsg_FrameSwapMessages,
OnFrameSwapMessagesReceived)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -678,7 +722,7 @@ void RenderWidgetHostImpl::WasHidden() {
visual_properties_ack_pending_ = false;
// Don't bother reporting hung state when we aren't active.
- StopHangMonitorTimeout();
+ StopInputEventAckTimeout();
// If we have a renderer, then inform it that we are being hidden so it can
// reduce its resource utilization.
@@ -696,7 +740,7 @@ void RenderWidgetHostImpl::WasHidden() {
observer.RenderWidgetHostVisibilityChanged(this, false);
}
-void RenderWidgetHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
+void RenderWidgetHostImpl::WasShown(bool record_presentation_time) {
if (!is_hidden_)
return;
@@ -708,12 +752,14 @@ void RenderWidgetHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
ForceFirstFrameAfterNavigationTimeout();
SendScreenRects();
- RestartHangMonitorTimeoutIfNecessary();
+ RestartInputEventAckTimeoutIfNecessary();
// Always repaint on restore.
bool needs_repainting = true;
needs_repainting_on_restore_ = false;
- Send(new ViewMsg_WasShown(routing_id_, needs_repainting, latency_info));
+ Send(new ViewMsg_WasShown(
+ routing_id_, needs_repainting,
+ record_presentation_time ? base::TimeTicks::Now() : base::TimeTicks()));
process_->UpdateClientPriority(this);
@@ -767,9 +813,11 @@ bool RenderWidgetHostImpl::GetVisualProperties(
visual_properties->is_fullscreen_granted =
delegate_->IsFullscreenForCurrentTab();
visual_properties->display_mode = delegate_->GetDisplayMode(this);
+ visual_properties->zoom_level = delegate_->GetPendingPageZoomLevel();
} else {
visual_properties->is_fullscreen_granted = false;
visual_properties->display_mode = blink::kWebDisplayModeBrowser;
+ visual_properties->zoom_level = 0;
}
visual_properties->auto_resize_enabled = auto_resize_enabled_;
@@ -840,8 +888,12 @@ bool RenderWidgetHostImpl::GetVisualProperties(
old_parent_local_surface_id.embed_token() !=
new_parent_local_surface_id.embed_token();
+ const bool zoom_changed =
+ !old_visual_properties_ ||
+ old_visual_properties_->zoom_level != visual_properties->zoom_level;
+
bool dirty =
- size_changed || parent_local_surface_id_changed ||
+ zoom_changed || size_changed || parent_local_surface_id_changed ||
old_visual_properties_->screen_info != visual_properties->screen_info ||
old_visual_properties_->compositor_viewport_pixel_size !=
visual_properties->compositor_viewport_pixel_size ||
@@ -893,8 +945,8 @@ bool RenderWidgetHostImpl::SynchronizeVisualProperties(
bool scroll_focused_node_into_view) {
// Skip if the |delegate_| has already been detached because
// it's web contents is being deleted.
- if (visual_properties_ack_pending_ || !process_->HasConnection() || !view_ ||
- !view_->HasSize() || !renderer_initialized_ || !delegate_) {
+ if (visual_properties_ack_pending_ || !process_->IsInitializedAndNotDead() ||
+ !view_ || !view_->HasSize() || !renderer_initialized_ || !delegate_) {
return false;
}
@@ -1091,39 +1143,39 @@ bool RenderWidgetHostImpl::RequestRepaintForTesting() {
void RenderWidgetHostImpl::ProcessIgnoreInputEventsChanged(
bool ignore_input_events) {
if (ignore_input_events)
- StopHangMonitorTimeout();
+ StopInputEventAckTimeout();
else
- RestartHangMonitorTimeoutIfNecessary();
+ RestartInputEventAckTimeoutIfNecessary();
}
-void RenderWidgetHostImpl::StartHangMonitorTimeout(TimeDelta delay) {
- if (!hang_monitor_timeout_)
+void RenderWidgetHostImpl::StartInputEventAckTimeout(TimeDelta delay) {
+ if (!input_event_ack_timeout_)
return;
- hang_monitor_timeout_->Start(delay);
- hang_monitor_start_time_ = clock_->NowTicks();
+ input_event_ack_timeout_->Start(delay);
+ input_event_ack_start_time_ = clock_->NowTicks();
}
-void RenderWidgetHostImpl::RestartHangMonitorTimeoutIfNecessary() {
- if (hang_monitor_timeout_ && in_flight_event_count_ > 0 && !is_hidden_)
- hang_monitor_timeout_->Restart(hung_renderer_delay_);
+void RenderWidgetHostImpl::RestartInputEventAckTimeoutIfNecessary() {
+ if (input_event_ack_timeout_ && in_flight_event_count_ > 0 && !is_hidden_)
+ input_event_ack_timeout_->Restart(hung_renderer_delay_);
}
bool RenderWidgetHostImpl::IsCurrentlyUnresponsive() const {
return is_unresponsive_;
}
-void RenderWidgetHostImpl::StopHangMonitorTimeout() {
- if (hang_monitor_timeout_)
- hang_monitor_timeout_->Stop();
+void RenderWidgetHostImpl::StopInputEventAckTimeout() {
+ if (input_event_ack_timeout_)
+ input_event_ack_timeout_->Stop();
- if (!hang_monitor_start_time_.is_null()) {
- base::TimeDelta elapsed = clock_->NowTicks() - hang_monitor_start_time_;
+ if (!input_event_ack_start_time_.is_null()) {
+ base::TimeDelta elapsed = clock_->NowTicks() - input_event_ack_start_time_;
const base::TimeDelta kMinimumHangTimeToReport =
base::TimeDelta::FromSeconds(5);
if (elapsed >= kMinimumHangTimeToReport)
UMA_HISTOGRAM_LONG_TIMES("Renderer.Hung.Duration", elapsed);
- hang_monitor_start_time_ = TimeTicks();
+ input_event_ack_start_time_ = TimeTicks();
}
RendererIsResponsive();
}
@@ -1137,8 +1189,19 @@ void RenderWidgetHostImpl::DidNavigate(uint32_t next_source_id) {
// |visual_properties_ack_pending_| and make sure the next resize will be
// acked if the last resize before navigation was supposed to be acked.
visual_properties_ack_pending_ = false;
+ viz::LocalSurfaceId old_surface_id = view_->GetLocalSurfaceId();
if (view_)
view_->DidNavigate();
+ viz::LocalSurfaceId new_surface_id = view_->GetLocalSurfaceId();
+ // If |view_| didn't allocate a new surface id, then don't start
+ // |new_content_rendering_timeout_|. Two reasons:
+ // 1. It's not needed (because this was the first navigation event)
+ // 2. If we don't change the surface id, then we will not get the call to
+ // OnFirstSurfaceActivation, and not stop the timer (even if we get new
+ // frames).
+ // https://crbug.com/853651, https://crbug.com/535375
+ if (old_surface_id == new_surface_id)
+ return;
} else {
// It is possible for a compositor frame to arrive before the browser is
// notified about the page being committed, in which case no timer is
@@ -1284,9 +1347,8 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
// the GFS are directly injected to RWHI rather than being generated
// from wheel events in MouseWheelEventQueue.
is_in_gesture_scroll_[gesture_event.SourceDevice()] = false;
- } else if (GetView()->wheel_scroll_latching_enabled()) {
- // When wheel scroll latching is enabled, no GSE is sent before GFS, so
- // is_in_gesture_scroll must be true.
+ } else {
+ // No GSE is sent before GFS, so is_in_gesture_scroll must be true.
// TODO(sahel): This often gets tripped on Debug builds in ChromeOS
// indicating some kind of gesture event ordering race.
// https://crbug.com/821237.
@@ -1300,12 +1362,6 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
// and send a wheel event with phaseEnded. MouseWheelEventQueue will
// process the wheel event to generate and send a GSE which shows the
// end of a scroll sequence.
- } else { // !GetView()->IsInVR() &&
- // !GetView()->wheel_scroll_latching_enabled()
-
- // When wheel scroll latching is disabled a GSE is sent before a GFS.
- // The GSE has already finished the scroll sequence.
- DCHECK(!is_in_gesture_scroll_[gesture_event.SourceDevice()]);
}
is_in_touchpad_gesture_fling_ = true;
@@ -1406,7 +1462,7 @@ void RenderWidgetHostImpl::ForwardKeyboardEventWithCommands(
if (ShouldDropInputEvents())
return;
- if (!process_->HasConnection())
+ if (!process_->IsInitializedAndNotDead())
return;
// First, let keypress listeners take a shot at handling the event. If a
@@ -1452,9 +1508,6 @@ void RenderWidgetHostImpl::ForwardKeyboardEventWithCommands(
switch (delegate_->PreHandleKeyboardEvent(key_event)) {
case KeyboardEventProcessingResult::HANDLED:
return;
- case KeyboardEventProcessingResult::HANDLED_WANTS_KEY_UP:
- suppress_events_until_keydown_ = false;
- return;
#if defined(USE_AURA)
case KeyboardEventProcessingResult::HANDLED_DONT_UPDATE_EVENT:
if (update_event)
@@ -1520,10 +1573,6 @@ void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible) {
GetWidgetInputHandler()->CursorVisibilityChanged(is_visible);
}
-int64_t RenderWidgetHostImpl::GetLatencyComponentId() const {
- return latency_tracker_.latency_component_id();
-}
-
// static
void RenderWidgetHostImpl::DisableResizeAckCheckForTesting() {
g_check_for_pending_visual_properties_ack = false;
@@ -1720,12 +1769,11 @@ void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
void RenderWidgetHostImpl::GetSnapshotFromBrowser(
const GetSnapshotFromBrowserCallback& callback,
bool from_surface) {
- int id = next_browser_snapshot_id_++;
+ int snapshot_id = next_browser_snapshot_id_++;
if (from_surface) {
- pending_surface_browser_snapshots_.insert(std::make_pair(id, callback));
- ui::LatencyInfo latency_info;
- latency_info.AddSnapshot(GetLatencyComponentId(), id);
- Send(new ViewMsg_ForceRedraw(GetRoutingID(), latency_info));
+ pending_surface_browser_snapshots_.insert(
+ std::make_pair(snapshot_id, callback));
+ Send(new ViewMsg_ForceRedraw(GetRoutingID(), snapshot_id));
return;
}
@@ -1737,10 +1785,8 @@ void RenderWidgetHostImpl::GetSnapshotFromBrowser(
GetWakeLock()->RequestWakeLock();
#endif
// TODO(nzolghadr): Remove the duplication here and the if block just above.
- pending_browser_snapshots_.insert(std::make_pair(id, callback));
- ui::LatencyInfo latency_info;
- latency_info.AddSnapshot(GetLatencyComponentId(), id);
- Send(new ViewMsg_ForceRedraw(GetRoutingID(), latency_info));
+ pending_browser_snapshots_.insert(std::make_pair(snapshot_id, callback));
+ Send(new ViewMsg_ForceRedraw(GetRoutingID(), snapshot_id));
}
void RenderWidgetHostImpl::SelectionChanged(const base::string16& text,
@@ -1829,6 +1875,23 @@ void RenderWidgetHostImpl::OnFrameSwapMessagesReceived(
std::move(messages));
}
+void RenderWidgetHostImpl::OnForceRedrawComplete(int snapshot_id) {
+#if defined(OS_MACOSX) || defined(OS_WIN)
+ // On Mac, when using CoreAnimation, or Win32 when using GDI, there is a
+ // delay between when content is drawn to the screen, and when the
+ // snapshot will actually pick up that content. Insert a manual delay of
+ // 1/6th of a second (to simulate 10 frames at 60 fps) before actually
+ // taking the snapshot.
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&RenderWidgetHostImpl::WindowSnapshotReachedScreen,
+ weak_factory_.GetWeakPtr(), snapshot_id),
+ TimeDelta::FromSecondsD(1. / 6));
+#else
+ WindowSnapshotReachedScreen(snapshot_id);
+#endif
+}
+
void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
int exit_code) {
if (!renderer_initialized_)
@@ -1866,7 +1929,7 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
// Reset this to ensure the hung renderer mechanism is working properly.
in_flight_event_count_ = 0;
- StopHangMonitorTimeout();
+ StopInputEventAckTimeout();
if (view_) {
view_->RenderProcessGone(status, exit_code);
@@ -1990,8 +2053,15 @@ void RenderWidgetHostImpl::Destroy(bool also_delete) {
// The display compositor has ownership of shared memory for each
// SharedBitmapId that has been reported from the client. Since the client is
// gone that memory can be freed. If we don't then it would leak.
- for (const auto& id : owned_bitmaps_)
- viz::ServerSharedBitmapManager::current()->ChildDeletedSharedBitmap(id);
+ if (shared_bitmap_manager_) {
+ for (const auto& id : owned_bitmaps_)
+ shared_bitmap_manager_->ChildDeletedSharedBitmap(id);
+ } else {
+ // If the display compositor is not in the browser process, then the
+ // |bitmap_manager| is not present in the process either, and no bitmaps
+ // should have been registered with this class.
+ DCHECK(owned_bitmaps_.empty());
+ }
process_->RemoveWidget(this);
process_->RemoveRoute(routing_id_);
@@ -2015,7 +2085,10 @@ void RenderWidgetHostImpl::RendererIsUnresponsive() {
is_unresponsive_ = true;
if (delegate_)
- delegate_->RendererUnresponsive(this);
+ delegate_->RendererUnresponsive(
+ this, base::BindRepeating(
+ &RenderWidgetHostImpl::RestartInputEventAckTimeoutIfNecessary,
+ weak_factory_.GetWeakPtr()));
// Do not add code after this since the Delegate may delete this
// RenderWidgetHostImpl in RendererUnresponsive.
@@ -2035,31 +2108,6 @@ void RenderWidgetHostImpl::ClearDisplayedGraphics() {
view_->ClearCompositorFrame();
}
-void RenderWidgetHostImpl::OnGpuSwapBuffersCompletedInternal(
- const ui::LatencyInfo& latency_info) {
- // Note that a compromised renderer can send LatencyInfo to a
- // RenderWidgetHostImpl other than its own. Be mindful of security
- // implications of the code you add here.
- if (latency_info.Snapshots().find(GetLatencyComponentId()) !=
- latency_info.Snapshots().end()) {
- int snapshot_id = latency_info.Snapshots().at(GetLatencyComponentId());
-#if defined(OS_MACOSX) || defined(OS_WIN)
- // On Mac, when using CoreAnimation, or Win32 when using GDI, there is a
- // delay between when content is drawn to the screen, and when the
- // snapshot will actually pick up that content. Insert a manual delay of
- // 1/6th of a second (to simulate 10 frames at 60 fps) before actually
- // taking the snapshot.
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&RenderWidgetHostImpl::WindowSnapshotReachedScreen,
- weak_factory_.GetWeakPtr(), snapshot_id),
- TimeDelta::FromSecondsD(1. / 6));
-#else
- WindowSnapshotReachedScreen(snapshot_id);
-#endif
- }
-}
-
void RenderWidgetHostImpl::OnRenderProcessGone(int status, int exit_code) {
// RenderFrameHost owns a RenderWidgetHost when it needs one, in which case
// it handles destruction.
@@ -2130,10 +2178,10 @@ void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
SendScreenRects();
}
-void RenderWidgetHostImpl::OnRequestMove(const gfx::Rect& pos) {
+void RenderWidgetHostImpl::OnRequestSetBounds(const gfx::Rect& bounds) {
if (view_) {
- view_->SetBounds(pos);
- Send(new ViewMsg_Move_ACK(routing_id_));
+ view_->SetBounds(bounds);
+ Send(new ViewMsg_SetBounds_ACK(routing_id_));
}
}
@@ -2149,8 +2197,8 @@ void RenderWidgetHostImpl::DidNotProduceFrame(const viz::BeginFrameAck& ack) {
void RenderWidgetHostImpl::DidAllocateSharedBitmap(
mojo::ScopedSharedBufferHandle buffer,
const viz::SharedBitmapId& id) {
- if (!viz::ServerSharedBitmapManager::current()->ChildAllocatedSharedBitmap(
- std::move(buffer), id)) {
+ if (!shared_bitmap_manager_->ChildAllocatedSharedBitmap(std::move(buffer),
+ id)) {
bad_message::ReceivedBadMessage(GetProcess(),
bad_message::RWH_SHARED_BITMAP);
}
@@ -2159,7 +2207,7 @@ void RenderWidgetHostImpl::DidAllocateSharedBitmap(
void RenderWidgetHostImpl::DidDeleteSharedBitmap(
const viz::SharedBitmapId& id) {
- viz::ServerSharedBitmapManager::current()->ChildDeletedSharedBitmap(id);
+ shared_bitmap_manager_->ChildDeletedSharedBitmap(id);
owned_bitmaps_.erase(id);
}
@@ -2432,12 +2480,13 @@ InputEventAckState RenderWidgetHostImpl::FilterInputEvent(
if (ShouldDropInputEvents() && event.GetType() != WebInputEvent::kTouchCancel)
return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
- if (!process_->HasConnection())
+ if (!process_->IsInitializedAndNotDead())
return INPUT_EVENT_ACK_STATE_UNKNOWN;
if (delegate_) {
if (event.GetType() == WebInputEvent::kMouseDown ||
- event.GetType() == WebInputEvent::kTouchStart) {
+ event.GetType() == WebInputEvent::kTouchStart ||
+ event.GetType() == WebInputEvent::kGestureTap) {
delegate_->FocusOwningWebContents(this);
}
delegate_->DidReceiveInputEvent(this, event.GetType());
@@ -2450,7 +2499,7 @@ InputEventAckState RenderWidgetHostImpl::FilterInputEvent(
void RenderWidgetHostImpl::IncrementInFlightEventCount() {
++in_flight_event_count_;
if (!is_hidden_)
- StartHangMonitorTimeout(hung_renderer_delay_);
+ StartInputEventAckTimeout(hung_renderer_delay_);
}
void RenderWidgetHostImpl::DecrementInFlightEventCount(
@@ -2458,12 +2507,12 @@ void RenderWidgetHostImpl::DecrementInFlightEventCount(
--in_flight_event_count_;
if (in_flight_event_count_ <= 0) {
// Cancel pending hung renderer checks since the renderer is responsive.
- StopHangMonitorTimeout();
+ StopInputEventAckTimeout();
} else {
// Only restart the hang monitor timer if we got a response from the
// main thread.
if (ack_source == InputEventAckSource::MAIN_THREAD)
- RestartHangMonitorTimeoutIfNecessary();
+ RestartInputEventAckTimeoutIfNecessary();
}
}
@@ -2727,39 +2776,6 @@ void RenderWidgetHostImpl::OnSnapshotReceived(int snapshot_id,
#endif
}
-// static
-void RenderWidgetHostImpl::NotifyCorrespondingRenderWidgetHost(
- int64_t frame_id,
- std::set<RenderWidgetHostImpl*>& notified_hosts,
- const ui::LatencyInfo& latency_info) {
- // Matches with GetLatencyComponentId.
- int routing_id = frame_id & 0xffffffff;
- int process_id = (frame_id >> 32) & 0xffffffff;
- RenderWidgetHost* rwh = RenderWidgetHost::FromID(process_id, routing_id);
- if (!rwh)
- return;
- RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
- if (notified_hosts.insert(rwhi).second)
- rwhi->OnGpuSwapBuffersCompletedInternal(latency_info);
-}
-
-// static
-void RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info) {
- for (size_t i = 0; i < latency_info.size(); i++) {
- std::set<RenderWidgetHostImpl*> rwhi_set;
- for (const auto& lc : latency_info[i].latency_components()) {
- if (lc.first.first == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT ||
- lc.first.first == ui::TAB_SHOW_COMPONENT)
- NotifyCorrespondingRenderWidgetHost(lc.first.second, rwhi_set,
- latency_info[i]);
- }
- for (const auto& snapshot : latency_info[i].Snapshots())
- NotifyCorrespondingRenderWidgetHost(snapshot.first, rwhi_set,
- latency_info[i]);
- }
-}
-
BrowserAccessibilityManager*
RenderWidgetHostImpl::GetRootBrowserAccessibilityManager() {
return delegate_ ? delegate_->GetRootBrowserAccessibilityManager() : nullptr;
@@ -2815,14 +2831,22 @@ void RenderWidgetHostImpl::RequestCompositorFrameSink(
return;
}
+ // Consider any bitmaps registered with the old CompositorFrameSink as gone,
+ // they will be re-registered on the newly requested CompositorFrameSink if
+ // they are meant to be used still. https://crbug.com/862584.
+ for (const auto& id : owned_bitmaps_)
+ shared_bitmap_manager_->ChildDeletedSharedBitmap(id);
+ owned_bitmaps_.clear();
+
if (compositor_frame_sink_binding_.is_bound())
compositor_frame_sink_binding_.Close();
compositor_frame_sink_binding_.Bind(
std::move(compositor_frame_sink_request),
BrowserMainLoop::GetInstance()->GetResizeTaskRunner());
- if (view_)
+ if (view_) {
view_->DidCreateNewRendererCompositorFrameSink(
compositor_frame_sink_client.get());
+ }
renderer_compositor_frame_sink_ = std::move(compositor_frame_sink_client);
}
@@ -2867,9 +2891,6 @@ void RenderWidgetHostImpl::SubmitCompositorFrame(
viz::CompositorFrame frame,
base::Optional<viz::HitTestRegionList> hit_test_region_list,
uint64_t submit_time) {
- TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"),
- "SubmitCompositorFrame", local_surface_id.hash());
-
// Ensure there are no CopyOutputRequests stowed-away in the CompositorFrame.
// For security/privacy reasons, renderers are not allowed to make copy
// requests because they could use this to gain access to content from another
@@ -2880,23 +2901,11 @@ void RenderWidgetHostImpl::SubmitCompositorFrame(
return;
}
- bool tracing_enabled;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"),
- &tracing_enabled);
- if (tracing_enabled) {
- TimeDelta elapsed = clock_->NowTicks().since_origin() -
- TimeDelta::FromMicroseconds(submit_time);
- TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"),
- "SubmitCompositorFrame::TimeElapsed",
- TRACE_EVENT_SCOPE_THREAD,
- "elapsed time:", elapsed.InMicroseconds());
- }
auto new_surface_properties =
RenderWidgetSurfaceProperties::FromCompositorFrame(frame);
if (local_surface_id == last_local_surface_id_ &&
- SurfacePropertiesMismatch(new_surface_properties,
- last_surface_properties_)) {
+ new_surface_properties != last_surface_properties_) {
std::string error = base::StringPrintf(
"[OOPIF? %d] %s\n", view_ && view_->IsRenderWidgetHostViewChildFrame(),
new_surface_properties.ToDiffString(last_surface_properties_).c_str());
@@ -3014,7 +3023,7 @@ device::mojom::WakeLock* RenderWidgetHostImpl::GetWakeLock() {
void RenderWidgetHostImpl::SetupInputRouter() {
in_flight_event_count_ = 0;
- StopHangMonitorTimeout();
+ StopInputEventAckTimeout();
associated_widget_input_handler_ = nullptr;
widget_input_handler_ = nullptr;
@@ -3105,36 +3114,6 @@ void RenderWidgetHostImpl::SetScreenOrientationForTesting(
SynchronizeVisualProperties();
}
-// TODO(ericrk): On Android, with surface synchronization enabled, we need to
-// request a new surface ID when things like top/bottom control height or
-// selection handles change. This will be enabled by child surface id
-// generation. For now ignore these mismatches. Remove this function when this
-// issue is resolved: https://crbug.com/789259 and https://crbug.com/801350
-bool RenderWidgetHostImpl::SurfacePropertiesMismatch(
- const RenderWidgetSurfaceProperties& first,
- const RenderWidgetSurfaceProperties& second) const {
-#ifdef OS_ANDROID
- if (enable_surface_synchronization_) {
- // To make this comparison resistant to changes in
- // RenderWidgetSurfaceProperties, create new properties which are forced to
- // match only for those categories we want to ignore.
- RenderWidgetSurfaceProperties second_reduced = second;
- second_reduced.top_controls_height = first.top_controls_height;
- second_reduced.top_controls_shown_ratio = first.top_controls_shown_ratio;
- second_reduced.bottom_controls_height = first.bottom_controls_height;
- second_reduced.bottom_controls_shown_ratio =
- first.bottom_controls_shown_ratio;
- second_reduced.selection = first.selection;
-
- return first != second_reduced;
- }
-#endif
-
- // For non-Android or when surface synchronization is not enabled, just use a
- // basic comparison.
- return first != second;
-}
-
bool RenderWidgetHostImpl::LockKeyboard() {
if (!keyboard_lock_allowed_ || !is_focused_ || !view_)
return false;
@@ -3151,7 +3130,10 @@ void RenderWidgetHostImpl::UnlockKeyboard() {
view_->UnlockKeyboard();
}
-void RenderWidgetHostImpl::OnRenderFrameMetadataChanged() {
+void RenderWidgetHostImpl::OnRenderFrameMetadataChangedBeforeActivation(
+ const cc::RenderFrameMetadata& metadata) {}
+
+void RenderWidgetHostImpl::OnRenderFrameMetadataChangedAfterActivation() {
bool is_mobile_optimized =
render_frame_metadata_provider_.LastRenderFrameMetadata()
.is_mobile_optimized;
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 316385180c6..4af5870e7c4 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -11,6 +11,7 @@
#include <list>
#include <map>
#include <memory>
+#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -30,7 +31,7 @@
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "build/build_config.h"
-#include "components/viz/common/quads/shared_bitmap.h"
+#include "components/viz/common/resources/shared_bitmap.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/browser/renderer_host/frame_token_message_queue.h"
@@ -96,10 +97,14 @@ namespace ui {
enum class DomCode;
}
+namespace viz {
+class ServerSharedBitmapManager;
+}
+
namespace content {
class BrowserAccessibilityManager;
-class FlingScheduler;
+class FlingSchedulerBase;
class InputRouter;
class MockRenderWidgetHost;
class RenderWidgetHostOwnerDelegate;
@@ -193,7 +198,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
int GetRoutingID() const override;
RenderWidgetHostViewBase* GetView() const override;
bool IsLoading() const override;
- void RestartHangMonitorTimeoutIfNecessary() override;
bool IsCurrentlyUnresponsive() const override;
void SetIgnoreInputEvents(bool ignore_input_events) override;
bool SynchronizeVisualProperties() override;
@@ -301,7 +305,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// Called to notify the RenderWidget that it has been hidden or restored from
// having been hidden.
void WasHidden();
- void WasShown(const ui::LatencyInfo& latency_info);
+ void WasShown(bool record_presentation_time);
#if defined(OS_ANDROID)
// Set the importance of widget. The importance is passed onto
@@ -526,13 +530,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void DidReceiveRendererFrame();
- // Returns the ID that uniquely describes this component to the latency
- // subsystem.
- int64_t GetLatencyComponentId() const;
-
- static void OnGpuSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info);
-
// Don't check whether we expected a resize ack during layout tests.
static void DisableResizeAckCheckForTesting();
@@ -728,10 +725,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// from a newly loaded page. Used for testing.
virtual void NotifyNewContentRenderingTimeoutForTesting() {}
- // Can be overriden for subclass based testing.
- virtual void OnGpuSwapBuffersCompletedInternal(
- const ui::LatencyInfo& latency_info);
-
// InputAckHandler
void OnKeyboardEventAck(const NativeWebKeyboardEventWithLatencyInfo& event,
InputEventAckSource ack_source,
@@ -763,13 +756,13 @@ class CONTENT_EXPORT RenderWidgetHostImpl
private:
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest,
- DontPostponeHangMonitorTimeout);
+ DontPostponeInputEventAckTimeout);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest, HiddenPaint);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest, RendererExitedNoDrag);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest,
- StopAndStartHangMonitorTimeout);
+ StopAndStartInputEventAckTimeout);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest,
- ShorterDelayHangMonitorTimeout);
+ ShorterDelayInputEventAckTimeout);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest, SynchronizeVisualProperties);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, AutoResizeWithScale);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
@@ -796,17 +789,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl
RenderProcessHost*,
RenderWidgetHost*);
- // Helper for notifying corresponding RenderWidgetHosts
- static void NotifyCorrespondingRenderWidgetHost(
- int64_t frame_id,
- std::set<RenderWidgetHostImpl*>&,
- const ui::LatencyInfo&);
-
// Tell this object to destroy itself. If |also_delete| is specified, the
// destructor is called as well.
void Destroy(bool also_delete);
- // Called by |hang_monitor_timeout_| on delayed response from the renderer.
+ // Called by |input_event_ack_timeout_| on delayed response from the renderer.
void RendererIsUnresponsive();
// Called by |new_content_rendering_timeout_| if a renderer has loaded new
@@ -822,7 +809,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void OnRenderProcessGone(int status, int error_code);
void OnClose();
void OnUpdateScreenRectsAck();
- void OnRequestMove(const gfx::Rect& pos);
+ void OnRequestSetBounds(const gfx::Rect& bounds);
void OnSetTooltipText(const base::string16& tooltip_text,
blink::WebTextDirection text_direction_hint);
void OnSetCursor(const WebCursor& cursor);
@@ -850,6 +837,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void OnUpdateDragCursor(blink::WebDragOperation current_op);
void OnFrameSwapMessagesReceived(uint32_t frame_token,
std::vector<IPC::Message> messages);
+ void OnForceRedrawComplete(int snapshot_id);
// Called when visual properties have changed in the renderer.
void DidUpdateVisualProperties(const cc::RenderFrameMetadata& metadata);
@@ -891,17 +879,18 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// Starts a hang monitor timeout. If there's already a hang monitor timeout
// the new one will only fire if it has a shorter delay than the time
// left on the existing timeouts.
- void StartHangMonitorTimeout(base::TimeDelta delay);
+ void StartInputEventAckTimeout(base::TimeDelta delay);
// Stops all existing hang monitor timeouts and assumes the renderer is
// responsive.
- void StopHangMonitorTimeout();
+ void StopInputEventAckTimeout();
- void SetupInputRouter();
+ // Implementation of |hang_monitor_restarter| callback passed to
+ // RenderWidgetHostDelegate::RendererUnresponsive if the unresponsiveness
+ // was noticed because of input event ack timeout.
+ void RestartInputEventAckTimeoutIfNecessary();
- bool SurfacePropertiesMismatch(
- const RenderWidgetSurfaceProperties& first,
- const RenderWidgetSurfaceProperties& second) const;
+ void SetupInputRouter();
// Start intercepting system keyboard events.
bool LockKeyboard();
@@ -914,7 +903,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl
#endif
// RenderFrameMetadataProvider::Observer implementation.
- void OnRenderFrameMetadataChanged() override;
+ void OnRenderFrameMetadataChangedBeforeActivation(
+ const cc::RenderFrameMetadata& metadata) override;
+ void OnRenderFrameMetadataChangedAfterActivation() override;
void OnRenderFrameSubmission() override {}
void OnLocalSurfaceIdChanged(
const cc::RenderFrameMetadata& metadata) override;
@@ -1072,8 +1063,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// Receives and handles all input events.
std::unique_ptr<InputRouter> input_router_;
- std::unique_ptr<TimeoutMonitor> hang_monitor_timeout_;
- base::TimeTicks hang_monitor_start_time_;
+ std::unique_ptr<TimeoutMonitor> input_event_ack_timeout_;
+ base::TimeTicks input_event_ack_start_time_;
std::unique_ptr<TimeoutMonitor> new_content_rendering_timeout_;
@@ -1174,9 +1165,15 @@ class CONTENT_EXPORT RenderWidgetHostImpl
base::Optional<uint16_t> screen_orientation_angle_for_testing_;
base::Optional<ScreenOrientationValues> screen_orientation_type_for_testing_;
+ // When the viz display compositor is in the browser process, this is used to
+ // register and unregister the bitmaps (stored in |owned_bitmaps_| reported to
+ // this class from the renderer.
+ viz::ServerSharedBitmapManager* shared_bitmap_manager_ = nullptr;
// The set of SharedBitmapIds that have been reported as allocated to this
// interface. On closing this interface, the display compositor should drop
- // ownership of the bitmaps with these ids to avoid leaking them.
+ // ownership of the bitmaps with these ids to avoid leaking them. This is only
+ // used when SharedBitmaps are reported to this class because the display
+ // compositor is in the browser process.
std::set<viz::SharedBitmapId> owned_bitmaps_;
bool force_enable_zoom_ = false;
@@ -1185,7 +1182,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
const viz::FrameSinkId frame_sink_id_;
- std::unique_ptr<FlingScheduler> fling_scheduler_;
+ std::unique_ptr<FlingSchedulerBase> fling_scheduler_;
bool did_receive_first_frame_after_navigation_ = true;
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 1ff58114735..52a1434b1b4 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
@@ -132,35 +132,28 @@ void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed(
first_bubbling_scroll_target_.target = nullptr;
} else if (view == first_bubbling_scroll_target_.target) {
first_bubbling_scroll_target_.target = nullptr;
- // When wheel scroll latching is disabled
- // bubbling_gesture_scroll_target_.target should also get reset since
- // gesture scroll events are bubbled one target at a time and they need the
- // first target for getting bubbled to the current bubbling target. With
- // latching enabled gesture scroll events (other than GSB) are bubbled
- // directly to the bubbling target, the bubbling target should wait for the
- // GSE to arrive and finish scrolling sequence rather than getting reset.
- if (bubbling_gesture_scroll_target_.target &&
- !bubbling_gesture_scroll_target_.target
- ->wheel_scroll_latching_enabled()) {
- bubbling_gesture_scroll_target_.target = nullptr;
- }
}
if (view == last_mouse_move_target_) {
// When a child iframe is destroyed, consider its parent to be to be the
// most recent target, if possible. In some cases the parent might already
// have been destroyed, in which case the last target is cleared.
- if (view != last_mouse_move_root_view_)
+ if (view != last_mouse_move_root_view_) {
+ DCHECK(last_mouse_move_target_->IsRenderWidgetHostViewChildFrame());
last_mouse_move_target_ =
static_cast<RenderWidgetHostViewChildFrame*>(last_mouse_move_target_)
->GetParentView();
- else
+ } else {
last_mouse_move_target_ = nullptr;
+ }
if (!last_mouse_move_target_ || view == last_mouse_move_root_view_)
last_mouse_move_root_view_ = nullptr;
}
+ if (view == last_fling_start_target_)
+ last_fling_start_target_ = nullptr;
+
event_targeter_->ViewWillBeDestroyed(view);
}
@@ -272,7 +265,6 @@ RenderWidgetHostInputEventRouter::FindMouseWheelEventTarget(
return {target, false, transformed_point, true};
}
- if (root_view->wheel_scroll_latching_enabled()) {
if (event.phase == blink::WebMouseWheelEvent::kPhaseBegan) {
auto result = FindViewAtLocation(
root_view, event.PositionInWidget(), event.PositionInScreen(),
@@ -282,7 +274,6 @@ RenderWidgetHostInputEventRouter::FindMouseWheelEventTarget(
// For non-begin events, the target found for the previous phaseBegan is
// used.
return {nullptr, false, base::nullopt, true};
- }
auto result = FindViewAtLocation(root_view, event.PositionInWidget(),
event.PositionInScreen(),
@@ -423,8 +414,7 @@ void RenderWidgetHostInputEventRouter::DispatchMouseWheelEvent(
const ui::LatencyInfo& latency,
const base::Optional<gfx::PointF>& target_location) {
base::Optional<gfx::PointF> point_in_target = target_location;
- if (!root_view->IsMouseLocked() &&
- root_view->wheel_scroll_latching_enabled()) {
+ if (!root_view->IsMouseLocked()) {
if (mouse_wheel_event.phase == blink::WebMouseWheelEvent::kPhaseBegan) {
wheel_target_.target = target;
if (target_location.has_value()) {
@@ -464,16 +454,14 @@ void RenderWidgetHostInputEventRouter::DispatchMouseWheelEvent(
// If target_location doesn't have a value, it can be for two reasons:
// 1. |target| is null, in which case we would have early returned from the
// check above.
- // 2. Wheel scroll latching is enabled and the event we are receiving is not
- // a phaseBegan, in which case we should have got a valid |point_in_target|
- // from wheel_target_.delta above.
+ // 2. The event we are receiving is not a phaseBegan, in which case we should
+ // have got a valid |point_in_target| from wheel_target_.delta above.
DCHECK(point_in_target.has_value());
blink::WebMouseWheelEvent event = mouse_wheel_event;
event.SetPositionInWidget(point_in_target->x(), point_in_target->y());
target->ProcessMouseWheelEvent(event, latency);
- DCHECK(root_view->wheel_scroll_latching_enabled() || !wheel_target_.target);
if (mouse_wheel_event.phase == blink::WebMouseWheelEvent::kPhaseEnded ||
mouse_wheel_event.momentum_phase ==
blink::WebMouseWheelEvent::kPhaseEnded) {
@@ -673,6 +661,8 @@ void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
std::vector<RenderWidgetHostViewBase*> exited_views;
RenderWidgetHostViewBase* cur_view = target;
entered_views.push_back(cur_view);
+ // Non-root RWHVs are guaranteed to be RenderWidgetHostViewChildFrames,
+ // as long as they are the only embeddable RWHVs.
while (cur_view->IsRenderWidgetHostViewChildFrame()) {
cur_view =
static_cast<RenderWidgetHostViewChildFrame*>(cur_view)->GetParentView();
@@ -685,9 +675,12 @@ void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
}
entered_views.push_back(cur_view);
}
- // Non-root RWHVs are guaranteed to be RenderWidgetHostViewChildFrames,
- // as long as they are the only embeddable RWHVs.
- DCHECK_EQ(cur_view, root_view);
+
+ // On Windows, it appears to be possible that render widget targeting could
+ // produce a target that is outside of the specified root. For now, we'll
+ // just give up in such a case. See https://crbug.com/851958.
+ if (cur_view != root_view)
+ return;
cur_view = last_mouse_move_target_;
if (cur_view) {
@@ -799,8 +792,7 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
const blink::WebGestureEvent& event,
const RenderWidgetHostViewBase* resending_view) {
DCHECK(target_view);
- DCHECK((target_view->wheel_scroll_latching_enabled() &&
- event.GetType() == blink::WebInputEvent::kGestureScrollBegin) ||
+ DCHECK(event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
event.GetType() == blink::WebInputEvent::kGestureFlingStart);
@@ -808,136 +800,67 @@ void RenderWidgetHostInputEventRouter::BubbleScrollEvent(
ui::LatencyInfo latency_info =
ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(event);
- if (target_view->wheel_scroll_latching_enabled()) {
- if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
- // If target_view has unrelated gesture events in progress, do
- // not proceed. This could cause confusion between independent
- // scrolls.
- if (target_view == touchscreen_gesture_target_.target ||
- target_view == touchpad_gesture_target_.target ||
- target_view == touch_target_.target) {
- return;
- }
-
- // This accounts for bubbling through nested OOPIFs. A gesture scroll
- // begin has been bubbled but the target has sent back a gesture scroll
- // event ack which didn't consume any scroll delta, and so another level
- // of bubbling is needed. This requires a GestureScrollEnd be sent to the
- // last view, which will no longer be the scroll target.
- if (bubbling_gesture_scroll_target_.target) {
- SendGestureScrollEnd(
- bubbling_gesture_scroll_target_.target,
- GestureEventInTarget(event,
- bubbling_gesture_scroll_target_.target));
- } else {
- first_bubbling_scroll_target_.target = target_view;
- }
-
- bubbling_gesture_scroll_target_.target = target_view;
- } else { // !(event.GetType() == blink::WebInputEvent::kGestureScrollBegin)
- if (!bubbling_gesture_scroll_target_.target) {
- // The GestureScrollBegin event is not bubbled, don't bubble the rest of
- // the scroll events.
- return;
- }
-
- // Don't bubble the GSE events that are generated and sent to intermediate
- // bubbling targets.
- if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd &&
- target_view != first_bubbling_scroll_target_.target) {
- return;
- }
- }
-
- // If the router tries to resend a gesture scroll event back to the same
- // view, we could hang.
- DCHECK_NE(resending_view, bubbling_gesture_scroll_target_.target);
- // We've seen reports of this, but don't know the cause yet. For now,
- // instead of CHECKing or hanging, we'll report the issue and abort scroll
- // bubbling.
- // TODO(828422): Remove once this issue no longer occurs.
- if (resending_view == bubbling_gesture_scroll_target_.target) {
- ReportBubblingScrollToSameView(event, resending_view);
- first_bubbling_scroll_target_.target = nullptr;
- bubbling_gesture_scroll_target_.target = nullptr;
+ if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
+ // If target_view has unrelated gesture events in progress, do
+ // not proceed. This could cause confusion between independent
+ // scrolls.
+ if (target_view == touchscreen_gesture_target_.target ||
+ target_view == touchpad_gesture_target_.target ||
+ target_view == touch_target_.target) {
return;
}
- bubbling_gesture_scroll_target_.target->ProcessGestureEvent(
- GestureEventInTarget(event, bubbling_gesture_scroll_target_.target),
- latency_info);
- if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
- event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
- first_bubbling_scroll_target_.target = nullptr;
- bubbling_gesture_scroll_target_.target = nullptr;
+ // This accounts for bubbling through nested OOPIFs. A gesture scroll
+ // begin has been bubbled but the target has sent back a gesture scroll
+ // event ack which didn't consume any scroll delta, and so another level
+ // of bubbling is needed. This requires a GestureScrollEnd be sent to the
+ // last view, which will no longer be the scroll target.
+ if (bubbling_gesture_scroll_target_.target) {
+ SendGestureScrollEnd(
+ bubbling_gesture_scroll_target_.target,
+ GestureEventInTarget(event, bubbling_gesture_scroll_target_.target));
+ } else {
+ first_bubbling_scroll_target_.target = target_view;
}
- return;
- }
-
- DCHECK(!target_view->wheel_scroll_latching_enabled());
-
- // DCHECK_XNOR the current and original bubble targets. Both should be set
- // if a bubbling gesture scroll is in progress.
- DCHECK(!first_bubbling_scroll_target_.target ==
- !bubbling_gesture_scroll_target_.target);
+ bubbling_gesture_scroll_target_.target = target_view;
+ } else { // !(event.GetType() == blink::WebInputEvent::kGestureScrollBegin)
+ if (!bubbling_gesture_scroll_target_.target) {
+ // The GestureScrollBegin event is not bubbled, don't bubble the rest of
+ // the scroll events.
+ return;
+ }
- // If target_view is already set up for bubbled scrolls, we forward
- // the event to the current scroll target without further consideration.
- if (target_view == first_bubbling_scroll_target_.target) {
- bubbling_gesture_scroll_target_.target->ProcessGestureEvent(
- GestureEventInTarget(event, bubbling_gesture_scroll_target_.target),
- latency_info);
- if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
- event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
- first_bubbling_scroll_target_.target = nullptr;
- bubbling_gesture_scroll_target_.target = nullptr;
+ // Don't bubble the GSE events that are generated and sent to intermediate
+ // bubbling targets.
+ if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd &&
+ target_view != first_bubbling_scroll_target_.target) {
+ return;
}
- return;
}
- // Disregard GestureScrollEnd events going to non-current targets.
- // These should only happen on ACKs of synthesized GSE events that are
- // sent from SendGestureScrollEnd calls, and are not relevant here.
- if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd)
- return;
-
- // This is a special case to catch races where multiple GestureScrollUpdates
- // have been sent to a renderer before the first one was ACKed, and the ACK
- // caused a bubble retarget. In this case they all get forwarded.
- if (target_view == bubbling_gesture_scroll_target_.target) {
- bubbling_gesture_scroll_target_.target->ProcessGestureEvent(
- GestureEventInTarget(event, bubbling_gesture_scroll_target_.target),
- latency_info);
+ // If the router tries to resend a gesture scroll event back to the same
+ // view, we could hang.
+ DCHECK_NE(resending_view, bubbling_gesture_scroll_target_.target);
+ // We've seen reports of this, but don't know the cause yet. For now,
+ // instead of CHECKing or hanging, we'll report the issue and abort scroll
+ // bubbling.
+ // TODO(828422): Remove once this issue no longer occurs.
+ if (resending_view == bubbling_gesture_scroll_target_.target) {
+ ReportBubblingScrollToSameView(event, resending_view);
+ first_bubbling_scroll_target_.target = nullptr;
+ bubbling_gesture_scroll_target_.target = nullptr;
return;
}
- // If target_view has unrelated gesture events in progress, do
- // not proceed. This could cause confusion between independent
- // scrolls.
- if (target_view == touchscreen_gesture_target_.target ||
- target_view == touchpad_gesture_target_.target ||
- target_view == touch_target_.target)
- return;
-
- // This accounts for bubbling through nested OOPIFs. A gesture scroll has
- // been bubbled but the target has sent back a gesture scroll event ack with
- // unused scroll delta, and so another level of bubbling is needed. This
- // requires a GestureScrollEnd be sent to the last view, which will no
- // longer be the scroll target.
- if (bubbling_gesture_scroll_target_.target) {
- SendGestureScrollEnd(
- bubbling_gesture_scroll_target_.target,
- GestureEventInTarget(event, bubbling_gesture_scroll_target_.target));
- } else {
- first_bubbling_scroll_target_.target = target_view;
+ bubbling_gesture_scroll_target_.target->ProcessGestureEvent(
+ GestureEventInTarget(event, bubbling_gesture_scroll_target_.target),
+ latency_info);
+ if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
+ event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
+ first_bubbling_scroll_target_.target = nullptr;
+ bubbling_gesture_scroll_target_.target = nullptr;
}
-
- bubbling_gesture_scroll_target_.target = target_view;
-
- SendGestureScrollBegin(target_view, GestureEventInTarget(event, target_view));
- target_view->ProcessGestureEvent(GestureEventInTarget(event, target_view),
- latency_info);
}
void RenderWidgetHostInputEventRouter::SendGestureScrollBegin(
@@ -976,7 +899,6 @@ void RenderWidgetHostInputEventRouter::SendGestureScrollEnd(
scroll_end.SetTimeStamp(base::TimeTicks::Now());
switch (event.GetType()) {
case blink::WebInputEvent::kGestureScrollBegin:
- DCHECK(view->wheel_scroll_latching_enabled());
scroll_end.data.scroll_end.inertial_phase =
event.data.scroll_begin.inertial_phase;
scroll_end.data.scroll_end.delta_units =
@@ -1126,8 +1048,8 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
// should have been one.
if (root_view != touchscreen_gesture_target_.target &&
!rwhi->is_in_touchscreen_gesture_scroll()) {
- cc::TouchAction target_allowed_touch_action =
- cc::TouchAction::kTouchActionAuto;
+ base::Optional<cc::TouchAction> target_allowed_touch_action(
+ cc::kTouchActionNone);
if (touchscreen_gesture_target_.target) {
target_allowed_touch_action =
(static_cast<RenderWidgetHostImpl*>(
@@ -1135,7 +1057,8 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
->input_router()
->AllowedTouchAction();
}
- if (target_allowed_touch_action &
+ DCHECK(target_allowed_touch_action.has_value());
+ if (target_allowed_touch_action.value() &
cc::TouchAction::kTouchActionPinchZoom) {
gesture_pinch_did_send_scroll_begin_ = true;
SendGestureScrollBegin(root_view, gesture_event);
@@ -1167,6 +1090,12 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
return;
}
+ if (gesture_event.GetType() == blink::WebInputEvent::kGestureFlingCancel &&
+ last_fling_start_target_) {
+ last_fling_start_target_->ProcessGestureEvent(gesture_event, latency);
+ return;
+ }
+
auto gesture_target_it =
touchscreen_gesture_target_map_.find(gesture_event.unique_touch_event_id);
bool no_matching_id =
@@ -1233,6 +1162,11 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
}
}
+ // If we set a target and it's not in the map, we won't get notified if the
+ // target goes away, so drop the target and the resulting events.
+ if (!touchscreen_gesture_target_in_map_)
+ touchscreen_gesture_target_.target = nullptr;
+
if (!touchscreen_gesture_target_.target) {
root_view->GestureEventAck(gesture_event,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
@@ -1264,6 +1198,9 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
base::StringPrintf("%u", static_cast<int>(owner_map_.size())));
touchscreen_gesture_target_.target->ProcessGestureEvent(event, latency);
+
+ if (gesture_event.GetType() == blink::WebInputEvent::kGestureFlingStart)
+ last_fling_start_target_ = touchscreen_gesture_target_.target;
}
void RenderWidgetHostInputEventRouter::RouteTouchscreenGestureEvent(
@@ -1279,13 +1216,13 @@ RenderWidgetHostInputEventRouter::FindTouchpadGestureEventTarget(
RenderWidgetHostViewBase* root_view,
const blink::WebGestureEvent& event) const {
if (event.GetType() != blink::WebInputEvent::kGesturePinchBegin &&
- event.GetType() != blink::WebInputEvent::kGestureFlingStart) {
+ event.GetType() != blink::WebInputEvent::kGestureFlingCancel) {
return {nullptr, false, base::nullopt, true};
}
gfx::PointF transformed_point;
return FindViewAtLocation(root_view, event.PositionInWidget(),
- event.PositionInScreen(), viz::EventSource::TOUCH,
+ event.PositionInScreen(), viz::EventSource::MOUSE,
&transformed_point);
}
@@ -1303,6 +1240,37 @@ void RenderWidgetHostInputEventRouter::DispatchTouchpadGestureEvent(
const blink::WebGestureEvent& touchpad_gesture_event,
const ui::LatencyInfo& latency,
const base::Optional<gfx::PointF>& target_location) {
+ // Touchpad gesture flings should be treated as mouse wheels for the purpose
+ // of routing.
+ if (touchpad_gesture_event.GetType() ==
+ blink::WebInputEvent::kGestureFlingStart) {
+ if (wheel_target_.target) {
+ blink::WebGestureEvent gesture_fling = touchpad_gesture_event;
+ gesture_fling.SetPositionInWidget(gesture_fling.PositionInWidget() +
+ wheel_target_.delta);
+ wheel_target_.target->ProcessGestureEvent(gesture_fling, latency);
+ last_fling_start_target_ = wheel_target_.target;
+ } else {
+ root_view->GestureEventAck(touchpad_gesture_event,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ }
+ return;
+ }
+
+ if (touchpad_gesture_event.GetType() ==
+ blink::WebInputEvent::kGestureFlingCancel) {
+ if (last_fling_start_target_) {
+ last_fling_start_target_->ProcessGestureEvent(touchpad_gesture_event,
+ latency);
+ } else if (target) {
+ target->ProcessGestureEvent(touchpad_gesture_event, latency);
+ } else {
+ root_view->GestureEventAck(touchpad_gesture_event,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ }
+ return;
+ }
+
if (target) {
touchpad_gesture_target_.target = target;
// TODO(mohsen): Instead of just computing a delta, we should extract the
@@ -1336,6 +1304,11 @@ void RenderWidgetHostInputEventRouter::DispatchTouchpadGestureEvent(
gesture_event.SetPositionInWidget(gesture_event.PositionInWidget() +
touchpad_gesture_target_.delta);
touchpad_gesture_target_.target->ProcessGestureEvent(gesture_event, latency);
+
+ if (touchpad_gesture_event.GetType() ==
+ blink::WebInputEvent::kGesturePinchEnd) {
+ touchpad_gesture_target_.target = nullptr;
+ }
}
RenderWidgetHostViewBase*
@@ -1458,7 +1431,11 @@ void RenderWidgetHostInputEventRouter::ForwardEmulatedGestureEvent(
const blink::WebGestureEvent& event) {
TRACE_EVENT0("input",
"RenderWidgetHostInputEventRouter::ForwardEmulatedGestureEvent");
- DCHECK(last_emulated_event_root_view_);
+ // It's possible that since |last_emulated_event_root_view_| was set by the
+ // outbound touch event that the view may have gone away. Before with dispatch
+ // the GestureEvent, confirm the view is still available.
+ if (!IsViewInMap(last_emulated_event_root_view_))
+ return;
DispatchTouchscreenGestureEvent(last_emulated_event_root_view_, nullptr,
event, ui::LatencyInfo(),
event.PositionInWidget());
@@ -1501,7 +1478,11 @@ void RenderWidgetHostInputEventRouter::SetCursor(const WebCursor& cursor) {
void RenderWidgetHostInputEventRouter::ShowContextMenuAtPoint(
const gfx::Point& point,
const ui::MenuSourceType source_type) {
- DCHECK(last_mouse_move_target_);
+ // It's possible that since |last_mouse_move_target_| was set by the
+ // outbound mouse event that the view may have gone away. Before dispatching
+ // the context menu, confirm the view is still available.
+ if (!IsViewInMap(last_mouse_move_target_))
+ return;
auto* rwhi = static_cast<RenderWidgetHostImpl*>(
last_mouse_move_target_->GetRenderWidgetHost());
diff --git a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
index 9d766924b89..68d7cf064c2 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
@@ -283,8 +283,7 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
TargetData touchpad_gesture_target_;
TargetData bubbling_gesture_scroll_target_;
TargetData first_bubbling_scroll_target_;
- // Used to target wheel events for the duration of a scroll when wheel scroll
- // latching is enabled.
+ // Used to target wheel events for the duration of a scroll.
TargetData wheel_target_;
// Maintains the same target between mouse down and mouse up.
TargetData mouse_capture_target_;
@@ -293,6 +292,9 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
RenderWidgetHostViewBase* last_mouse_move_target_;
RenderWidgetHostViewBase* last_mouse_move_root_view_;
+ // Tracked for the purpose of targeting subsequent fling cancel events.
+ RenderWidgetHostViewBase* last_fling_start_target_ = nullptr;
+
// Tracked for the purpose of providing a root_view when dispatching emulated
// touch/gesture events.
RenderWidgetHostViewBase* last_emulated_event_root_view_;
@@ -324,6 +326,8 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
InputEventRouterGesturePreventDefaultTargetMapTest);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
InputEventRouterTouchpadGestureTargetTest);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
+ TouchpadPinchOverOOPIF);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessMouseWheelHitTestBrowserTest,
InputEventRouterWheelTargetTest);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessMacBrowserTest,
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.h b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.h
deleted file mode 100644
index 3761be5f730..00000000000
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2018 The Chromium Authors. All 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_NS_VIEW_BRIDGE_H_
-#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_BRIDGE_H_
-
-@class RenderWidgetHostViewCocoa;
-
-#include <memory>
-
-#include "base/containers/flat_set.h"
-#include "base/macros.h"
-#include "base/optional.h"
-#include "base/strings/string16.h"
-#include "content/common/mac/attributed_string_coder.h"
-#include "third_party/blink/public/web/web_popup_type.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/base/ime/text_input_type.h"
-
-namespace gfx {
-struct CALayerParams;
-class Point;
-class Range;
-class Rect;
-} // namespace gfx
-
-namespace ui {
-enum class DomCode;
-} // namespace ui
-
-namespace content {
-
-class RenderWidgetHostNSViewClient;
-class WebCursor;
-
-// The interface through which RenderWidgetHostViewMac is to manipulate its
-// corresponding NSView (potentially in another process).
-class RenderWidgetHostNSViewBridge {
- public:
- RenderWidgetHostNSViewBridge() {}
- virtual ~RenderWidgetHostNSViewBridge() {}
-
- static std::unique_ptr<RenderWidgetHostNSViewBridge> Create(
- RenderWidgetHostNSViewClient* client);
-
- // TODO(ccameron): RenderWidgetHostViewMac and other functions currently use
- // this method to communicate directly with RenderWidgetHostViewCocoa. The
- // goal of this class is to eliminate this direct communication (so this
- // method is expected to go away).
- virtual RenderWidgetHostViewCocoa* GetRenderWidgetHostViewCocoa() = 0;
-
- // Initialize the window as a popup (e.g, date/time picker).
- virtual void InitAsPopup(const gfx::Rect& content_rect,
- blink::WebPopupType popup_type) = 0;
-
- // Disable displaying any content (including the background color). This is
- // to be called on views that are to be displayed via a parent ui::Compositor.
- virtual void DisableDisplay() = 0;
-
- // Make the NSView be the first responder of its NSWindow.
- virtual void MakeFirstResponder() = 0;
-
- // Set the bounds of the NSView or its enclosing NSWindow (depending on the
- // window type).
- virtual void SetBounds(const gfx::Rect& rect) = 0;
-
- // Set the contents to display in the NSView.
- virtual void SetCALayerParams(const gfx::CALayerParams& ca_layer_params) = 0;
-
- // Set the background color of the hosted CALayer.
- virtual void SetBackgroundColor(SkColor color) = 0;
-
- // Call the -[NSView setHidden:] method.
- virtual void SetVisible(bool visible) = 0;
-
- // Call the -[NSView setToolTipAtMousePoint] method.
- virtual void SetTooltipText(const base::string16& display_text) = 0;
-
- // Forward changes in ui::TextInputType.
- virtual void SetTextInputType(ui::TextInputType text_input_type) = 0;
-
- // Forward the TextInputManager::TextSelection from the renderer.
- virtual void SetTextSelection(const base::string16& text,
- size_t offset,
- const gfx::Range& range) = 0;
-
- // Forward the TextInputManager::CompositionRangeInfo from the renderer.
- virtual void SetCompositionRangeInfo(const gfx::Range& range) = 0;
-
- // Clear the marked range.
- virtual void CancelComposition() = 0;
-
- // Indicate if the WebContext is showing a context menu.
- virtual void SetShowingContextMenu(bool showing) = 0;
-
- // Set the cursor type to display.
- virtual void DisplayCursor(const WebCursor& cursor) = 0;
-
- // Lock or unlock the cursor.
- virtual void SetCursorLocked(bool locked) = 0;
-
- // Open the dictionary overlay for the currently selected string. This
- // will roundtrip to the NSView to determine the selected range.
- virtual void ShowDictionaryOverlayForSelection() = 0;
-
- // Open the dictionary overlay for the specified string at the specified
- // point.
- virtual void ShowDictionaryOverlay(
- const mac::AttributedStringCoder::EncodedString& encoded_string,
- gfx::Point baseline_point) = 0;
-
- // Start intercepting keyboard events.
- virtual void LockKeyboard(
- base::Optional<base::flat_set<ui::DomCode>> dom_codes) = 0;
-
- // Stop intercepting keyboard events.
- virtual void UnlockKeyboard() = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewBridge);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_BRIDGE_H_
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h
new file mode 100644
index 00000000000..a7678f05d79
--- /dev/null
+++ b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h
@@ -0,0 +1,99 @@
+// Copyright 2018 The Chromium Authors. All 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_NS_VIEW_BRIDGE_LOCAL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_BRIDGE_LOCAL_H_
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/scoped_nsobject.h"
+#import "content/browser/renderer_host/popup_window_mac.h"
+#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
+#include "content/common/render_widget_host_ns_view.mojom.h"
+#include "ui/accelerated_widget_mac/display_ca_layer_tree.h"
+#include "ui/display/display_observer.h"
+
+namespace content {
+
+// Bridge to a locally-hosted NSView -- this is always instantiated in the same
+// process as the NSView. The caller of this interface may exist in another
+// process.
+class RenderWidgetHostNSViewBridgeLocal
+ : public mojom::RenderWidgetHostNSViewBridge,
+ public display::DisplayObserver {
+ public:
+ RenderWidgetHostNSViewBridgeLocal(
+ mojom::RenderWidgetHostNSViewClient* client,
+ RenderWidgetHostNSViewLocalClient* local_client);
+ ~RenderWidgetHostNSViewBridgeLocal() override;
+
+ // TODO(ccameron): RenderWidgetHostViewMac and other functions currently use
+ // this method to communicate directly with RenderWidgetHostViewCocoa. The
+ // goal of this class is to eliminate this direct communication (so this
+ // method is expected to go away).
+ RenderWidgetHostViewCocoa* GetRenderWidgetHostViewCocoa();
+
+ // mojom::RenderWidgetHostNSViewBridge implementation.
+ void InitAsPopup(const gfx::Rect& content_rect,
+ blink::WebPopupType popup_type) override;
+ void DisableDisplay() override;
+ void MakeFirstResponder() override;
+ void SetBounds(const gfx::Rect& rect) override;
+ void SetCALayerParams(const gfx::CALayerParams& ca_layer_params) override;
+ void SetBackgroundColor(SkColor color) override;
+ void SetVisible(bool visible) override;
+ void SetTooltipText(const base::string16& display_text) override;
+ void SetTextInputType(ui::TextInputType text_input_type) override;
+ void SetTextSelection(const base::string16& text,
+ uint64_t offset,
+ const gfx::Range& range) override;
+ void SetCompositionRangeInfo(const gfx::Range& range) override;
+ void CancelComposition() override;
+ void SetShowingContextMenu(bool showing) override;
+ void DisplayCursor(const WebCursor& cursor) override;
+ void SetCursorLocked(bool locked) override;
+ void ShowDictionaryOverlayForSelection() override;
+ void ShowDictionaryOverlay(
+ const mac::AttributedStringCoder::EncodedString& encoded_string,
+ const gfx::Point& baseline_point) override;
+ void LockKeyboard(
+ const base::Optional<std::vector<uint32_t>>& uint_dom_codes) override;
+ void UnlockKeyboard() override;
+
+ private:
+ bool IsPopup() const {
+ // TODO(ccameron): If this is not equivalent to |popup_window_| then
+ // there are bugs.
+ return popup_type_ != blink::kWebPopupTypeNone;
+ }
+
+ // display::DisplayObserver implementation.
+ void OnDisplayMetricsChanged(const display::Display& display,
+ uint32_t metrics) override;
+
+ // The NSView used for input and display.
+ base::scoped_nsobject<RenderWidgetHostViewCocoa> cocoa_view_;
+
+ // Once set, all calls to set the background color or CALayer content will
+ // be ignored.
+ bool display_disabled_ = false;
+
+ // The window used for popup widgets, and its helper.
+ std::unique_ptr<PopupWindowMac> popup_window_;
+ blink::WebPopupType popup_type_ = blink::kWebPopupTypeNone;
+
+ // The background CALayer which is hosted by |cocoa_view_|, and is used as
+ // the root of |display_ca_layer_tree_|.
+ base::scoped_nsobject<CALayer> background_layer_;
+ std::unique_ptr<ui::DisplayCALayerTree> display_ca_layer_tree_;
+
+ // Cached copy of the tooltip text, to avoid redundant calls.
+ base::string16 tooltip_text_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewBridgeLocal);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_BRIDGE_LOCAL_H_
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm
index 54b1c71bb4c..9df5543cc21 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm
@@ -2,103 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "content/browser/renderer_host/render_widget_host_ns_view_bridge.h"
-
-#import <Cocoa/Cocoa.h>
+#import "content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h"
#include "base/mac/scoped_cftyperef.h"
-#import "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
-#import "content/browser/renderer_host/popup_window_mac.h"
-#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
#include "content/common/cursors/webcursor.h"
#import "skia/ext/skia_utils_mac.h"
-#include "ui/accelerated_widget_mac/display_ca_layer_tree.h"
#import "ui/base/cocoa/animation_utils.h"
-#include "ui/display/display_observer.h"
#include "ui/display/screen.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/mac/coordinate_conversion.h"
namespace content {
-namespace {
-
-// Bridge to a locally-hosted NSView -- this is always instantiated in the same
-// process as the NSView. The caller of this interface may exist in another
-// process.
-class RenderWidgetHostViewNSViewBridgeLocal
- : public RenderWidgetHostNSViewBridge,
- public display::DisplayObserver {
- public:
- explicit RenderWidgetHostViewNSViewBridgeLocal(
- RenderWidgetHostNSViewClient* client);
- ~RenderWidgetHostViewNSViewBridgeLocal() override;
- RenderWidgetHostViewCocoa* GetRenderWidgetHostViewCocoa() override;
-
- void InitAsPopup(const gfx::Rect& content_rect,
- blink::WebPopupType popup_type) override;
- void DisableDisplay() override;
- void MakeFirstResponder() override;
- void SetBounds(const gfx::Rect& rect) override;
- void SetCALayerParams(const gfx::CALayerParams& ca_layer_params) override;
- void SetBackgroundColor(SkColor color) override;
- void SetVisible(bool visible) override;
- void SetTooltipText(const base::string16& display_text) override;
- void SetTextInputType(ui::TextInputType text_input_type) override;
- void SetTextSelection(const base::string16& text,
- size_t offset,
- const gfx::Range& range) override;
- void SetCompositionRangeInfo(const gfx::Range& range) override;
- void CancelComposition() override;
- void SetShowingContextMenu(bool showing) override;
- void DisplayCursor(const WebCursor& cursor) override;
- void SetCursorLocked(bool locked) override;
- void ShowDictionaryOverlayForSelection() override;
- void ShowDictionaryOverlay(
- const mac::AttributedStringCoder::EncodedString& encoded_string,
- gfx::Point baseline_point) override;
- void LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes) override;
- void UnlockKeyboard() override;
-
- private:
- bool IsPopup() const {
- // TODO(ccameron): If this is not equivalent to |popup_window_| then
- // there are bugs.
- return popup_type_ != blink::kWebPopupTypeNone;
- }
-
- // display::DisplayObserver implementation.
- void OnDisplayMetricsChanged(const display::Display& display,
- uint32_t metrics) override;
-
- // The NSView used for input and display.
- base::scoped_nsobject<RenderWidgetHostViewCocoa> cocoa_view_;
-
- // Once set, all calls to set the background color or CALayer content will
- // be ignored.
- bool display_disabled_ = false;
-
- // The window used for popup widgets, and its helper.
- std::unique_ptr<PopupWindowMac> popup_window_;
- blink::WebPopupType popup_type_ = blink::kWebPopupTypeNone;
-
- // The background CALayer which is hosted by |cocoa_view_|, and is used as
- // the root of |display_ca_layer_tree_|.
- base::scoped_nsobject<CALayer> background_layer_;
- std::unique_ptr<ui::DisplayCALayerTree> display_ca_layer_tree_;
-
- // Cached copy of the tooltip text, to avoid redundant calls.
- base::string16 tooltip_text_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewNSViewBridgeLocal);
-};
-
-RenderWidgetHostViewNSViewBridgeLocal::RenderWidgetHostViewNSViewBridgeLocal(
- RenderWidgetHostNSViewClient* client) {
+RenderWidgetHostNSViewBridgeLocal::RenderWidgetHostNSViewBridgeLocal(
+ mojom::RenderWidgetHostNSViewClient* client,
+ RenderWidgetHostNSViewLocalClient* local_client) {
display::Screen::GetScreen()->AddObserver(this);
- cocoa_view_.reset([[RenderWidgetHostViewCocoa alloc] initWithClient:client]);
+ cocoa_view_.reset([[RenderWidgetHostViewCocoa alloc]
+ initWithClient:client
+ withLocalClient:local_client]);
background_layer_.reset([[CALayer alloc] init]);
display_ca_layer_tree_ =
@@ -107,8 +31,7 @@ RenderWidgetHostViewNSViewBridgeLocal::RenderWidgetHostViewNSViewBridgeLocal(
[cocoa_view_ setWantsLayer:YES];
}
-RenderWidgetHostViewNSViewBridgeLocal::
- ~RenderWidgetHostViewNSViewBridgeLocal() {
+RenderWidgetHostNSViewBridgeLocal::~RenderWidgetHostNSViewBridgeLocal() {
[cocoa_view_ setClientDisconnected];
// Do not immediately remove |cocoa_view_| from the NSView heirarchy, because
// the call to -[NSView removeFromSuperview] may cause use to call into the
@@ -123,11 +46,11 @@ RenderWidgetHostViewNSViewBridgeLocal::
}
RenderWidgetHostViewCocoa*
-RenderWidgetHostViewNSViewBridgeLocal::GetRenderWidgetHostViewCocoa() {
+RenderWidgetHostNSViewBridgeLocal::GetRenderWidgetHostViewCocoa() {
return cocoa_view_;
}
-void RenderWidgetHostViewNSViewBridgeLocal::InitAsPopup(
+void RenderWidgetHostNSViewBridgeLocal::InitAsPopup(
const gfx::Rect& content_rect,
blink::WebPopupType popup_type) {
popup_type_ = popup_type;
@@ -135,11 +58,11 @@ void RenderWidgetHostViewNSViewBridgeLocal::InitAsPopup(
std::make_unique<PopupWindowMac>(content_rect, popup_type_, cocoa_view_);
}
-void RenderWidgetHostViewNSViewBridgeLocal::MakeFirstResponder() {
+void RenderWidgetHostNSViewBridgeLocal::MakeFirstResponder() {
[[cocoa_view_ window] makeFirstResponder:cocoa_view_];
}
-void RenderWidgetHostViewNSViewBridgeLocal::DisableDisplay() {
+void RenderWidgetHostNSViewBridgeLocal::DisableDisplay() {
if (display_disabled_)
return;
SetBackgroundColor(SK_ColorTRANSPARENT);
@@ -147,7 +70,7 @@ void RenderWidgetHostViewNSViewBridgeLocal::DisableDisplay() {
display_disabled_ = true;
}
-void RenderWidgetHostViewNSViewBridgeLocal::SetBounds(const gfx::Rect& rect) {
+void RenderWidgetHostNSViewBridgeLocal::SetBounds(const gfx::Rect& rect) {
// |rect.size()| is view coordinates, |rect.origin| is screen coordinates,
// TODO(thakis): fix, http://crbug.com/73362
@@ -188,14 +111,14 @@ void RenderWidgetHostViewNSViewBridgeLocal::SetBounds(const gfx::Rect& rect) {
}
}
-void RenderWidgetHostViewNSViewBridgeLocal::SetCALayerParams(
+void RenderWidgetHostNSViewBridgeLocal::SetCALayerParams(
const gfx::CALayerParams& ca_layer_params) {
if (display_disabled_)
return;
display_ca_layer_tree_->UpdateCALayerTree(ca_layer_params);
}
-void RenderWidgetHostViewNSViewBridgeLocal::SetBackgroundColor(SkColor color) {
+void RenderWidgetHostNSViewBridgeLocal::SetBackgroundColor(SkColor color) {
if (display_disabled_)
return;
ScopedCAActionDisabler disabler;
@@ -204,12 +127,12 @@ void RenderWidgetHostViewNSViewBridgeLocal::SetBackgroundColor(SkColor color) {
[background_layer_ setBackgroundColor:cg_color];
}
-void RenderWidgetHostViewNSViewBridgeLocal::SetVisible(bool visible) {
+void RenderWidgetHostNSViewBridgeLocal::SetVisible(bool visible) {
ScopedCAActionDisabler disabler;
[cocoa_view_ setHidden:!visible];
}
-void RenderWidgetHostViewNSViewBridgeLocal::SetTooltipText(
+void RenderWidgetHostNSViewBridgeLocal::SetTooltipText(
const base::string16& tooltip_text) {
// Called from the renderer to tell us what the tooltip text should be. It
// calls us frequently so we need to cache the value to prevent doing a lot
@@ -233,24 +156,24 @@ void RenderWidgetHostViewNSViewBridgeLocal::SetTooltipText(
[cocoa_view_ setToolTipAtMousePoint:tooltip_nsstring];
}
-void RenderWidgetHostViewNSViewBridgeLocal::SetCompositionRangeInfo(
+void RenderWidgetHostNSViewBridgeLocal::SetCompositionRangeInfo(
const gfx::Range& range) {
[cocoa_view_ setCompositionRange:range];
[cocoa_view_ setMarkedRange:range.ToNSRange()];
}
-void RenderWidgetHostViewNSViewBridgeLocal::CancelComposition() {
+void RenderWidgetHostNSViewBridgeLocal::CancelComposition() {
[cocoa_view_ cancelComposition];
}
-void RenderWidgetHostViewNSViewBridgeLocal::SetTextInputType(
+void RenderWidgetHostNSViewBridgeLocal::SetTextInputType(
ui::TextInputType text_input_type) {
[cocoa_view_ setTextInputType:text_input_type];
}
-void RenderWidgetHostViewNSViewBridgeLocal::SetTextSelection(
+void RenderWidgetHostNSViewBridgeLocal::SetTextSelection(
const base::string16& text,
- size_t offset,
+ uint64_t offset,
const gfx::Range& range) {
[cocoa_view_ setTextSelectionText:text offset:offset range:range];
// Updates markedRange when there is no marked text so that retrieving
@@ -261,12 +184,11 @@ void RenderWidgetHostViewNSViewBridgeLocal::SetTextSelection(
}
}
-void RenderWidgetHostViewNSViewBridgeLocal::SetShowingContextMenu(
- bool showing) {
+void RenderWidgetHostNSViewBridgeLocal::SetShowingContextMenu(bool showing) {
[cocoa_view_ setShowingContextMenu:showing];
}
-void RenderWidgetHostViewNSViewBridgeLocal::OnDisplayMetricsChanged(
+void RenderWidgetHostNSViewBridgeLocal::OnDisplayMetricsChanged(
const display::Display& display,
uint32_t changed_metrics) {
// Note that -updateScreenProperties is also be called by the notification
@@ -275,13 +197,12 @@ void RenderWidgetHostViewNSViewBridgeLocal::OnDisplayMetricsChanged(
[cocoa_view_ updateScreenProperties];
}
-void RenderWidgetHostViewNSViewBridgeLocal::DisplayCursor(
- const WebCursor& cursor) {
+void RenderWidgetHostNSViewBridgeLocal::DisplayCursor(const WebCursor& cursor) {
WebCursor non_const_cursor = cursor;
[cocoa_view_ updateCursor:non_const_cursor.GetNativeCursor()];
}
-void RenderWidgetHostViewNSViewBridgeLocal::SetCursorLocked(bool locked) {
+void RenderWidgetHostNSViewBridgeLocal::SetCursorLocked(bool locked) {
if (locked) {
CGAssociateMouseAndMouseCursorPosition(NO);
[NSCursor hide];
@@ -292,15 +213,14 @@ void RenderWidgetHostViewNSViewBridgeLocal::SetCursorLocked(bool locked) {
}
}
-void RenderWidgetHostViewNSViewBridgeLocal::
- ShowDictionaryOverlayForSelection() {
+void RenderWidgetHostNSViewBridgeLocal::ShowDictionaryOverlayForSelection() {
NSRange selection_range = [cocoa_view_ selectedRange];
[cocoa_view_ showLookUpDictionaryOverlayFromRange:selection_range];
}
-void RenderWidgetHostViewNSViewBridgeLocal::ShowDictionaryOverlay(
+void RenderWidgetHostNSViewBridgeLocal::ShowDictionaryOverlay(
const mac::AttributedStringCoder::EncodedString& encoded_string,
- gfx::Point baseline_point) {
+ const gfx::Point& baseline_point) {
NSAttributedString* string =
mac::AttributedStringCoder::Decode(&encoded_string);
if ([string length] == 0)
@@ -312,21 +232,19 @@ void RenderWidgetHostViewNSViewBridgeLocal::ShowDictionaryOverlay(
atPoint:flipped_baseline_point];
}
-void RenderWidgetHostViewNSViewBridgeLocal::LockKeyboard(
- base::Optional<base::flat_set<ui::DomCode>> dom_codes) {
+void RenderWidgetHostNSViewBridgeLocal::LockKeyboard(
+ const base::Optional<std::vector<uint32_t>>& uint_dom_codes) {
+ base::Optional<base::flat_set<ui::DomCode>> dom_codes;
+ if (uint_dom_codes) {
+ dom_codes.emplace();
+ for (const auto& uint_dom_code : *uint_dom_codes)
+ dom_codes->insert(static_cast<ui::DomCode>(uint_dom_code));
+ }
[cocoa_view_ lockKeyboard:std::move(dom_codes)];
}
-void RenderWidgetHostViewNSViewBridgeLocal::UnlockKeyboard() {
+void RenderWidgetHostNSViewBridgeLocal::UnlockKeyboard() {
[cocoa_view_ unlockKeyboard];
}
-} // namespace
-
-// static
-std::unique_ptr<RenderWidgetHostNSViewBridge>
-RenderWidgetHostNSViewBridge::Create(RenderWidgetHostNSViewClient* client) {
- return std::make_unique<RenderWidgetHostViewNSViewBridgeLocal>(client);
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h b/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h
index bc2365191c6..92f4fd7407f 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h
@@ -6,11 +6,8 @@
#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_H_
#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "content/common/edit_command.h"
-#include "content/common/mac/attributed_string_coder.h"
-#include "ui/base/ime/ime_text_span.h"
-#include "ui/base/ime/text_input_type.h"
+
+#include <vector>
namespace blink {
class WebGestureEvent;
@@ -18,170 +15,62 @@ class WebMouseEvent;
class WebMouseWheelEvent;
} // namespace blink
-namespace display {
-class Display;
-} // namespace display
-
-namespace gfx {
-class PointF;
-class Range;
-class Rect;
-} // namespace gfx
-
namespace ui {
class LatencyInfo;
} // namespace ui
namespace content {
-class RenderWidgetHostViewMac;
+class BrowserAccessibilityManager;
+struct EditCommand;
+struct NativeWebKeyboardEvent;
-// The interface through which the NSView for a RenderWidgetHostViewMac is to
+// An interface through which the NSView for a RenderWidgetHostViewMac is to
// communicate with the RenderWidgetHostViewMac (potentially in another
-// process).
-class RenderWidgetHostNSViewClient {
+// process). Unlike mojom::RenderWidgetHostNSViewClient, this object is always
+// instantiated in the local process. This is to implement functions that
+// cannot be sent across mojo (e.g, GetRootBrowserAccessibilityManager), or
+// to avoid unnecessary translation of event types.
+class RenderWidgetHostNSViewLocalClient {
public:
- RenderWidgetHostNSViewClient() {}
- virtual ~RenderWidgetHostNSViewClient() {}
+ RenderWidgetHostNSViewLocalClient() {}
+ virtual ~RenderWidgetHostNSViewLocalClient() {}
// Return the RenderWidget's BrowserAccessibilityManager.
// TODO(ccameron): This returns nullptr for non-local NSViews. A scheme for
// non-local accessibility needs to be developed.
virtual BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() = 0;
- // Synchronously query if there exists a RenderViewHost for the corresponding
- // RenderWidgetHostView's RenderWidgetHost, and store the result in
- // |*is_render_view|.
- virtual void OnNSViewSyncIsRenderViewHost(bool* is_render_view) = 0;
-
- // Indicates that the RenderWidgetHost is to shut down.
- virtual void OnNSViewRequestShutdown() = 0;
-
- // Indicates whether or not the NSView is its NSWindow's first responder.
- virtual void OnNSViewIsFirstResponderChanged(bool is_first_responder) = 0;
-
- // Indicates whether or not the NSView's NSWindow is key.
- virtual void OnNSViewWindowIsKeyChanged(bool is_key) = 0;
-
- // Indicates the NSView's bounds in its NSWindow's DIP coordinate system (with
- // the origin at the upper-left corner), and indicate if the the NSView is
- // attached to an NSWindow (if it is not, then |view_bounds_in_window_dip|'s
- // origin is meaningless, but its size is still relevant).
- virtual void OnNSViewBoundsInWindowChanged(
- const gfx::Rect& view_bounds_in_window_dip,
- bool attached_to_window) = 0;
-
- // Indicates the NSView's NSWindow's frame in the global display::Screen
- // DIP coordinate system (where the origin the upper-left corner of
- // Screen::GetPrimaryDisplay).
- virtual void OnNSViewWindowFrameInScreenChanged(
- const gfx::Rect& window_frame_in_screen_dip) = 0;
-
- // Indicate the NSView's NSScreen's properties.
- virtual void OnNSViewDisplayChanged(const display::Display& display) = 0;
-
- // Indicate the begin and end block of a keyboard event. The beginning of this
- // block will record the active RenderWidgetHost, and will forward all
- // remaining keyboard and Ime messages to that RenderWidgetHost.
- virtual void OnNSViewBeginKeyboardEvent() = 0;
- virtual void OnNSViewEndKeyboardEvent() = 0;
-
// Forward a keyboard event to the RenderWidgetHost that is currently handling
// the key-down event.
- virtual void OnNSViewForwardKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info) = 0;
- virtual void OnNSViewForwardKeyboardEventWithCommands(
+ virtual void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info) = 0;
+ virtual void ForwardKeyboardEventWithCommands(
const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency_info,
const std::vector<EditCommand>& commands) = 0;
// Forward events to the renderer or the input router, as appropriate.
- virtual void OnNSViewRouteOrProcessMouseEvent(
+ virtual void RouteOrProcessMouseEvent(
const blink::WebMouseEvent& web_event) = 0;
- virtual void OnNSViewRouteOrProcessWheelEvent(
+ virtual void RouteOrProcessWheelEvent(
const blink::WebMouseWheelEvent& web_event) = 0;
// Special case forwarding of synthetic events to the renderer.
- virtual void OnNSViewForwardMouseEvent(
- const blink::WebMouseEvent& web_event) = 0;
- virtual void OnNSViewForwardWheelEvent(
+ virtual void ForwardMouseEvent(const blink::WebMouseEvent& web_event) = 0;
+ virtual void ForwardWheelEvent(
const blink::WebMouseWheelEvent& web_event) = 0;
// Handling pinch gesture events.
- virtual void OnNSViewGestureBegin(blink::WebGestureEvent begin_event,
- bool is_synthetically_injected) = 0;
- virtual void OnNSViewGestureUpdate(blink::WebGestureEvent update_event) = 0;
- virtual void OnNSViewGestureEnd(blink::WebGestureEvent end_event) = 0;
- virtual void OnNSViewSmartMagnify(
+ virtual void GestureBegin(blink::WebGestureEvent begin_event,
+ bool is_synthetically_injected) = 0;
+ virtual void GestureUpdate(blink::WebGestureEvent update_event) = 0;
+ virtual void GestureEnd(blink::WebGestureEvent end_event) = 0;
+ virtual void SmartMagnify(
const blink::WebGestureEvent& smart_magnify_event) = 0;
- // Forward the corresponding Ime commands to the appropriate RenderWidgetHost.
- // Appropriate, has two meanings here. If this is during a key-down event,
- // then the target is the RWH that is handling that key-down event. Otherwise,
- // it is the result of GetActiveWidget.
- virtual void OnNSViewImeSetComposition(
- const base::string16& text,
- const std::vector<ui::ImeTextSpan>& ime_text_spans,
- const gfx::Range& replacement_range,
- int selection_start,
- int selection_end) = 0;
- virtual void OnNSViewImeCommitText(const base::string16& text,
- const gfx::Range& replacement_range) = 0;
- virtual void OnNSViewImeFinishComposingText() = 0;
- virtual void OnNSViewImeCancelComposition() = 0;
-
- // Request an overlay dictionary be displayed for the text at the specified
- // point.
- virtual void OnNSViewLookUpDictionaryOverlayAtPoint(
- const gfx::PointF& root_point) = 0;
-
- // Request an overlay dictionary be displayed for the text in the the
- // specified character range.
- virtual void OnNSViewLookUpDictionaryOverlayFromRange(
- const gfx::Range& range) = 0;
-
- // Synchronously query the character index for |root_point| and return it in
- // |*index|. Sets it to UINT32_MAX if the request fails or is not completed.
- virtual void OnNSViewSyncGetCharacterIndexAtPoint(
- const gfx::PointF& root_point,
- uint32_t* index) = 0;
-
- // Synchronously query the composition character boundary rectangle and return
- // it in |*rect|. Set |*actual_range| to the range actually used for the
- // returned rectangle. If there was no focused RenderWidgetHost to query,
- // then set |*success| to false.
- virtual void OnNSViewSyncGetFirstRectForRange(
- const gfx::Range& requested_range,
- gfx::Rect* rect,
- gfx::Range* actual_range,
- bool* success) = 0;
-
- // Forward the corresponding edit menu command to the RenderWidgetHost's
- // delegate.
- virtual void OnNSViewExecuteEditCommand(const std::string& command) = 0;
- virtual void OnNSViewUndo() = 0;
- virtual void OnNSViewRedo() = 0;
- virtual void OnNSViewCut() = 0;
- virtual void OnNSViewCopy() = 0;
- virtual void OnNSViewCopyToFindPboard() = 0;
- virtual void OnNSViewPaste() = 0;
- virtual void OnNSViewPasteAndMatchStyle() = 0;
- virtual void OnNSViewSelectAll() = 0;
-
- // Speak the selected text of the appropriate RenderWidgetHostView using
- // TextServicesContextMenu.
- virtual void OnNSViewSpeakSelection() = 0;
-
- // Stop speaking using TextServicesContextMenu.
- virtual void OnNSViewStopSpeaking() = 0;
-
- // Synchronously query if TextServicesContextMenu is currently speaking and
- // store the result in |*is_speaking|.
- virtual void OnNSViewSyncIsSpeaking(bool* is_speaking) = 0;
-
private:
- DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewClient);
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewLocalClient);
};
} // 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 409e8efb2a7..24a08a3fdf6 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
@@ -57,6 +57,9 @@ class CONTENT_EXPORT RenderWidgetHostOwnerDelegate {
// priority to the RenderProcessHost.
virtual bool ShouldContributePriorityToProcess() = 0;
+ // Called when the RenderWidgetHost has shutdown.
+ virtual void RenderWidgetDidShutdown() = 0;
+
protected:
virtual ~RenderWidgetHostOwnerDelegate() {}
};
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 99e582adf7d..e5de66d7b7c 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -14,7 +14,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -127,12 +127,16 @@ class MockInputRouter : public InputRouter {
bool HasPendingEvents() const override { return false; }
void SetDeviceScaleFactor(float device_scale_factor) override {}
void SetFrameTreeNodeId(int frameTreeNodeId) override {}
- cc::TouchAction AllowedTouchAction() override { return cc::kTouchActionAuto; }
+ base::Optional<cc::TouchAction> AllowedTouchAction() override {
+ return cc::kTouchActionAuto;
+ }
void SetForceEnableZoom(bool enabled) override {}
void BindHost(mojom::WidgetInputHandlerHostRequest request,
bool frame_handler) override {}
void StopFling() override {}
bool FlingCancellationIsDeferred() override { return false; }
+ void OnSetTouchAction(cc::TouchAction touch_action) override {}
+ void ForceSetTouchActionAuto() override {}
// IPC::Listener
bool OnMessageReceived(const IPC::Message& message) override {
@@ -157,7 +161,7 @@ class MockInputRouter : public InputRouter {
class TestFrameTokenMessageQueue : public FrameTokenMessageQueue {
public:
- TestFrameTokenMessageQueue(FrameTokenMessageQueue::Client* client)
+ explicit TestFrameTokenMessageQueue(FrameTokenMessageQueue::Client* client)
: FrameTokenMessageQueue(client) {}
~TestFrameTokenMessageQueue() override {}
@@ -180,7 +184,6 @@ class TestFrameTokenMessageQueue : public FrameTokenMessageQueue {
class MockRenderWidgetHost : public RenderWidgetHostImpl {
public:
-
// Allow poking at a few private members.
using RenderWidgetHostImpl::GetVisualProperties;
using RenderWidgetHostImpl::RendererExited;
@@ -241,6 +244,8 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
return static_cast<MockInputRouter*>(input_router_.get());
}
+ InputRouter* input_router() { return input_router_.get(); }
+
uint32_t processed_frame_messages_count() {
CHECK(frame_token_message_queue_);
return static_cast<TestFrameTokenMessageQueue*>(
@@ -308,7 +313,7 @@ class RenderWidgetHostProcess : public MockRenderProcessHost {
}
~RenderWidgetHostProcess() override {}
- bool HasConnection() const override { return true; }
+ bool IsInitializedAndNotDead() const override { return true; }
private:
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostProcess);
@@ -403,7 +408,7 @@ class TestView : public TestRenderWidgetHostView {
float GetBottomControlsHeight() const override {
return bottom_controls_height_;
}
- viz::LocalSurfaceId GetLocalSurfaceId() const override {
+ const viz::LocalSurfaceId& GetLocalSurfaceId() const override {
return local_surface_id_allocator_.GetCurrentLocalSurfaceId();
}
@@ -560,6 +565,19 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
return render_view_host_delegate_view_.get();
}
+ void SetZoomLevel(double zoom_level) { zoom_level_ = zoom_level; }
+
+ double GetPendingPageZoomLevel() const override { return zoom_level_; }
+
+ void FocusOwningWebContents(
+ RenderWidgetHostImpl* render_widget_host) override {
+ focus_owning_web_contents_call_count++;
+ }
+
+ int GetFocusOwningWebContentsCallCount() const {
+ return focus_owning_web_contents_call_count;
+ }
+
RenderViewHostDelegateView* GetDelegateView() override {
return mock_delegate_view();
}
@@ -586,7 +604,9 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
return handle_wheel_event_;
}
- void RendererUnresponsive(RenderWidgetHostImpl* render_widget_host) override {
+ void RendererUnresponsive(
+ RenderWidgetHostImpl* render_widget_host,
+ base::RepeatingClosure hang_monitor_restarter) override {
unresponsive_timer_fired_ = true;
}
@@ -615,45 +635,23 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
std::unique_ptr<MockRenderViewHostDelegateView>
render_view_host_delegate_view_;
-};
-enum WheelScrollingMode {
- kWheelScrollingModeNone,
- kWheelScrollLatching,
- kAsyncWheelEvents,
+ double zoom_level_ = 0;
+
+ int focus_owning_web_contents_call_count = 0;
};
// RenderWidgetHostTest --------------------------------------------------------
class RenderWidgetHostTest : public testing::Test {
public:
- RenderWidgetHostTest(
- WheelScrollingMode wheel_scrolling_mode = kWheelScrollLatching)
+ RenderWidgetHostTest()
: process_(nullptr),
handle_key_press_event_(false),
handle_mouse_event_(false),
- last_simulated_event_time_(ui::EventTimeForNow()),
- wheel_scroll_latching_enabled_(wheel_scrolling_mode !=
- kWheelScrollingModeNone) {
+ last_simulated_event_time_(ui::EventTimeForNow()) {
std::vector<base::StringPiece> features;
std::vector<base::StringPiece> disabled_features;
-
- switch (wheel_scrolling_mode) {
- case kWheelScrollingModeNone:
- disabled_features.push_back(
- features::kTouchpadAndWheelScrollLatching.name);
- disabled_features.push_back(features::kAsyncWheelEvents.name);
- break;
- case kWheelScrollLatching:
- features.push_back(features::kTouchpadAndWheelScrollLatching.name);
- disabled_features.push_back(features::kAsyncWheelEvents.name);
- break;
- case kAsyncWheelEvents:
- features.push_back(features::kTouchpadAndWheelScrollLatching.name);
- features.push_back(features::kAsyncWheelEvents.name);
- break;
- }
-
features.push_back(features::kVsyncAlignedInputEvents.name);
feature_list_.InitFromCommandLine(base::JoinString(features, ","),
@@ -668,6 +666,13 @@ class RenderWidgetHostTest : public testing::Test {
return handle_mouse_event_;
}
+ void RunLoopFor(base::TimeDelta duration) {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), duration);
+ run_loop.Run();
+ }
+
protected:
// testing::Test
void SetUp() override {
@@ -761,8 +766,6 @@ class RenderWidgetHostTest : public testing::Test {
virtual void ConfigureView(TestView* view) {
}
- int64_t GetLatencyComponentId() { return host_->GetLatencyComponentId(); }
-
base::TimeTicks GetNextSimulatedEventTime() {
last_simulated_event_time_ += simulated_event_time_delta_;
return last_simulated_event_time_;
@@ -802,16 +805,14 @@ class RenderWidgetHostTest : public testing::Test {
0, 0, dX, dY, modifiers, precise));
}
- void SimulateWheelEventPossiblyIncludingPhase(
- float dX,
- float dY,
- int modifiers,
- bool precise,
- WebMouseWheelEvent::Phase phase) {
+ void SimulateWheelEvent(float dX,
+ float dY,
+ int modifiers,
+ bool precise,
+ WebMouseWheelEvent::Phase phase) {
WebMouseWheelEvent wheel_event = SyntheticWebMouseWheelEventBuilder::Build(
0, 0, dX, dY, modifiers, precise);
- if (wheel_scroll_latching_enabled_)
- wheel_event.phase = phase;
+ wheel_event.phase = phase;
host_->ForwardWheelEvent(wheel_event);
}
@@ -826,17 +827,15 @@ class RenderWidgetHostTest : public testing::Test {
ui_latency);
}
- void SimulateWheelEventWithLatencyInfoAndPossiblyPhase(
- float dX,
- float dY,
- int modifiers,
- bool precise,
- const ui::LatencyInfo& ui_latency,
- WebMouseWheelEvent::Phase phase) {
+ void SimulateWheelEventWithLatencyInfo(float dX,
+ float dY,
+ int modifiers,
+ bool precise,
+ const ui::LatencyInfo& ui_latency,
+ WebMouseWheelEvent::Phase phase) {
WebMouseWheelEvent wheel_event = SyntheticWebMouseWheelEventBuilder::Build(
0, 0, dX, dY, modifiers, precise);
- if (wheel_scroll_latching_enabled_)
- wheel_event.phase = phase;
+ wheel_event.phase = phase;
host_->ForwardWheelEventWithLatencyInfo(wheel_event, ui_latency);
}
@@ -865,8 +864,7 @@ class RenderWidgetHostTest : public testing::Test {
WebGestureDevice sourceDevice,
const ui::LatencyInfo& ui_latency) {
host_->ForwardGestureEventWithLatencyInfo(
- SyntheticWebGestureEventBuilder::Build(type, sourceDevice),
- ui_latency);
+ SyntheticWebGestureEventBuilder::Build(type, sourceDevice), ui_latency);
}
// Set the timestamp for the touch-event.
@@ -905,10 +903,6 @@ class RenderWidgetHostTest : public testing::Test {
return reinterpret_cast<const WebInputEvent*>(data);
}
- void UnhandledWheelEvent();
- void HandleWheelEvent();
- void InputEventRWHLatencyComponent();
-
std::unique_ptr<TestBrowserContext> browser_context_;
RenderWidgetHostProcess* process_; // Deleted automatically by the widget.
std::unique_ptr<MockRenderWidgetHostDelegate> delegate_;
@@ -924,7 +918,6 @@ class RenderWidgetHostTest : public testing::Test {
renderer_compositor_frame_sink_;
std::unique_ptr<FakeRenderFrameMetadataObserver>
renderer_render_frame_metadata_observer_;
- bool wheel_scroll_latching_enabled_;
private:
SyntheticWebTouchEvent touch_event_;
@@ -936,20 +929,6 @@ class RenderWidgetHostTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest);
};
-class RenderWidgetHostWheelScrollLatchingDisabledTest
- : public RenderWidgetHostTest {
- public:
- RenderWidgetHostWheelScrollLatchingDisabledTest()
- : RenderWidgetHostTest(kWheelScrollingModeNone) {}
-};
-
-class RenderWidgetHostAsyncWheelEventsEnabledTest
- : public RenderWidgetHostTest {
- public:
- RenderWidgetHostAsyncWheelEventsEnabledTest()
- : RenderWidgetHostTest(kAsyncWheelEvents) {}
-};
-
// RenderWidgetHostWithSourceTest ----------------------------------------------
// This is for tests that are to be run for all source devices.
@@ -962,8 +941,26 @@ class RenderWidgetHostWithSourceTest
// -----------------------------------------------------------------------------
TEST_F(RenderWidgetHostTest, SynchronizeVisualProperties) {
+ // The initial zoom is 0 so host should not send a sync message
+ delegate_->SetZoomLevel(0);
+ EXPECT_FALSE(host_->SynchronizeVisualProperties());
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
+
+ // The zoom has changed so host should send out a sync message
+ process_->sink().ClearMessages();
+ double new_zoom_level = content::ZoomFactorToZoomLevel(0.25);
+ delegate_->SetZoomLevel(new_zoom_level);
+ EXPECT_TRUE(host_->SynchronizeVisualProperties());
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_NEAR(new_zoom_level, host_->old_visual_properties_->zoom_level, 0.01);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
+
// The initial bounds is the empty rect, so setting it to the same thing
// shouldn't send the resize message.
+ process_->sink().ClearMessages();
view_->SetBounds(gfx::Rect());
host_->SynchronizeVisualProperties();
EXPECT_FALSE(host_->visual_properties_ack_pending_);
@@ -1215,14 +1212,14 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) {
// Now unhide.
process_->sink().ClearMessages();
- host_->WasShown(ui::LatencyInfo());
+ host_->WasShown(false /* record_presentation_time */);
EXPECT_FALSE(host_->is_hidden_);
// It should have sent out a restored message with a request to paint.
const IPC::Message* restored = process_->sink().GetUniqueMessageMatching(
ViewMsg_WasShown::ID);
ASSERT_TRUE(restored);
- std::tuple<bool, ui::LatencyInfo> needs_repaint;
+ std::tuple<bool, base::TimeTicks> needs_repaint;
ViewMsg_WasShown::Read(restored, &needs_repaint);
EXPECT_TRUE(std::get<0>(needs_repaint));
}
@@ -1374,9 +1371,8 @@ TEST_F(RenderWidgetHostTest, RawKeyDownShortcutEvent) {
EXPECT_EQ(WebInputEvent::kKeyUp, delegate_->unhandled_keyboard_event_type());
}
-void RenderWidgetHostTest::UnhandledWheelEvent() {
- SimulateWheelEventPossiblyIncludingPhase(-5, 0, 0, true,
- WebMouseWheelEvent::kPhaseBegan);
+TEST_F(RenderWidgetHostTest, UnhandledWheelEvent) {
+ SimulateWheelEvent(-5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan);
MockWidgetInputHandler::MessageVector dispatched_events =
host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
@@ -1393,22 +1389,12 @@ void RenderWidgetHostTest::UnhandledWheelEvent() {
EXPECT_EQ(1, view_->unhandled_wheel_event_count());
EXPECT_EQ(-5, view_->unhandled_wheel_event().delta_x);
}
-TEST_F(RenderWidgetHostTest, UnhandledWheelEvent) {
- UnhandledWheelEvent();
-}
-TEST_F(RenderWidgetHostWheelScrollLatchingDisabledTest, UnhandledWheelEvent) {
- UnhandledWheelEvent();
-}
-TEST_F(RenderWidgetHostAsyncWheelEventsEnabledTest, UnhandledWheelEvent) {
- UnhandledWheelEvent();
-}
-void RenderWidgetHostTest::HandleWheelEvent() {
+TEST_F(RenderWidgetHostTest, HandleWheelEvent) {
// Indicate that we're going to handle this wheel event
delegate_->set_handle_wheel_event(true);
- SimulateWheelEventPossiblyIncludingPhase(-5, 0, 0, true,
- WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEvent(-5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan);
MockWidgetInputHandler::MessageVector dispatched_events =
host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
@@ -1427,14 +1413,26 @@ void RenderWidgetHostTest::HandleWheelEvent() {
// and that it suppressed the unhandled wheel event handler.
EXPECT_EQ(0, view_->unhandled_wheel_event_count());
}
-TEST_F(RenderWidgetHostTest, HandleWheelEvent) {
- HandleWheelEvent();
-}
-TEST_F(RenderWidgetHostWheelScrollLatchingDisabledTest, HandleWheelEvent) {
- HandleWheelEvent();
-}
-TEST_F(RenderWidgetHostAsyncWheelEventsEnabledTest, HandleWheelEvent) {
- HandleWheelEvent();
+
+TEST_F(RenderWidgetHostTest, EventsCausingFocus) {
+ SimulateMouseEvent(WebInputEvent::kMouseDown);
+ EXPECT_EQ(1, delegate_->GetFocusOwningWebContentsCallCount());
+
+ PressTouchPoint(0, 1);
+ SendTouchEvent();
+ EXPECT_EQ(2, delegate_->GetFocusOwningWebContentsCallCount());
+
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ EXPECT_EQ(2, delegate_->GetFocusOwningWebContentsCallCount());
+
+ SimulateGestureEvent(WebInputEvent::kGestureTapDown,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(2, delegate_->GetFocusOwningWebContentsCallCount());
+
+ SimulateGestureEvent(WebInputEvent::kGestureTap,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(3, delegate_->GetFocusOwningWebContentsCallCount());
}
TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) {
@@ -1458,62 +1456,53 @@ TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) {
// Test that the hang monitor timer expires properly if a new timer is started
// while one is in progress (see crbug.com/11007).
-TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) {
+TEST_F(RenderWidgetHostTest, DontPostponeInputEventAckTimeout) {
// Start with a short timeout.
- host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
+ host_->StartInputEventAckTimeout(TimeDelta::FromMilliseconds(10));
// Immediately try to add a long 30 second timeout.
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
- host_->StartHangMonitorTimeout(TimeDelta::FromSeconds(30));
+ host_->StartInputEventAckTimeout(TimeDelta::FromSeconds(30));
// Wait long enough for first timeout and see if it fired.
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMilliseconds(10));
- base::RunLoop().Run();
+ RunLoopFor(TimeDelta::FromMilliseconds(10));
EXPECT_TRUE(delegate_->unresponsive_timer_fired());
}
// Test that the hang monitor timer expires properly if it is started, stopped,
// and then started again.
-TEST_F(RenderWidgetHostTest, StopAndStartHangMonitorTimeout) {
+TEST_F(RenderWidgetHostTest, StopAndStartInputEventAckTimeout) {
// Start with a short timeout, then stop it.
- host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
- host_->StopHangMonitorTimeout();
+ host_->StartInputEventAckTimeout(TimeDelta::FromMilliseconds(10));
+ host_->StopInputEventAckTimeout();
// Start it again to ensure it still works.
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
- host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
+ host_->StartInputEventAckTimeout(TimeDelta::FromMilliseconds(10));
// Wait long enough for first timeout and see if it fired.
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMilliseconds(40));
- base::RunLoop().Run();
+ RunLoopFor(TimeDelta::FromMilliseconds(40));
EXPECT_TRUE(delegate_->unresponsive_timer_fired());
}
// Test that the hang monitor timer expires properly if it is started, then
// updated to a shorter duration.
-TEST_F(RenderWidgetHostTest, ShorterDelayHangMonitorTimeout) {
+TEST_F(RenderWidgetHostTest, ShorterDelayInputEventAckTimeout) {
// Start with a timeout.
- host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(100));
+ host_->StartInputEventAckTimeout(TimeDelta::FromMilliseconds(100));
// Start it again with shorter delay.
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
- host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(20));
+ host_->StartInputEventAckTimeout(TimeDelta::FromMilliseconds(20));
// Wait long enough for the second timeout and see if it fired.
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMilliseconds(25));
- base::RunLoop().Run();
+ RunLoopFor(TimeDelta::FromMilliseconds(25));
EXPECT_TRUE(delegate_->unresponsive_timer_fired());
}
// Test that the hang monitor timer is effectively disabled when the widget is
// hidden.
-TEST_F(RenderWidgetHostTest, HangMonitorTimeoutDisabledForInputWhenHidden) {
+TEST_F(RenderWidgetHostTest, InputEventAckTimeoutDisabledForInputWhenHidden) {
host_->set_hung_renderer_delay(base::TimeDelta::FromMicroseconds(1));
SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 10, 0, false);
@@ -1522,27 +1511,18 @@ TEST_F(RenderWidgetHostTest, HangMonitorTimeoutDisabledForInputWhenHidden) {
// The timeout should not fire.
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMicroseconds(2));
- base::RunLoop().Run();
+ RunLoopFor(TimeDelta::FromMicroseconds(2));
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
// The timeout should never reactivate while hidden.
SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 10, 0, false);
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMicroseconds(2));
- base::RunLoop().Run();
+ RunLoopFor(TimeDelta::FromMicroseconds(2));
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
// Showing the widget should restore the timeout, as the events have
// not yet been ack'ed.
- host_->WasShown(ui::LatencyInfo());
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMicroseconds(2));
- base::RunLoop().Run();
+ host_->WasShown(false /* record_presentation_time */);
+ RunLoopFor(TimeDelta::FromMicroseconds(2));
EXPECT_TRUE(delegate_->unresponsive_timer_fired());
}
@@ -1567,10 +1547,7 @@ TEST_F(RenderWidgetHostTest, MultipleInputEvents) {
dispatched_events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
// Wait long enough for first timeout and see if it fired.
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMicroseconds(20));
- base::RunLoop().Run();
+ RunLoopFor(TimeDelta::FromMicroseconds(20));
EXPECT_TRUE(delegate_->unresponsive_timer_fired());
}
@@ -1606,10 +1583,7 @@ TEST_F(RenderWidgetHostTest, NewContentRenderingTimeoutWithoutSurfaceSync) {
.Build();
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMicroseconds(20));
- base::RunLoop().Run();
+ RunLoopFor(TimeDelta::FromMicroseconds(20));
EXPECT_FALSE(host_->new_content_rendering_timeout_fired());
host_->reset_new_content_rendering_timeout_fired();
@@ -1623,10 +1597,7 @@ TEST_F(RenderWidgetHostTest, NewContentRenderingTimeoutWithoutSurfaceSync) {
.Build();
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMicroseconds(20));
- base::RunLoop().Run();
+ RunLoopFor(TimeDelta::FromMicroseconds(20));
EXPECT_TRUE(host_->new_content_rendering_timeout_fired());
host_->reset_new_content_rendering_timeout_fired();
@@ -1640,20 +1611,14 @@ TEST_F(RenderWidgetHostTest, NewContentRenderingTimeoutWithoutSurfaceSync) {
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
host_->DidNavigate(7);
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMicroseconds(20));
- base::RunLoop().Run();
+ RunLoopFor(TimeDelta::FromMicroseconds(20));
EXPECT_FALSE(host_->new_content_rendering_timeout_fired());
host_->reset_new_content_rendering_timeout_fired();
// Don't send any frames after the timer starts. The timer should fire.
host_->DidNavigate(20);
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TimeDelta::FromMicroseconds(20));
- base::RunLoop().Run();
+ RunLoopFor(TimeDelta::FromMicroseconds(20));
EXPECT_TRUE(host_->new_content_rendering_timeout_fired());
host_->reset_new_content_rendering_timeout_fired();
}
@@ -1817,7 +1782,6 @@ TEST_F(RenderWidgetHostTest, InputRouterReceivesHasTouchEventHandlers) {
void CheckLatencyInfoComponentInMessage(
MockWidgetInputHandler::MessageVector& dispatched_events,
- int64_t component_id,
WebInputEvent::Type expected_type) {
ASSERT_EQ(1u, dispatched_events.size());
ASSERT_TRUE(dispatched_events[0]->ToEvent());
@@ -1826,13 +1790,12 @@ void CheckLatencyInfoComponentInMessage(
expected_type);
EXPECT_TRUE(
dispatched_events[0]->ToEvent()->Event()->latency_info.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, component_id, nullptr));
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
dispatched_events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
}
void CheckLatencyInfoComponentInGestureScrollUpdate(
- MockWidgetInputHandler::MessageVector& dispatched_events,
- int64_t component_id) {
+ MockWidgetInputHandler::MessageVector& dispatched_events) {
ASSERT_EQ(2u, dispatched_events.size());
ASSERT_TRUE(dispatched_events[0]->ToEvent());
ASSERT_TRUE(dispatched_events[1]->ToEvent());
@@ -1843,7 +1806,7 @@ void CheckLatencyInfoComponentInGestureScrollUpdate(
dispatched_events[1]->ToEvent()->Event()->web_event->GetType());
EXPECT_TRUE(
dispatched_events[1]->ToEvent()->Event()->latency_info.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, component_id, nullptr));
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, nullptr));
dispatched_events[1]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
}
@@ -1851,30 +1814,29 @@ void CheckLatencyInfoComponentInGestureScrollUpdate(
// or ForwardXXXEventWithLatencyInfo(), LatencyInfo component
// ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT will always present in the
// event's LatencyInfo.
-void RenderWidgetHostTest::InputEventRWHLatencyComponent() {
+TEST_F(RenderWidgetHostTest, InputEventRWHLatencyComponent) {
host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
// Tests RWHI::ForwardWheelEvent().
- SimulateWheelEventPossiblyIncludingPhase(-5, 0, 0, true,
- WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEvent(-5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan);
MockWidgetInputHandler::MessageVector dispatched_events =
host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ CheckLatencyInfoComponentInMessage(dispatched_events,
WebInputEvent::kMouseWheel);
// Tests RWHI::ForwardWheelEventWithLatencyInfo().
- SimulateWheelEventWithLatencyInfoAndPossiblyPhase(
- -5, 0, 0, true, ui::LatencyInfo(), WebMouseWheelEvent::kPhaseChanged);
+ SimulateWheelEventWithLatencyInfo(-5, 0, 0, true, ui::LatencyInfo(),
+ WebMouseWheelEvent::kPhaseChanged);
dispatched_events =
host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ CheckLatencyInfoComponentInMessage(dispatched_events,
WebInputEvent::kMouseWheel);
// Tests RWHI::ForwardMouseEvent().
SimulateMouseEvent(WebInputEvent::kMouseMove);
dispatched_events =
host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ CheckLatencyInfoComponentInMessage(dispatched_events,
WebInputEvent::kMouseMove);
// Tests RWHI::ForwardMouseEventWithLatencyInfo().
@@ -1882,15 +1844,23 @@ void RenderWidgetHostTest::InputEventRWHLatencyComponent() {
ui::LatencyInfo());
dispatched_events =
host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ CheckLatencyInfoComponentInMessage(dispatched_events,
WebInputEvent::kMouseMove);
// Tests RWHI::ForwardGestureEvent().
+ PressTouchPoint(0, 1);
+ SendTouchEvent();
+ host_->input_router()->OnSetTouchAction(cc::kTouchActionAuto);
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
+ CheckLatencyInfoComponentInMessage(dispatched_events,
+ WebInputEvent::kTouchStart);
+
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
dispatched_events =
host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ CheckLatencyInfoComponentInMessage(dispatched_events,
WebInputEvent::kGestureScrollBegin);
// Tests RWHI::ForwardGestureEventWithLatencyInfo().
@@ -1899,28 +1869,21 @@ void RenderWidgetHostTest::InputEventRWHLatencyComponent() {
ui::LatencyInfo());
dispatched_events =
host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- CheckLatencyInfoComponentInGestureScrollUpdate(dispatched_events,
- GetLatencyComponentId());
+ CheckLatencyInfoComponentInGestureScrollUpdate(dispatched_events);
+
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
// Tests RWHI::ForwardTouchEventWithLatencyInfo().
PressTouchPoint(0, 1);
SendTouchEvent();
dispatched_events =
host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ CheckLatencyInfoComponentInMessage(dispatched_events,
WebInputEvent::kTouchStart);
}
-TEST_F(RenderWidgetHostTest, InputEventRWHLatencyComponent) {
- InputEventRWHLatencyComponent();
-}
-TEST_F(RenderWidgetHostWheelScrollLatchingDisabledTest,
- InputEventRWHLatencyComponent) {
- InputEventRWHLatencyComponent();
-}
-TEST_F(RenderWidgetHostAsyncWheelEventsEnabledTest,
- InputEventRWHLatencyComponent) {
- InputEventRWHLatencyComponent();
-}
TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) {
// RendererExited will delete the view.
@@ -1935,7 +1898,7 @@ TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) {
TEST_F(RenderWidgetHostTest, RendererExitedResetsIsHidden) {
// RendererExited will delete the view.
host_->SetView(new TestView(host_.get()));
- host_->WasShown(ui::LatencyInfo());
+ host_->WasShown(false /* record_presentation_time */);
ASSERT_FALSE(host_->is_hidden());
host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
@@ -2087,6 +2050,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_MessageThenFrame) {
auto frame = viz::CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetFrameToken(frame_token)
+ .SetSendFrameTokenToEmbedder(true)
.Build();
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
@@ -2109,6 +2073,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_FrameThenMessage) {
auto frame = viz::CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetFrameToken(frame_token)
+ .SetSendFrameTokenToEmbedder(true)
.Build();
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
@@ -2149,6 +2114,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleMessagesThenTokens) {
auto frame = viz::CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetFrameToken(frame_token1)
+ .SetSendFrameTokenToEmbedder(true)
.Build();
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
@@ -2158,6 +2124,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleMessagesThenTokens) {
frame = viz::CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetFrameToken(frame_token2)
+ .SetSendFrameTokenToEmbedder(true)
.Build();
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
@@ -2183,6 +2150,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleTokensThenMessages) {
auto frame = viz::CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetFrameToken(frame_token1)
+ .SetSendFrameTokenToEmbedder(true)
.Build();
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
@@ -2192,6 +2160,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleTokensThenMessages) {
frame = viz::CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetFrameToken(frame_token2)
+ .SetSendFrameTokenToEmbedder(true)
.Build();
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
@@ -2237,6 +2206,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_DroppedFrame) {
auto frame = viz::CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetFrameToken(frame_token2)
+ .SetSendFrameTokenToEmbedder(true)
.Build();
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
@@ -2282,6 +2252,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_RendererCrash) {
auto frame = viz::CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetFrameToken(frame_token2)
+ .SetSendFrameTokenToEmbedder(true)
.Build();
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
@@ -2302,6 +2273,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_RendererCrash) {
frame = viz::CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetFrameToken(frame_token3)
+ .SetSendFrameTokenToEmbedder(true)
.Build();
host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
base::nullopt, 0);
@@ -2366,20 +2338,20 @@ TEST_F(RenderWidgetHostTest, RenderWidgetSurfaceProperties) {
TEST_F(RenderWidgetHostTest, NavigateInBackgroundShowsBlank) {
// When visible, navigation does not immediately call into
// ClearDisplayedGraphics.
- host_->WasShown(ui::LatencyInfo());
+ host_->WasShown(false /* record_presentation_time */);
host_->DidNavigate(5);
EXPECT_FALSE(host_->new_content_rendering_timeout_fired());
// Hide then show. ClearDisplayedGraphics must be called.
host_->WasHidden();
- host_->WasShown(ui::LatencyInfo());
+ host_->WasShown(false /* record_presentation_time */);
EXPECT_TRUE(host_->new_content_rendering_timeout_fired());
host_->reset_new_content_rendering_timeout_fired();
// Hide, navigate, then show. ClearDisplayedGraphics must be called.
host_->WasHidden();
host_->DidNavigate(6);
- host_->WasShown(ui::LatencyInfo());
+ host_->WasShown(false /* record_presentation_time */);
EXPECT_TRUE(host_->new_content_rendering_timeout_fired());
}
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 c0cefeddd6b..f56a9746443 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
@@ -10,6 +10,7 @@
#include "base/android/build_info.h"
#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
@@ -26,6 +27,8 @@
#include "cc/trees/layer_tree_host.h"
#include "components/viz/common/features.h"
#include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/common/surfaces/frame_sink_id_allocator.h"
+#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_hittest.h"
@@ -179,7 +182,6 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
stylus_text_selector_(this),
using_browser_compositor_(CompositorImpl::IsInitialized()),
synchronous_compositor_client_(nullptr),
- frame_evictor_(new viz::FrameEvictor(this)),
observing_root_window_(false),
prev_top_shown_pix_(0.f),
prev_top_controls_translate_(0.f),
@@ -198,7 +200,12 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
if (using_browser_compositor_) {
delegated_frame_host_ = std::make_unique<ui::DelegatedFrameHostAndroid>(
&view_, CompositorImpl::GetHostFrameSinkManager(), this,
- host()->GetFrameSinkId());
+ host()->GetFrameSinkId(), features::IsSurfaceSynchronizationEnabled());
+ if (is_showing_) {
+ delegated_frame_host_->WasShown(
+ local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
+ GetCompositorViewportPixelSize());
+ }
// Let the page-level input event router know about our frame sink ID
// for surface-based hit testing.
@@ -223,7 +230,6 @@ RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
UpdateNativeViewTree(nullptr);
view_.set_event_handler(nullptr);
DCHECK(!ime_adapter_android_);
- DCHECK(ack_callbacks_.empty());
DCHECK(!delegated_frame_host_);
}
@@ -262,10 +268,20 @@ void RenderWidgetHostViewAndroid::InitAsFullscreen(
NOTIMPLEMENTED();
}
-bool RenderWidgetHostViewAndroid::SynchronizeVisualProperties() {
+bool RenderWidgetHostViewAndroid::SynchronizeVisualProperties(
+ const cc::DeadlinePolicy& deadline_policy,
+ const base::Optional<viz::LocalSurfaceId>&
+ child_allocated_local_surface_id) {
+ if (child_allocated_local_surface_id) {
+ local_surface_id_allocator_.UpdateFromChild(
+ *child_allocated_local_surface_id);
+ } else {
+ local_surface_id_allocator_.GenerateId();
+ }
if (delegated_frame_host_) {
- delegated_frame_host_->SynchronizeVisualProperties(
- GetCompositorViewportPixelSize());
+ delegated_frame_host_->EmbedSurface(
+ local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
+ GetCompositorViewportPixelSize(), deadline_policy);
// TODO(ericrk): This can be removed once surface synchronization is
// enabled. https://crbug.com/835102
@@ -287,18 +303,16 @@ void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
}
bool RenderWidgetHostViewAndroid::HasValidFrame() const {
+ if (!delegated_frame_host_)
+ return false;
+
if (!view_.parent())
return false;
if (current_surface_size_.IsEmpty())
return false;
- // This tell us whether a valid frame has arrived or not.
- if (!frame_evictor_->HasFrame())
- return false;
- DCHECK(!delegated_frame_host_ ||
- delegated_frame_host_->HasDelegatedContent());
- return true;
+ return delegated_frame_host_->HasSavedFrame();
}
gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
@@ -321,6 +335,88 @@ void RenderWidgetHostViewAndroid::LostFocus() {
LostFocusInternal();
}
+void RenderWidgetHostViewAndroid::OnRenderFrameMetadataChangedBeforeActivation(
+ const cc::RenderFrameMetadata& metadata) {
+ if (!features::IsSurfaceSynchronizationEnabled())
+ return;
+
+ bool is_mobile_optimized = IsMobileOptimizedFrame(
+ metadata.page_scale_factor, metadata.min_page_scale_factor,
+ metadata.max_page_scale_factor, metadata.scrollable_viewport_size,
+ metadata.root_layer_size);
+
+ gesture_provider_.SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
+
+ float dip_scale = view_.GetDipScale();
+ gfx::SizeF root_layer_size_dip = metadata.root_layer_size;
+ gfx::SizeF scrollable_viewport_size_dip = metadata.scrollable_viewport_size;
+ gfx::Vector2dF root_scroll_offset_dip =
+ metadata.root_scroll_offset.value_or(gfx::Vector2dF());
+ if (IsUseZoomForDSFEnabled()) {
+ float pix_to_dip = 1 / dip_scale;
+ root_layer_size_dip.Scale(pix_to_dip);
+ scrollable_viewport_size_dip.Scale(pix_to_dip);
+ root_scroll_offset_dip.Scale(pix_to_dip);
+ }
+
+ float to_pix = IsUseZoomForDSFEnabled() ? 1.f : dip_scale;
+ // Note that the height of browser control is not affected by page scale
+ // factor. Thus, |top_content_offset| in CSS pixels is also in DIPs.
+ float top_content_offset =
+ metadata.top_controls_height * metadata.top_controls_shown_ratio;
+ float top_shown_pix = top_content_offset * to_pix;
+
+ if (ime_adapter_android_) {
+ ime_adapter_android_->UpdateFrameInfo(metadata.selection.start, dip_scale,
+ top_shown_pix);
+ }
+
+ auto* wcax = GetWebContentsAccessibilityAndroid();
+ if (wcax)
+ wcax->UpdateFrameInfo(metadata.page_scale_factor);
+
+ if (!gesture_listener_manager_)
+ return;
+
+ UpdateTouchSelectionController(metadata.selection, metadata.page_scale_factor,
+ metadata.top_controls_height,
+ metadata.top_controls_shown_ratio,
+ scrollable_viewport_size_dip);
+
+ // ViewAndroid::content_offset() must be in dip.
+ float top_content_offset_dip = IsUseZoomForDSFEnabled()
+ ? top_content_offset / dip_scale
+ : top_content_offset;
+ view_.UpdateFrameInfo({scrollable_viewport_size_dip, top_content_offset});
+ bool controls_changed = UpdateControls(
+ view_.GetDipScale(), metadata.top_controls_height,
+ metadata.top_controls_shown_ratio, metadata.bottom_controls_height,
+ metadata.bottom_controls_shown_ratio);
+
+ SetContentBackgroundColor(metadata.has_transparent_background
+ ? SK_ColorTRANSPARENT
+ : metadata.root_background_color);
+
+ if (overscroll_controller_) {
+ overscroll_controller_->OnFrameMetadataUpdated(
+ metadata.page_scale_factor, metadata.device_scale_factor,
+ metadata.scrollable_viewport_size, metadata.root_layer_size,
+ metadata.root_scroll_offset.value_or(gfx::Vector2dF()),
+ metadata.root_overflow_y_hidden);
+ }
+
+ // All offsets and sizes except |top_shown_pix| are in dip.
+ gesture_listener_manager_->UpdateScrollInfo(
+ root_scroll_offset_dip, metadata.page_scale_factor,
+ metadata.min_page_scale_factor, metadata.max_page_scale_factor,
+ root_layer_size_dip, scrollable_viewport_size_dip, top_content_offset_dip,
+ top_shown_pix, controls_changed);
+
+ page_scale_ = metadata.page_scale_factor;
+ min_page_scale_ = metadata.min_page_scale_factor;
+ max_page_scale_ = metadata.max_page_scale_factor;
+}
+
void RenderWidgetHostViewAndroid::Focus() {
if (view_.HasFocus())
GotFocus();
@@ -465,8 +561,7 @@ void RenderWidgetHostViewAndroid::OnUpdateTextInputStateCalled(
? *GetTextInputManager()->GetTextInputState()
: TextInputState();
- if (!ime_adapter_android_ || (is_in_vr_ && !base::FeatureList::IsEnabled(
- features::kVrWebInputEditing)))
+ if (!ime_adapter_android_)
return;
ime_adapter_android_->UpdateState(state);
@@ -502,11 +597,6 @@ void RenderWidgetHostViewAndroid::OnTextSelectionChanged(
RenderWidgetHostViewBase* updated_view) {
DCHECK_EQ(text_input_manager_, text_input_manager);
- // TODO(asimjour): remove the flag and fix text selection popup for
- // virtual reality mode.
- if (is_in_vr_)
- return;
-
if (!selection_popup_controller_)
return;
@@ -672,7 +762,7 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent(
return false;
ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT);
if (ShouldRouteEvents()) {
host()->delegate()->GetInputEventRouter()->RouteTouchEvent(this, &web_event,
latency_info);
@@ -699,8 +789,7 @@ bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
int RenderWidgetHostViewAndroid::GetTouchHandleHeight() {
if (!touch_selection_controller_)
return 0;
- return static_cast<int>(
- touch_selection_controller_->GetStartHandleRect().height());
+ return static_cast<int>(touch_selection_controller_->GetTouchHandleHeight());
}
void RenderWidgetHostViewAndroid::ResetGestureDetection() {
@@ -717,7 +806,7 @@ void RenderWidgetHostViewAndroid::ResetGestureDetection() {
if (gesture_provider_.OnTouchEvent(*cancel_event).succeeded) {
bool causes_scrolling = false;
ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT);
blink::WebTouchEvent web_event = ui::CreateWebTouchEventFromMotionEvent(
*cancel_event, causes_scrolling /* may_cause_scrolling */,
false /* hovering */);
@@ -818,7 +907,8 @@ void RenderWidgetHostViewAndroid::CopyFromSurface(
void RenderWidgetHostViewAndroid::EnsureSurfaceSynchronizedForLayoutTest() {
++latest_capture_sequence_number_;
- SynchronizeVisualProperties();
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseInfiniteDeadline(),
+ base::nullopt);
}
uint32_t RenderWidgetHostViewAndroid::GetCaptureSequenceNumber() const {
@@ -849,48 +939,22 @@ bool RenderWidgetHostViewAndroid::ShouldRouteEvents() const {
host()->delegate()->GetInputEventRouter();
}
-void RenderWidgetHostViewAndroid::SendReclaimCompositorResources(
- bool is_swap_ack) {
- DCHECK(host());
- if (is_swap_ack) {
- renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(
- surface_returned_resources_);
- } else {
- renderer_compositor_frame_sink_->ReclaimResources(
- surface_returned_resources_);
- }
- surface_returned_resources_.clear();
-}
-
-void RenderWidgetHostViewAndroid::DidReceiveCompositorFrameAck() {
- RunAckCallbacks();
+void RenderWidgetHostViewAndroid::DidReceiveCompositorFrameAck(
+ const std::vector<viz::ReturnedResource>& resources) {
+ renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
}
void RenderWidgetHostViewAndroid::DidPresentCompositorFrame(
uint32_t presentation_token,
- base::TimeTicks time,
- base::TimeDelta refresh,
- uint32_t flags) {
- DCHECK(using_browser_compositor_);
- renderer_compositor_frame_sink_->DidPresentCompositorFrame(
- presentation_token, time, refresh, flags);
-}
-
-void RenderWidgetHostViewAndroid::DidDiscardCompositorFrame(
- uint32_t presentation_token) {
+ const gfx::PresentationFeedback& feedback) {
DCHECK(using_browser_compositor_);
- renderer_compositor_frame_sink_->DidDiscardCompositorFrame(
- presentation_token);
+ renderer_compositor_frame_sink_->DidPresentCompositorFrame(presentation_token,
+ feedback);
}
void RenderWidgetHostViewAndroid::ReclaimResources(
const std::vector<viz::ReturnedResource>& resources) {
- if (resources.empty())
- return;
- std::copy(resources.begin(), resources.end(),
- std::back_inserter(surface_returned_resources_));
- if (ack_callbacks_.empty())
- SendReclaimCompositorResources(false /* is_swap_ack */);
+ renderer_compositor_frame_sink_->ReclaimResources(resources);
}
void RenderWidgetHostViewAndroid::OnFrameTokenChanged(uint32_t frame_token) {
@@ -913,9 +977,6 @@ void RenderWidgetHostViewAndroid::DidCreateNewRendererCompositorFrameSink(
}
delegated_frame_host_->CompositorFrameSinkChanged();
renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
- // Accumulated resources belong to the old RendererCompositorFrameSink and
- // should not be returned.
- surface_returned_resources_.clear();
}
void RenderWidgetHostViewAndroid::EvictFrameIfNecessary() {
@@ -954,50 +1015,14 @@ void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
viz::CompositorFrameMetadata metadata = frame.metadata.Clone();
- bool has_content = !current_surface_size_.IsEmpty();
-
- base::Closure ack_callback =
- base::Bind(&RenderWidgetHostViewAndroid::SendReclaimCompositorResources,
- weak_ptr_factory_.GetWeakPtr(), true /* is_swap_ack */);
-
- ack_callbacks_.push(ack_callback);
-
- viz::BeginFrameAck ack = frame.metadata.begin_frame_ack;
- if (!has_content) {
- DestroyDelegatedContent();
-
- ack.has_damage = false;
- OnDidNotProduceFrame(ack);
- } else {
- delegated_frame_host_->SubmitCompositorFrame(
- local_surface_id, std::move(frame), std::move(hit_test_region_list));
- frame_evictor_->SwappedFrame(!host()->is_hidden());
- AcknowledgeBeginFrame(ack);
- }
-
- if (host()->is_hidden())
- RunAckCallbacks();
+ delegated_frame_host_->SubmitCompositorFrame(
+ local_surface_id, std::move(frame), std::move(hit_test_region_list));
// As the metadata update may trigger view invalidation, always call it after
// any potential compositor scheduling.
OnFrameMetadataUpdated(std::move(metadata), is_transparent);
}
-void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
- if (!delegated_frame_host_)
- return;
-
- DCHECK(delegated_frame_host_->HasDelegatedContent() ==
- frame_evictor_->HasFrame());
-
- delegated_frame_host_->DestroyDelegatedContent();
-
- if (frame_evictor_->HasFrame())
- frame_evictor_->DiscardedFrame();
-
- current_surface_size_.SetSize(0, 0);
-}
-
void RenderWidgetHostViewAndroid::OnDidNotProduceFrame(
const viz::BeginFrameAck& ack) {
if (!delegated_frame_host_) {
@@ -1008,48 +1033,43 @@ void RenderWidgetHostViewAndroid::OnDidNotProduceFrame(
}
delegated_frame_host_->DidNotProduceFrame(ack);
- AcknowledgeBeginFrame(ack);
-}
-
-void RenderWidgetHostViewAndroid::AcknowledgeBeginFrame(
- const viz::BeginFrameAck& ack) {
- // AcknowledgeBeginFrame is not called for the synchronous compositor path.
- if (begin_frame_source_)
- begin_frame_source_->DidFinishFrame(this);
}
void RenderWidgetHostViewAndroid::ClearCompositorFrame() {
- DestroyDelegatedContent();
+ EvictDelegatedFrame();
}
bool RenderWidgetHostViewAndroid::RequestRepaintForTesting() {
- return SynchronizeVisualProperties();
+ return SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+ base::nullopt);
}
void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
- viz::CompositorFrameMetadata frame_metadata) {
+ viz::CompositorFrameMetadata metadata) {
if (!view_.parent())
return;
- bool is_mobile_optimized = IsMobileOptimizedFrame(frame_metadata);
+ bool is_mobile_optimized = IsMobileOptimizedFrame(
+ metadata.page_scale_factor, metadata.min_page_scale_factor,
+ metadata.max_page_scale_factor, metadata.scrollable_viewport_size,
+ metadata.root_layer_size);
if (host() && host()->input_router()) {
host()->input_router()->NotifySiteIsMobileOptimized(is_mobile_optimized);
}
- if (host() && frame_metadata.frame_token)
- host()->DidProcessFrame(frame_metadata.frame_token);
+ if (host() && metadata.frame_token)
+ host()->DidProcessFrame(metadata.frame_token);
// This is a subset of OnSwapCompositorFrame() used in the synchronous
// compositor flow.
- OnFrameMetadataUpdated(frame_metadata.Clone(), false);
+ OnFrameMetadataUpdated(metadata.Clone(), false);
// DevTools ScreenCast support for Android WebView.
RenderFrameHost* frame_host = RenderViewHost::From(host())->GetMainFrame();
if (frame_host) {
RenderFrameDevToolsAgentHost::SignalSynchronousSwapCompositorFrame(
- frame_host,
- std::move(frame_metadata));
+ frame_host, std::move(metadata));
}
}
@@ -1195,16 +1215,22 @@ RenderWidgetHostViewAndroid::GetWebContentsAccessibilityAndroid() const {
}
void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
- const viz::CompositorFrameMetadata& frame_metadata,
+ const viz::CompositorFrameMetadata& metadata,
bool is_transparent) {
- bool is_mobile_optimized = IsMobileOptimizedFrame(frame_metadata);
+ if (features::IsSurfaceSynchronizationEnabled())
+ return;
+
+ bool is_mobile_optimized = IsMobileOptimizedFrame(
+ metadata.page_scale_factor, metadata.min_page_scale_factor,
+ metadata.max_page_scale_factor, metadata.scrollable_viewport_size,
+ metadata.root_layer_size);
+
gesture_provider_.SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
float dip_scale = view_.GetDipScale();
- gfx::SizeF root_layer_size_dip = frame_metadata.root_layer_size;
- gfx::SizeF scrollable_viewport_size_dip =
- frame_metadata.scrollable_viewport_size;
- gfx::Vector2dF root_scroll_offset_dip = frame_metadata.root_scroll_offset;
+ gfx::SizeF root_layer_size_dip = metadata.root_layer_size;
+ gfx::SizeF scrollable_viewport_size_dip = metadata.scrollable_viewport_size;
+ gfx::Vector2dF root_scroll_offset_dip = metadata.root_scroll_offset;
if (IsUseZoomForDSFEnabled()) {
float pix_to_dip = 1 / dip_scale;
root_layer_size_dip.Scale(pix_to_dip);
@@ -1215,76 +1241,83 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
float to_pix = IsUseZoomForDSFEnabled() ? 1.f : dip_scale;
// Note that the height of browser control is not affected by page scale
// factor. Thus, |top_content_offset| in CSS pixels is also in DIPs.
- float top_content_offset = frame_metadata.top_controls_height *
- frame_metadata.top_controls_shown_ratio;
+ float top_content_offset =
+ metadata.top_controls_height * metadata.top_controls_shown_ratio;
float top_shown_pix = top_content_offset * to_pix;
- if (ime_adapter_android_)
- ime_adapter_android_->UpdateFrameInfo(frame_metadata.selection.start,
- dip_scale, top_shown_pix);
+ if (ime_adapter_android_) {
+ ime_adapter_android_->UpdateFrameInfo(metadata.selection.start, dip_scale,
+ top_shown_pix);
+ }
auto* wcax = GetWebContentsAccessibilityAndroid();
if (wcax)
- wcax->UpdateFrameInfo(frame_metadata.page_scale_factor);
+ wcax->UpdateFrameInfo(metadata.page_scale_factor);
if (!gesture_listener_manager_)
return;
- if (overscroll_controller_)
- overscroll_controller_->OnFrameMetadataUpdated(frame_metadata);
-
- if (touch_selection_controller_) {
- DCHECK(touch_selection_controller_client_manager_);
- touch_selection_controller_client_manager_->UpdateClientSelectionBounds(
- frame_metadata.selection.start, frame_metadata.selection.end, this,
- nullptr);
- touch_selection_controller_client_manager_->SetPageScaleFactor(
- frame_metadata.page_scale_factor);
-
- // Set parameters for adaptive handle orientation.
- gfx::SizeF viewport_size(scrollable_viewport_size_dip);
- viewport_size.Scale(frame_metadata.page_scale_factor);
- gfx::RectF viewport_rect(0.0f, frame_metadata.top_controls_height *
- frame_metadata.top_controls_shown_ratio,
- viewport_size.width(), viewport_size.height());
- touch_selection_controller_->OnViewportChanged(viewport_rect);
- }
-
- SetContentBackgroundColor(is_transparent
- ? SK_ColorTRANSPARENT
- : frame_metadata.root_background_color);
+ if (overscroll_controller_) {
+ overscroll_controller_->OnFrameMetadataUpdated(
+ metadata.page_scale_factor, metadata.device_scale_factor,
+ metadata.scrollable_viewport_size, metadata.root_layer_size,
+ metadata.root_scroll_offset, metadata.root_overflow_y_hidden);
+ }
- // ViewAndroid::content_offset() must be in CSS scale
+ UpdateTouchSelectionController(metadata.selection, metadata.page_scale_factor,
+ metadata.top_controls_height,
+ metadata.top_controls_shown_ratio,
+ scrollable_viewport_size_dip);
+ // ViewAndroid::content_offset() must be in dip
float top_content_offset_dip = IsUseZoomForDSFEnabled()
? top_content_offset / dip_scale
: top_content_offset;
- view_.UpdateFrameInfo({scrollable_viewport_size_dip, top_content_offset});
- bool controls_changed =
- features::IsSurfaceSynchronizationEnabled()
- ? false
- : UpdateControls(view_.GetDipScale(),
- frame_metadata.top_controls_height,
- frame_metadata.top_controls_shown_ratio,
- frame_metadata.bottom_controls_height,
- frame_metadata.bottom_controls_shown_ratio);
-
- page_scale_ = frame_metadata.page_scale_factor;
- min_page_scale_ = frame_metadata.min_page_scale_factor;
- max_page_scale_ = frame_metadata.max_page_scale_factor;
-
- // All offsets and sizes except |top_shown_pix| are in CSS pixels.
- // TODO(fsamuel): This needs to be synchronized with RenderFrameMetadata when
- // surface synchronization is enabled.
+ view_.UpdateFrameInfo({scrollable_viewport_size_dip, top_content_offset_dip});
+ bool controls_changed = UpdateControls(
+ view_.GetDipScale(), metadata.top_controls_height,
+ metadata.top_controls_shown_ratio, metadata.bottom_controls_height,
+ metadata.bottom_controls_shown_ratio);
+
+ // All offsets and sizes except |top_shown_pix| are in dip.
gesture_listener_manager_->UpdateScrollInfo(
- root_scroll_offset_dip, frame_metadata.page_scale_factor,
- frame_metadata.min_page_scale_factor,
- frame_metadata.max_page_scale_factor, root_layer_size_dip,
- scrollable_viewport_size_dip, top_content_offset_dip, top_shown_pix,
- controls_changed);
+ root_scroll_offset_dip, metadata.page_scale_factor,
+ metadata.min_page_scale_factor, metadata.max_page_scale_factor,
+ root_layer_size_dip, scrollable_viewport_size_dip, top_content_offset_dip,
+ top_shown_pix, controls_changed);
+
+ SetContentBackgroundColor(is_transparent ? SK_ColorTRANSPARENT
+ : metadata.root_background_color);
+
+ page_scale_ = metadata.page_scale_factor;
+ min_page_scale_ = metadata.min_page_scale_factor;
+ max_page_scale_ = metadata.max_page_scale_factor;
EvictFrameIfNecessary();
}
+void RenderWidgetHostViewAndroid::UpdateTouchSelectionController(
+ const viz::Selection<gfx::SelectionBound>& selection,
+ float page_scale_factor,
+ float top_controls_height,
+ float top_controls_shown_ratio,
+ const gfx::SizeF& scrollable_viewport_size_dip) {
+ if (!touch_selection_controller_)
+ return;
+
+ DCHECK(touch_selection_controller_client_manager_);
+ touch_selection_controller_client_manager_->UpdateClientSelectionBounds(
+ selection.start, selection.end, this, nullptr);
+ touch_selection_controller_client_manager_->SetPageScaleFactor(
+ page_scale_factor);
+
+ // Set parameters for adaptive handle orientation.
+ gfx::SizeF viewport_size(scrollable_viewport_size_dip);
+ viewport_size.Scale(page_scale_factor);
+ gfx::RectF viewport_rect(0.0f, top_controls_height * top_controls_shown_ratio,
+ viewport_size.width(), viewport_size.height());
+ touch_selection_controller_->OnViewportChanged(viewport_rect);
+}
+
bool RenderWidgetHostViewAndroid::UpdateControls(
float dip_scale,
float top_controls_height,
@@ -1322,16 +1355,8 @@ bool RenderWidgetHostViewAndroid::UpdateControls(
void RenderWidgetHostViewAndroid::OnDidUpdateVisualPropertiesComplete(
const cc::RenderFrameMetadata& metadata) {
- if (delegated_frame_host_->GetLocalSurfaceIdAllocator()->UpdateFromChild(
- metadata.local_surface_id.value_or(viz::LocalSurfaceId()))) {
- // A synchronization event was initiated by the renderer so let's updated
- // the top/bottom bar controls now.
- UpdateControls(view_.GetDipScale(), metadata.top_controls_height,
- metadata.top_controls_shown_ratio,
- metadata.bottom_controls_height,
- metadata.bottom_controls_shown_ratio);
- }
- host()->SynchronizeVisualProperties();
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+ metadata.local_surface_id);
}
void RenderWidgetHostViewAndroid::ShowInternal() {
@@ -1344,12 +1369,29 @@ void RenderWidgetHostViewAndroid::ShowInternal() {
view_.GetLayer()->SetHideLayerAndSubtree(false);
- frame_evictor_->SetVisible(true);
-
if (overscroll_controller_)
overscroll_controller_->Enable();
- host()->WasShown(ui::LatencyInfo());
+ if (delegated_frame_host_ &&
+ delegated_frame_host_->IsPrimarySurfaceEvicted()) {
+ ui::WindowAndroidCompositor* compositor =
+ view_.GetWindowAndroid() ? view_.GetWindowAndroid()->GetCompositor()
+ : nullptr;
+ SynchronizeVisualProperties(
+ compositor && compositor->IsDrawingFirstVisibleFrame()
+ ? cc::DeadlinePolicy::UseSpecifiedDeadline(
+ ui::DelegatedFrameHostAndroid::FirstFrameTimeoutFrames())
+ : cc::DeadlinePolicy::UseDefaultDeadline(),
+ base::nullopt);
+ }
+
+ host()->WasShown(false /* record_presentation_time */);
+
+ if (delegated_frame_host_) {
+ delegated_frame_host_->WasShown(
+ local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
+ GetCompositorViewportPixelSize());
+ }
if (view_.parent() && view_.GetWindowAndroid()) {
StartObservingRootWindow();
@@ -1373,7 +1415,8 @@ void RenderWidgetHostViewAndroid::HideInternal() {
if (hide_frontbuffer) {
view_.GetLayer()->SetHideLayerAndSubtree(true);
- frame_evictor_->SetVisible(false);
+ if (delegated_frame_host_)
+ delegated_frame_host_->WasHidden();
}
if (stop_observing_root_window) {
@@ -1387,8 +1430,6 @@ void RenderWidgetHostViewAndroid::HideInternal() {
if (overscroll_controller_)
overscroll_controller_->Disable();
- RunAckCallbacks();
-
// Inform the renderer that we are being hidden so it can reduce its resource
// utilization.
host()->WasHidden();
@@ -1509,10 +1550,6 @@ void RenderWidgetHostViewAndroid::RequestDisallowInterceptTouchEvent() {
view_.RequestDisallowInterceptTouchEvent();
}
-void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
- DestroyDelegatedContent();
-}
-
void RenderWidgetHostViewAndroid::TransformPointToRootSurface(
gfx::PointF* point) {
*point += gfx::Vector2d(
@@ -1548,6 +1585,8 @@ void RenderWidgetHostViewAndroid::GestureEventAck(
overscroll_controller_->OnGestureEventAck(event, ack_result);
mouse_wheel_phase_handler_.GestureEventAck(event, ack_result);
+ ForwardTouchpadPinchIfNecessary(event, ack_result);
+
if (!gesture_listener_manager_)
return;
gesture_listener_manager_->GestureEventAck(event, ack_result);
@@ -1650,7 +1689,7 @@ void RenderWidgetHostViewAndroid::SendKeyEvent(
event.GetType() == blink::WebInputEvent::kChar) {
latency_info.set_source_event_type(ui::SourceEventType::KEY_PRESS);
}
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT);
target_host->ForwardKeyboardEventWithLatencyInfo(event, latency_info);
}
@@ -1718,13 +1757,12 @@ void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
return;
ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT);
blink::WebMouseWheelEvent wheel_event(event);
bool should_route_events = ShouldRouteEvents();
- if (wheel_scroll_latching_enabled()) {
- mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
- wheel_event, should_route_events);
- }
+ mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
+ wheel_event, should_route_events);
+
if (should_route_events) {
host()->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
this, &wheel_event, latency_info);
@@ -1771,28 +1809,26 @@ void RenderWidgetHostViewAndroid::SendGestureEvent(
ui::LatencyInfo latency_info =
ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(event);
- if (wheel_scroll_latching_enabled()) {
- if (event.SourceDevice() ==
- blink::WebGestureDevice::kWebGestureDeviceTouchscreen) {
- if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
- // If there is a current scroll going on and a new scroll that isn't
- // wheel based, send a synthetic wheel event with kPhaseEnded to cancel
- // the current scroll.
- mouse_wheel_phase_handler_.DispatchPendingWheelEndEvent();
- } else if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd) {
- // Make sure that the next wheel event will have phase = |kPhaseBegan|.
- // This is for maintaining the correct phase info when some of the wheel
- // events get ignored while a touchscreen scroll is going on.
- mouse_wheel_phase_handler_.IgnorePendingWheelEndEvent();
- }
-
- } else if (event.GetType() == blink::WebInputEvent::kGestureFlingStart &&
- event.SourceDevice() ==
- blink::WebGestureDevice::kWebGestureDeviceTouchpad) {
- // Ignore the pending wheel end event to avoid sending a wheel event with
- // kPhaseEnded before a GFS.
+ if (event.SourceDevice() ==
+ blink::WebGestureDevice::kWebGestureDeviceTouchscreen) {
+ if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
+ // If there is a current scroll going on and a new scroll that isn't
+ // wheel based, send a synthetic wheel event with kPhaseEnded to cancel
+ // the current scroll.
+ mouse_wheel_phase_handler_.DispatchPendingWheelEndEvent();
+ } else if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd) {
+ // Make sure that the next wheel event will have phase = |kPhaseBegan|.
+ // This is for maintaining the correct phase info when some of the wheel
+ // events get ignored while a touchscreen scroll is going on.
mouse_wheel_phase_handler_.IgnorePendingWheelEndEvent();
}
+
+ } else if (event.GetType() == blink::WebInputEvent::kGestureFlingStart &&
+ event.SourceDevice() ==
+ blink::WebGestureDevice::kWebGestureDeviceTouchpad) {
+ // Ignore the pending wheel end event to avoid sending a wheel event with
+ // kPhaseEnded before a GFS.
+ mouse_wheel_phase_handler_.IgnorePendingWheelEndEvent();
}
if (ShouldRouteEvents()) {
blink::WebGestureEvent gesture_event(event);
@@ -1846,8 +1882,7 @@ void RenderWidgetHostViewAndroid::SetTextHandlesTemporarilyHidden(
handles_hidden_by_selection_ui_ == hide_handles)
return;
handles_hidden_by_selection_ui_ = hide_handles;
- touch_selection_controller_->SetTemporarilyHidden(
- handles_hidden_by_selection_ui_ || handles_hidden_by_stylus_);
+ SetTextHandlesHiddenInternal();
}
base::Optional<SkColor> RenderWidgetHostViewAndroid::GetCachedBackgroundColor()
@@ -1856,14 +1891,15 @@ base::Optional<SkColor> RenderWidgetHostViewAndroid::GetCachedBackgroundColor()
}
void RenderWidgetHostViewAndroid::SetIsInVR(bool is_in_vr) {
+ if (is_in_vr_ == is_in_vr)
+ return;
is_in_vr_ = is_in_vr;
- // TODO(crbug.com/779126): support touch selection handles in VR.
- if (is_in_vr) {
- touch_selection_controller_.reset();
- } else if (view_.parent()) {
- touch_selection_controller_ = CreateSelectionController(
- touch_selection_controller_client_manager_.get(), view_.parent());
- }
+ // TODO(crbug.com/851054): support touch selection handles in VR.
+ SetTextHandlesHiddenInternal();
+
+ gesture_provider_.UpdateConfig(ui::GetGestureProviderConfig(
+ is_in_vr_ ? ui::GestureProviderConfigType::CURRENT_PLATFORM_VR
+ : ui::GestureProviderConfigType::CURRENT_PLATFORM));
if (is_in_vr_ && controls_initialized_) {
// TODO(mthiesse, https://crbug.com/825765): See the TODO in
@@ -1899,9 +1935,9 @@ void RenderWidgetHostViewAndroid::DidStopFlinging() {
gesture_listener_manager_->DidStopFlinging();
}
-viz::FrameSinkId RenderWidgetHostViewAndroid::GetFrameSinkId() {
+const viz::FrameSinkId& RenderWidgetHostViewAndroid::GetFrameSinkId() const {
if (!delegated_frame_host_)
- return viz::FrameSinkId();
+ return viz::FrameSinkIdAllocator::InvalidFrameSinkId();
return delegated_frame_host_->GetFrameSinkId();
}
@@ -1920,7 +1956,6 @@ void RenderWidgetHostViewAndroid::UpdateNativeViewTree(
bool resize = false;
if (will_build_tree != has_view_tree) {
touch_selection_controller_.reset();
- RunAckCallbacks();
if (has_view_tree) {
view_.RemoveObserver(this);
view_.RemoveFromParent();
@@ -1950,8 +1985,12 @@ void RenderWidgetHostViewAndroid::UpdateNativeViewTree(
if (is_showing_ && view_.GetWindowAndroid())
StartObservingRootWindow();
- if (resize)
- SynchronizeVisualProperties();
+ if (resize) {
+ SynchronizeVisualProperties(
+ cc::DeadlinePolicy::UseSpecifiedDeadline(
+ ui::DelegatedFrameHostAndroid::ResizeTimeoutFrames()),
+ base::nullopt);
+ }
if (!touch_selection_controller_) {
ui::TouchSelectionControllerClient* client =
@@ -1970,11 +2009,12 @@ RenderWidgetHostViewAndroid::GetMouseWheelPhaseHandler() {
return &mouse_wheel_phase_handler_;
}
-void RenderWidgetHostViewAndroid::RunAckCallbacks() {
- while (!ack_callbacks_.empty()) {
- ack_callbacks_.front().Run();
- ack_callbacks_.pop();
- }
+void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
+ if (!delegated_frame_host_)
+ return;
+
+ delegated_frame_host_->EvictDelegatedFrame();
+ current_surface_size_.SetSize(0, 0);
}
TouchSelectionControllerClientManager*
@@ -1982,10 +2022,11 @@ RenderWidgetHostViewAndroid::GetTouchSelectionControllerClientManager() {
return touch_selection_controller_client_manager_.get();
}
-viz::LocalSurfaceId RenderWidgetHostViewAndroid::GetLocalSurfaceId() const {
- if (delegated_frame_host_)
- return delegated_frame_host_->GetLocalSurfaceId();
- return viz::LocalSurfaceId();
+const viz::LocalSurfaceId& RenderWidgetHostViewAndroid::GetLocalSurfaceId()
+ const {
+ if (!delegated_frame_host_)
+ return viz::ParentLocalSurfaceIdAllocator::InvalidLocalSurfaceId();
+ return local_surface_id_allocator_.GetCurrentLocalSurfaceId();
}
void RenderWidgetHostViewAndroid::OnRenderWidgetInit() {
@@ -2028,6 +2069,10 @@ void RenderWidgetHostViewAndroid::OnGestureEvent(
SendGestureEvent(web_gesture);
}
+bool RenderWidgetHostViewAndroid::RequiresDoubleTapGestureEvents() const {
+ return true;
+}
+
void RenderWidgetHostViewAndroid::OnSizeChanged() {
if (ime_adapter_android_)
ime_adapter_android_->UpdateAfterViewSizeChanged();
@@ -2037,7 +2082,10 @@ void RenderWidgetHostViewAndroid::OnSizeChanged() {
void RenderWidgetHostViewAndroid::OnPhysicalBackingSizeChanged() {
EvictFrameIfNecessary();
- SynchronizeVisualProperties();
+ SynchronizeVisualProperties(
+ cc::DeadlinePolicy::UseSpecifiedDeadline(
+ ui::DelegatedFrameHostAndroid::ResizeTimeoutFrames()),
+ base::nullopt);
}
void RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged(bool visible) {
@@ -2084,7 +2132,6 @@ void RenderWidgetHostViewAndroid::OnAttachCompositor() {
void RenderWidgetHostViewAndroid::OnDetachCompositor() {
DCHECK(view_.parent());
- RunAckCallbacks();
overscroll_controller_.reset();
if (using_browser_compositor_)
delegated_frame_host_->DetachFromCompositor();
@@ -2180,8 +2227,7 @@ void RenderWidgetHostViewAndroid::OnActivityStarted() {
}
void RenderWidgetHostViewAndroid::OnLostResources() {
- DestroyDelegatedContent();
- DCHECK(ack_callbacks_.empty());
+ EvictDelegatedFrame();
}
void RenderWidgetHostViewAndroid::SetTextHandlesHiddenForStylus(
@@ -2189,8 +2235,16 @@ void RenderWidgetHostViewAndroid::SetTextHandlesHiddenForStylus(
if (!touch_selection_controller_ || handles_hidden_by_stylus_ == hide_handles)
return;
handles_hidden_by_stylus_ = hide_handles;
+ SetTextHandlesHiddenInternal();
+}
+
+void RenderWidgetHostViewAndroid::SetTextHandlesHiddenInternal() {
+ if (!touch_selection_controller_)
+ return;
+ // TODO(crbug.com/851054): support touch selection handles in VR.
touch_selection_controller_->SetTemporarilyHidden(
- handles_hidden_by_stylus_ || handles_hidden_by_selection_ui_);
+ is_in_vr_ || handles_hidden_by_stylus_ ||
+ handles_hidden_by_selection_ui_);
}
void RenderWidgetHostViewAndroid::OnStylusSelectBegin(float x0,
@@ -2316,7 +2370,8 @@ void RenderWidgetHostViewAndroid::TakeFallbackContentFrom(
}
void RenderWidgetHostViewAndroid::OnSynchronizedDisplayPropertiesChanged() {
- SynchronizeVisualProperties();
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+ base::nullopt);
}
base::Optional<SkColor> RenderWidgetHostViewAndroid::GetBackgroundColor()
@@ -2325,10 +2380,21 @@ base::Optional<SkColor> RenderWidgetHostViewAndroid::GetBackgroundColor()
}
void RenderWidgetHostViewAndroid::DidNavigate() {
- RenderWidgetHostViewBase::DidNavigate();
+ if (!delegated_frame_host_) {
+ RenderWidgetHostViewBase::DidNavigate();
+ return;
+ }
- if (delegated_frame_host_)
- delegated_frame_host_->DidNavigate();
+ if (is_first_navigation_) {
+ SynchronizeVisualProperties(
+ cc::DeadlinePolicy::UseExistingDeadline(),
+ local_surface_id_allocator_.GetCurrentLocalSurfaceId());
+ } else {
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(),
+ base::nullopt);
+ }
+ delegated_frame_host_->DidNavigate();
+ is_first_navigation_ = false;
}
viz::ScopedSurfaceIdAllocator
@@ -2341,7 +2407,6 @@ RenderWidgetHostViewAndroid::DidUpdateVisualProperties(
&RenderWidgetHostViewAndroid::OnDidUpdateVisualPropertiesComplete,
weak_ptr_factory_.GetWeakPtr(), metadata);
return viz::ScopedSurfaceIdAllocator(std::move(allocation_task));
- ;
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_android.h b/chromium/content/browser/renderer_host/render_widget_host_view_android.h
index 87b3d601b77..ae59220401e 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,10 +18,10 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
-#include "components/viz/client/frame_evictor.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/quads/selection.h"
+#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
#include "content/browser/renderer_host/input/stylus_text_selector.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
@@ -73,8 +73,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
public ui::TouchSelectionControllerClient,
public ui::ViewAndroidObserver,
public ui::WindowAndroidObserver,
- public viz::BeginFrameObserver,
- public viz::FrameEvictorClient {
+ public viz::BeginFrameObserver {
public:
RenderWidgetHostViewAndroid(RenderWidgetHostImpl* widget,
gfx::NativeView parent_native_view);
@@ -170,7 +169,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void OnDidNavigateMainFrameToNewPage() override;
void SetNeedsBeginFrames(bool needs_begin_frames) override;
void SetWantsAnimateOnlyBeginFrames() override;
- viz::FrameSinkId GetFrameSinkId() override;
+ const viz::FrameSinkId& GetFrameSinkId() const override;
bool TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
@@ -184,7 +183,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
viz::EventSource source = viz::EventSource::ANY) override;
TouchSelectionControllerClientManager*
GetTouchSelectionControllerClientManager() override;
- viz::LocalSurfaceId GetLocalSurfaceId() const override;
+ const viz::LocalSurfaceId& GetLocalSurfaceId() const override;
void OnRenderWidgetInit() override;
void TakeFallbackContentFrom(RenderWidgetHostView* view) override;
void OnSynchronizedDisplayPropertiesChanged() override;
@@ -207,6 +206,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// ui::GestureProviderClient implementation.
void OnGestureEvent(const ui::GestureEventData& gesture) override;
+ bool RequiresDoubleTapGestureEvents() const override;
// ui::WindowAndroidObserver implementation.
void OnCompositingDidCommit() override {}
@@ -217,9 +217,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void OnActivityStopped() override;
void OnActivityStarted() override;
- // viz::FrameEvictor implementation
- void EvictDelegatedFrame() override;
-
// StylusTextSelectorClient implementation.
void OnStylusSelectBegin(float x0, float y0, float x1, float y1) override;
void OnStylusSelectUpdate(float x, float y) override;
@@ -240,12 +237,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// DelegatedFrameHostAndroid::Client implementation.
void SetBeginFrameSource(viz::BeginFrameSource* begin_frame_source) override;
- void DidReceiveCompositorFrameAck() override;
- void DidPresentCompositorFrame(uint32_t presentation_token,
- base::TimeTicks time,
- base::TimeDelta refresh,
- uint32_t flags) override;
- void DidDiscardCompositorFrame(uint32_t presentation_token) override;
+ void DidPresentCompositorFrame(
+ uint32_t presentation_token,
+ const gfx::PresentationFeedback& feedback) override;
+ void DidReceiveCompositorFrameAck(
+ const std::vector<viz::ReturnedResource>& resources) override;
void ReclaimResources(
const std::vector<viz::ReturnedResource>& resources) override;
void OnFrameTokenChanged(uint32_t frame_token) override;
@@ -296,7 +292,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void SetDoubleTapSupportEnabled(bool enabled);
void SetMultiTouchZoomSupportEnabled(bool enabled);
- bool SynchronizeVisualProperties();
+ bool SynchronizeVisualProperties(const cc::DeadlinePolicy& deadline_policy,
+ const base::Optional<viz::LocalSurfaceId>&
+ child_allocated_local_surface_id);
bool HasValidFrame() const;
@@ -343,6 +341,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void GotFocus();
void LostFocus();
+ // RenderFrameMetadataProvider::Observer
+ void OnRenderFrameMetadataChangedBeforeActivation(
+ const cc::RenderFrameMetadata& metadata) override;
+
protected:
// RenderWidgetHostViewBase:
void UpdateBackgroundColor() override;
@@ -350,15 +352,20 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
private:
MouseWheelPhaseHandler* GetMouseWheelPhaseHandler() override;
- void RunAckCallbacks();
+ void EvictDelegatedFrame();
bool ShouldRouteEvents() const;
- void SendReclaimCompositorResources(bool is_swap_ack);
void OnFrameMetadataUpdated(
const viz::CompositorFrameMetadata& frame_metadata,
bool is_transparent);
+ void UpdateTouchSelectionController(
+ const viz::Selection<gfx::SelectionBound>& selection,
+ float page_scale_factor,
+ float top_controls_height,
+ float top_controls_shown_ratio,
+ const gfx::SizeF& scrollable_viewport_size_dip);
bool UpdateControls(float dip_scale,
float top_controls_height,
float top_controls_shown_ratio,
@@ -380,7 +387,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
const gfx::Size& dst_size_in_pixel,
base::OnceCallback<void(const SkBitmap&)> callback);
- void DestroyDelegatedContent();
+ void EvictDelegatedContent();
void OnLostResources();
enum BeginFrameRequestType {
@@ -389,7 +396,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
};
void AddBeginFrameRequest(BeginFrameRequestType request);
void ClearBeginFrameRequest(BeginFrameRequestType request);
- void AcknowledgeBeginFrame(const viz::BeginFrameAck& ack);
void StartObservingRootWindow();
void StopObservingRootWindow();
void SendBeginFramePaused();
@@ -414,6 +420,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void LostFocusInternal();
void SetTextHandlesHiddenForStylus(bool hide_handles);
+ void SetTextHandlesHiddenInternal();
// The begin frame source being observed. Null if none.
viz::BeginFrameSource* begin_frame_source_;
@@ -452,13 +459,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// Manages the Compositor Frames received from the renderer.
std::unique_ptr<ui::DelegatedFrameHostAndroid> delegated_frame_host_;
- std::vector<viz::ReturnedResource> surface_returned_resources_;
-
// The most recent surface size that was pushed to the surface layer.
gfx::Size current_surface_size_;
- base::queue<base::Closure> ack_callbacks_;
-
// Used to control and render overscroll-related effects.
std::unique_ptr<OverscrollControllerAndroid> overscroll_controller_;
@@ -487,8 +490,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
SynchronousCompositorClient* synchronous_compositor_client_;
- std::unique_ptr<viz::FrameEvictor> frame_evictor_;
-
bool observing_root_window_;
bool controls_initialized_ = false;
@@ -512,6 +513,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
MouseWheelPhaseHandler mouse_wheel_phase_handler_;
uint32_t latest_capture_sequence_number_ = 0u;
+ viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
+ bool is_first_navigation_ = true;
+
base::WeakPtrFactory<RenderWidgetHostViewAndroid> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroid);
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc b/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
index 861122e9908..09168578786 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
@@ -56,7 +56,7 @@
#include "gpu/ipc/common/gpu_messages.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/ui/common/switches.h"
-#include "services/ui/public/interfaces/window_manager_constants.mojom.h"
+#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/web/web_ime_text_span.h"
#include "ui/accessibility/platform/aura_window_properties.h"
@@ -98,6 +98,7 @@
#include "ui/gfx/skia_util.h"
#include "ui/touch_selection/touch_selection_controller.h"
#include "ui/wm/core/coordinate_conversion.h"
+#include "ui/wm/core/window_util.h"
#include "ui/wm/public/activation_client.h"
#include "ui/wm/public/scoped_tooltip_disabler.h"
#include "ui/wm/public/tooltip_client.h"
@@ -364,7 +365,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(
is_guest_view_hack_(is_guest_view_hack),
device_scale_factor_(0.0f),
event_handler_(new RenderWidgetHostViewEventHandler(host(), this, this)),
- frame_sink_id_(base::FeatureList::IsEnabled(features::kMash)
+ frame_sink_id_(!features::IsAshInBrowserProcess()
? viz::FrameSinkId()
: is_guest_view_hack_
? AllocateFrameSinkIdForGuestViewHack()
@@ -655,16 +656,6 @@ void RenderWidgetHostViewAura::WasUnOccluded() {
bool has_saved_frame =
delegated_frame_host_ ? delegated_frame_host_->HasSavedFrame() : false;
- ui::LatencyInfo renderer_latency_info, browser_latency_info;
- if (has_saved_frame) {
- browser_latency_info.AddLatencyNumber(ui::TAB_SHOW_COMPONENT,
- host()->GetLatencyComponentId());
- browser_latency_info.set_trace_id(++tab_show_sequence_);
- } else {
- renderer_latency_info.AddLatencyNumber(ui::TAB_SHOW_COMPONENT,
- host()->GetLatencyComponentId());
- renderer_latency_info.set_trace_id(++tab_show_sequence_);
- }
// If the primary surface was evicted, we should create a new primary.
if (delegated_frame_host_ &&
@@ -673,9 +664,8 @@ void RenderWidgetHostViewAura::WasUnOccluded() {
base::nullopt);
}
- TRACE_EVENT_ASYNC_BEGIN0("latency", "TabSwitching::Latency",
- tab_show_sequence_);
- host()->WasShown(renderer_latency_info);
+ const bool renderer_should_record_presentation_time = !has_saved_frame;
+ host()->WasShown(renderer_should_record_presentation_time);
aura::Window* root = window_->GetRootWindow();
if (root) {
@@ -686,9 +676,12 @@ void RenderWidgetHostViewAura::WasUnOccluded() {
}
if (delegated_frame_host_) {
+ // If the frame for the renderer is already available, then the
+ // tab-switching time is the presentation time for the browser-compositor.
+ const bool record_presentation_time = has_saved_frame;
delegated_frame_host_->WasShown(window_->GetLocalSurfaceId(),
window_->bounds().size(),
- browser_latency_info);
+ record_presentation_time);
}
#if defined(OS_WIN)
@@ -831,12 +824,6 @@ void RenderWidgetHostViewAura::DisplayTooltipText(
}
}
-gfx::Size RenderWidgetHostViewAura::GetRequestedRendererSize() const {
- return delegated_frame_host_
- ? delegated_frame_host_->GetRequestedRendererSize()
- : RenderWidgetHostViewBase::GetRequestedRendererSize();
-}
-
uint32_t RenderWidgetHostViewAura::GetCaptureSequenceNumber() const {
return latest_capture_sequence_number_;
}
@@ -988,6 +975,8 @@ void RenderWidgetHostViewAura::GestureEventAck(
}
}
event_handler_->GestureEventAck(event, ack_result);
+
+ ForwardTouchpadPinchIfNecessary(event, ack_result);
}
void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
@@ -1460,12 +1449,14 @@ bool RenderWidgetHostViewAura::IsTextEditCommandEnabled(
void RenderWidgetHostViewAura::SetTextEditCommandForNextKeyEvent(
ui::TextEditCommand command) {}
-const std::string& RenderWidgetHostViewAura::GetClientSourceInfo() const {
+ukm::SourceId RenderWidgetHostViewAura::GetClientSourceForMetrics() const {
RenderFrameHostImpl* frame = GetFocusedFrame();
if (frame) {
- return frame->GetLastCommittedURL().spec();
+ frame->GetRenderWidgetHost()
+ ->delegate()
+ ->GetUkmSourceIdForLastCommittedSource();
}
- return base::EmptyString();
+ return ukm::SourceId();
}
bool RenderWidgetHostViewAura::ShouldDoLearning() {
@@ -1519,7 +1510,7 @@ void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
}
gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
- if (mouse_locked_)
+ if (IsMouseLocked())
return ui::CursorType::kNone;
return current_cursor_.GetNativeCursor();
}
@@ -1553,7 +1544,8 @@ void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
if (!window_->GetRootWindow())
return;
- SyncSurfaceProperties(cc::DeadlinePolicy::UseDefaultDeadline());
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+ window_->GetLocalSurfaceId());
device_scale_factor_ = new_device_scale_factor;
const display::Display display =
@@ -1605,6 +1597,11 @@ bool RenderWidgetHostViewAura::HasHitTestMask() const {
void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
}
+bool RenderWidgetHostViewAura::RequiresDoubleTapGestureEvents() const {
+ RenderViewHost* rvh = RenderViewHost::From(host());
+ return rvh && rvh->GetWebkitPreferences().double_tap_to_zoom_enabled;
+}
+
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, ui::EventHandler implementation:
@@ -1703,7 +1700,7 @@ void RenderWidgetHostViewAura::FocusedNodeChanged(
void RenderWidgetHostViewAura::ScheduleEmbed(
ui::mojom::WindowTreeClientPtr client,
base::OnceCallback<void(const base::UnguessableToken&)> callback) {
- DCHECK(features::IsMashEnabled());
+ DCHECK(!features::IsAshInBrowserProcess());
aura::Env::GetInstance()->ScheduleEmbed(std::move(client),
std::move(callback));
}
@@ -1836,8 +1833,8 @@ void RenderWidgetHostViewAura::OnHostMovedInPixels(
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, RenderFrameMetadataProvider::Observer
// implementation:
-void RenderWidgetHostViewAura::OnRenderFrameMetadataChanged() {
- RenderWidgetHostViewBase::OnRenderFrameMetadataChanged();
+void RenderWidgetHostViewAura::OnRenderFrameMetadataChangedAfterActivation() {
+ RenderWidgetHostViewBase::OnRenderFrameMetadataChangedAfterActivation();
const cc::RenderFrameMetadata& metadata =
host()->render_frame_metadata_provider()->LastRenderFrameMetadata();
SetContentBackgroundColor(metadata.root_background_color);
@@ -1925,7 +1922,7 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
if (frame_sink_id_.is_valid())
window_->SetEmbedFrameSinkId(frame_sink_id_);
- if (!features::IsMashEnabled())
+ if (features::IsAshInBrowserProcess())
return;
// Embed the renderer into the Window.
@@ -2031,7 +2028,15 @@ bool RenderWidgetHostViewAura::SynchronizeVisualProperties(
DCHECK(window_);
window_->UpdateLocalSurfaceIdFromEmbeddedClient(
child_allocated_local_surface_id);
- return SyncSurfaceProperties(deadline_policy);
+ if (IsLocalSurfaceIdAllocationSuppressed())
+ return false;
+
+ if (delegated_frame_host_) {
+ delegated_frame_host_->EmbedSurface(window_->GetLocalSurfaceId(),
+ window_->bounds().size(),
+ deadline_policy);
+ }
+ return host()->SynchronizeVisualProperties();
}
ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
@@ -2134,15 +2139,8 @@ 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.
-#if defined(OS_CHROMEOS)
- aura::Window* snapped = window_->GetToplevelWindow();
-#else
- aura::Window* snapped = window_->GetRootWindow();
-#endif
-
- if (snapped && snapped != window_)
- ui::SnapLayerToPhysicalPixelBoundary(snapped->layer(), window_->layer());
-
+ // We want to snap it to the nearest ancestor.
+ wm::SnapWindowToPixelBoundary(window_);
has_snapped_to_boundary_ = true;
}
@@ -2159,32 +2157,17 @@ void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
if (!in_bounds_changed_)
window_->SetBounds(rect);
- SyncSurfaceProperties(cc::DeadlinePolicy::UseDefaultDeadline());
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+ window_->GetLocalSurfaceId());
#if defined(OS_WIN)
UpdateLegacyWin();
- if (mouse_locked_)
+ if (IsMouseLocked())
UpdateMouseLockRegion();
#endif
}
-bool RenderWidgetHostViewAura::SyncSurfaceProperties(
- const cc::DeadlinePolicy& deadline_policy) {
- if (IsLocalSurfaceIdAllocationSuppressed())
- return false;
-
- if (delegated_frame_host_) {
- delegated_frame_host_->SynchronizeVisualProperties(
- window_->GetLocalSurfaceId(), window_->bounds().size(),
- deadline_policy);
- }
- // Note that |host_| will retrieve resize parameters from
- // |delegated_frame_host_|, so it must have SynchronizeVisualProperties called
- // after.
- return host()->SynchronizeVisualProperties();
-}
-
#if defined(OS_WIN)
void RenderWidgetHostViewAura::UpdateLegacyWin() {
if (legacy_window_destroyed_ || !GetHostWindowHWND())
@@ -2335,11 +2318,11 @@ void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() {
ui::GestureRecognizer::Get()->CancelActiveTouches(window_);
}
-viz::FrameSinkId RenderWidgetHostViewAura::GetFrameSinkId() {
+const viz::FrameSinkId& RenderWidgetHostViewAura::GetFrameSinkId() const {
return frame_sink_id_;
}
-viz::LocalSurfaceId RenderWidgetHostViewAura::GetLocalSurfaceId() const {
+const viz::LocalSurfaceId& RenderWidgetHostViewAura::GetLocalSurfaceId() const {
return window_->GetLocalSurfaceId();
}
@@ -2360,7 +2343,7 @@ void RenderWidgetHostViewAura::OnUpdateTextInputStateCalled(
state->type != ui::TEXT_INPUT_TYPE_NONE &&
state->mode != ui::TEXT_INPUT_MODE_NONE &&
GetInputMethod()->GetTextInputClient() == this) {
- GetInputMethod()->ShowImeIfNeeded();
+ GetInputMethod()->ShowVirtualKeyboardIfEnabled();
}
if (auto* render_widget_host = updated_view->host()) {
@@ -2493,7 +2476,8 @@ void RenderWidgetHostViewAura::DidNavigate() {
// The first navigation does not need a new LocalSurfaceID. The renderer can
// use the ID that was already provided.
if (is_first_navigation_) {
- SyncSurfaceProperties(cc::DeadlinePolicy::UseExistingDeadline());
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(),
+ window_->GetLocalSurfaceId());
} else {
SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(),
base::nullopt);
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 d36135e491b..5f75e19c4a9 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
@@ -136,7 +136,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void Destroy() override;
void SetTooltipText(const base::string16& tooltip_text) override;
void DisplayTooltipText(const base::string16& tooltip_text) override;
- gfx::Size GetRequestedRendererSize() const override;
uint32_t GetCaptureSequenceNumber() const override;
bool IsSurfaceAvailableForCopy() const override;
void CopyFromSurface(
@@ -182,8 +181,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
bool RequestRepaintForTesting() override;
void DidStopFlinging() override;
void OnDidNavigateMainFrameToNewPage() override;
- viz::FrameSinkId GetFrameSinkId() override;
- viz::LocalSurfaceId GetLocalSurfaceId() const override;
+ const viz::FrameSinkId& GetFrameSinkId() const override;
+ const viz::LocalSurfaceId& GetLocalSurfaceId() const override;
bool TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
@@ -240,7 +239,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void EnsureCaretNotInRect(const gfx::Rect& rect) override;
bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override;
void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override;
- const std::string& GetClientSourceInfo() const override;
+ ukm::SourceId GetClientSourceForMetrics() const override;
bool ShouldDoLearning() override;
// Overridden from display::DisplayObserver:
@@ -269,6 +268,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void OnWindowTargetVisibilityChanged(bool visible) override;
bool HasHitTestMask() const override;
void GetHitTestMask(gfx::Path* mask) const override;
+ bool RequiresDoubleTapGestureEvents() const override;
// Overridden from ui::EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override;
@@ -292,7 +292,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
const gfx::Point& new_origin_in_pixels) override;
// RenderFrameMetadataProvider::Observer
- void OnRenderFrameMetadataChanged() override;
+ void OnRenderFrameMetadataChangedAfterActivation() override;
#if defined(OS_WIN)
// Gets the HWND of the host window.
@@ -404,6 +404,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
VirtualKeyboardFocusEnsureCaretInRect);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
HitTestRegionListSubmitted);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
+ DiscardDelegatedFramesWithMemoryPressure);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraKeyboardTest,
KeyboardObserverDestroyed);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
@@ -429,6 +431,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
WebContentsViewReparent);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
TakeFallbackContent);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
+ DiscardDelegatedFrames);
class WindowObserver;
friend class WindowObserver;
@@ -464,9 +468,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// space is required by the aura::Window.
void InternalSetBounds(const gfx::Rect& rect);
- // Handles propagation of surface properties when they are changed.
- bool SyncSurfaceProperties(const cc::DeadlinePolicy& deadline_policy);
-
#if defined(OS_WIN)
// Creates and/or updates the legacy dummy window which corresponds to
// the bounds of the webcontents. It is needed for accessibility and
@@ -660,7 +661,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
const viz::FrameSinkId frame_sink_id_;
std::unique_ptr<CursorManager> cursor_manager_;
- int tab_show_sequence_ = 0;
// Latest capture sequence number which is incremented when the caller
// requests surfaces be synchronized via
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 b84c96372ca..9aac9b4c740 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
@@ -213,8 +213,7 @@ class TestWindowObserver : public aura::WindowObserver {
class FakeWindowEventDispatcher : public aura::WindowEventDispatcher {
public:
FakeWindowEventDispatcher(aura::WindowTreeHost* host)
- : WindowEventDispatcher(host),
- processed_touch_event_count_(0) {}
+ : WindowEventDispatcher(host, true), processed_touch_event_count_(0) {}
void ProcessedTouchEvent(
uint32_t unique_event_id,
@@ -385,6 +384,20 @@ class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
lastWheelOrTouchEventLatencyInfo = ui::LatencyInfo(ui_latency);
}
+ void ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& gesture_event,
+ const ui::LatencyInfo& ui_latency) override {
+ RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(gesture_event,
+ ui_latency);
+ last_forwarded_gesture_event_ = gesture_event;
+ }
+
+ base::Optional<WebGestureEvent> GetAndResetLastForwardedGestureEvent() {
+ base::Optional<WebGestureEvent> ret;
+ last_forwarded_gesture_event_.swap(ret);
+ return ret;
+ }
+
static MockRenderWidgetHostImpl* Create(RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int32_t routing_id) {
@@ -429,8 +442,9 @@ class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
new_content_rendering_timeout_fired_ = true;
}
- bool new_content_rendering_timeout_fired_;
+ bool new_content_rendering_timeout_fired_ = false;
std::unique_ptr<MockWidgetImpl> widget_impl_;
+ base::Optional<WebGestureEvent> last_forwarded_gesture_event_;
};
class TestScopedKeyboardHook : public aura::ScopedKeyboardHook {
@@ -472,19 +486,14 @@ void TestScopedKeyboardHook::LockSpecificKey(ui::DomCode dom_code) {
locked_key_ = dom_code;
}
-enum WheelScrollingMode {
- kWheelScrollingModeNone,
- kWheelScrollLatching,
- kAsyncWheelEvents,
-};
-
class RenderWidgetHostViewAuraTest : public testing::Test {
public:
- RenderWidgetHostViewAuraTest(
- WheelScrollingMode wheel_scrolling_mode = kWheelScrollingModeNone)
- : wheel_scrolling_mode_(wheel_scrolling_mode),
- widget_host_uses_shutdown_to_destroy_(false),
- is_guest_view_hack_(false) {}
+ RenderWidgetHostViewAuraTest()
+ : widget_host_uses_shutdown_to_destroy_(false),
+ is_guest_view_hack_(false) {
+ ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
+ 0);
+ }
static void InstallDelegatedFrameHostClient(
RenderWidgetHostViewAura* view,
@@ -610,34 +619,10 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
const ui::MotionEventAura& pointer_state() { return view_->pointer_state(); }
void SetFeatureList() {
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- feature_list_.InitWithFeatures({features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents},
- {});
- } else if (wheel_scrolling_mode_ == kWheelScrollLatching) {
- feature_list_.InitWithFeatures(
- {features::kTouchpadAndWheelScrollLatching},
- {features::kAsyncWheelEvents});
- } else if (wheel_scrolling_mode_ == kWheelScrollingModeNone) {
- feature_list_.InitWithFeatures({},
- {features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents});
- }
-
vsync_feature_list_.InitAndEnableFeature(
features::kVsyncAlignedInputEvents);
}
- void TimerBasedWheelEventPhaseInfo();
- void TimerBasedLatchingBreaksWithMouseMove();
- void TimerBasedLatchingBreaksWithModifiersChange();
- void TimerBasedLatchingBreaksWithDirectionChange();
- void TimerBasedLatchingBreaksWithAutoscrollStart();
- void TouchpadFlingStartResetsWheelPhaseState();
- void GSBWithTouchSourceStopsWheelScrollSequence();
-
- WheelScrollingMode wheel_scrolling_mode_;
-
protected:
BrowserContext* browser_context() { return browser_context_.get(); }
@@ -722,32 +707,6 @@ class RenderWidgetHostViewAuraSurfaceSynchronizationTest
base::test::ScopedFeatureList surface_synchronization_feature_list_;
};
-class RenderWidgetHostViewAuraWheelScrollLatchingEnabledTest
- : public RenderWidgetHostViewAuraTest {
- public:
- RenderWidgetHostViewAuraWheelScrollLatchingEnabledTest()
- : RenderWidgetHostViewAuraTest(kWheelScrollLatching) {}
- void SetUp() override {
- SetFeatureList();
- ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
- 0);
- RenderWidgetHostViewAuraTest::SetUpEnvironment();
- }
-};
-
-class RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest
- : public RenderWidgetHostViewAuraTest {
- public:
- RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest()
- : RenderWidgetHostViewAuraTest(kAsyncWheelEvents) {}
- void SetUp() override {
- SetFeatureList();
- ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
- 0);
- RenderWidgetHostViewAuraTest::SetUpEnvironment();
- }
-};
-
void InstallDelegatedFrameHostClient(
RenderWidgetHostViewAura* render_widget_host_view,
std::unique_ptr<DelegatedFrameHostClient> delegated_frame_host_client) {
@@ -795,11 +754,7 @@ class RenderWidgetHostViewGuestAuraTest : public RenderWidgetHostViewAuraTest {
class RenderWidgetHostViewAuraOverscrollTest
: public RenderWidgetHostViewAuraTest {
public:
- RenderWidgetHostViewAuraOverscrollTest(
- WheelScrollingMode wheel_scrolling_mode = kWheelScrollLatching)
- : RenderWidgetHostViewAuraTest(wheel_scrolling_mode),
- wheel_scroll_latching_enabled_(wheel_scrolling_mode !=
- kWheelScrollingModeNone) {}
+ RenderWidgetHostViewAuraOverscrollTest() : RenderWidgetHostViewAuraTest() {}
// We explicitly invoke SetUp to allow gesture debounce customization.
void SetUp() override {}
@@ -823,16 +778,14 @@ class RenderWidgetHostViewAuraOverscrollTest
void SendScrollBeginAckIfNeeded(
MockWidgetInputHandler::MessageVector& messages,
InputEventAckState ack_result) {
- if (wheel_scroll_latching_enabled_) {
- for (size_t i = 0; i < messages.size(); ++i) {
- MockWidgetInputHandler::DispatchedEventMessage* event =
- messages[i]->ToEvent();
- // GSB events are blocking, send the ack.
- if (event && event->Event()->web_event->GetType() ==
- WebInputEvent::kGestureScrollBegin) {
- event->CallCallback(ack_result);
- return;
- }
+ for (size_t i = 0; i < messages.size(); ++i) {
+ MockWidgetInputHandler::DispatchedEventMessage* event =
+ messages[i]->ToEvent();
+ // GSB events are blocking, send the ack.
+ if (event && event->Event()->web_event->GetType() ==
+ WebInputEvent::kGestureScrollBegin) {
+ event->CallCallback(ack_result);
+ return;
}
}
}
@@ -887,17 +840,11 @@ class RenderWidgetHostViewAuraOverscrollTest
base::RunLoop().RunUntilIdle();
}
- void SimulateWheelEvent(float dX, float dY, int modifiers, bool precise) {
- widget_host_->ForwardWheelEvent(SyntheticWebMouseWheelEventBuilder::Build(
- 0, 0, dX, dY, modifiers, precise));
- base::RunLoop().RunUntilIdle();
- }
-
- void SimulateWheelEventWithPhase(float dX,
- float dY,
- int modifiers,
- bool precise,
- WebMouseWheelEvent::Phase phase) {
+ void SimulateWheelEvent(float dX,
+ float dY,
+ int modifiers,
+ bool precise,
+ WebMouseWheelEvent::Phase phase) {
WebMouseWheelEvent wheel_event = SyntheticWebMouseWheelEventBuilder::Build(
0, 0, dX, dY, modifiers, precise);
wheel_event.phase = phase;
@@ -905,30 +852,6 @@ class RenderWidgetHostViewAuraOverscrollTest
base::RunLoop().RunUntilIdle();
}
- void SimulateWheelEventPossiblyIncludingPhase(
- float dX,
- float dY,
- int modifiers,
- bool precise,
- WebMouseWheelEvent::Phase phase) {
- if (wheel_scroll_latching_enabled_)
- SimulateWheelEventWithPhase(dX, dY, modifiers, precise, phase);
- else
- SimulateWheelEvent(dX, dY, modifiers, precise);
- }
-
- void SimulateWheelEventWithLatencyInfo(float dX,
- float dY,
- int modifiers,
- bool precise,
- const ui::LatencyInfo& ui_latency) {
- widget_host_->ForwardWheelEventWithLatencyInfo(
- SyntheticWebMouseWheelEventBuilder::Build(0, 0, dX, dY, modifiers,
- precise),
- ui_latency);
- base::RunLoop().RunUntilIdle();
- }
-
void SimulateMouseMove(int x, int y, int modifiers) {
SimulateMouseEvent(WebInputEvent::kMouseMove, x, y, modifiers, false);
}
@@ -946,12 +869,6 @@ class RenderWidgetHostViewAuraOverscrollTest
base::RunLoop().RunUntilIdle();
}
- void SimulateWheelEventWithPhase(WebMouseWheelEvent::Phase phase) {
- widget_host_->ForwardWheelEvent(
- SyntheticWebMouseWheelEventBuilder::Build(phase));
- base::RunLoop().RunUntilIdle();
- }
-
// Inject provided synthetic WebGestureEvent instance.
void SimulateGestureEventCore(const WebGestureEvent& gesture_event) {
widget_host_->ForwardGestureEvent(gesture_event);
@@ -1059,15 +976,26 @@ class RenderWidgetHostViewAuraOverscrollTest
touch_event_.ReleasePoint(index);
}
+ void PressAndSetTouchActionAuto() {
+ PressTouchPoint(0, 1);
+ SendTouchEvent();
+ widget_host_->input_router()->OnSetTouchAction(cc::kTouchActionAuto);
+ MockWidgetInputHandler::MessageVector events =
+ GetAndResetDispatchedMessages();
+ EXPECT_EQ("TouchStart", GetMessageNames(events));
+ }
+
+ void ReleaseAndResetDispatchedMessages() {
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ MockWidgetInputHandler::MessageVector events =
+ GetAndResetDispatchedMessages();
+ }
+
MockWidgetInputHandler::MessageVector ExpectGestureScrollEndForWheelScrolling(
bool is_last) {
MockWidgetInputHandler::MessageVector events =
GetAndResetDispatchedMessages();
- if (!wheel_scroll_latching_enabled_) {
- // Already handled in |ExpectGestureScrollEventsAfterMouseWheelACK()|.
- EXPECT_EQ(0U, events.size());
- return events;
- }
if (is_last) {
// Scroll latching will have one GestureScrollEnd at the end.
EXPECT_EQ("GestureScrollEnd", GetMessageNames(events));
@@ -1085,8 +1013,6 @@ class RenderWidgetHostViewAuraOverscrollTest
MockWidgetInputHandler::MessageVector events =
GetAndResetDispatchedMessages();
std::string expected_events;
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- EXPECT_TRUE(wheel_scroll_latching_enabled_);
// If the ack for the first sent event is not consumed,
// MouseWheelEventQueue(MWEQ) sends the rest of the wheel events in the
// current scrolling sequence as non-blocking events. Since MWEQ
@@ -1100,30 +1026,6 @@ class RenderWidgetHostViewAuraOverscrollTest
expected_events += "GestureScrollBegin GestureScrollUpdate ";
for (size_t i = 0; i < enqueued_wheel_event_count; ++i)
expected_events += "MouseWheel GestureScrollUpdate ";
- } else if (wheel_scrolling_mode_ == kWheelScrollLatching) {
- EXPECT_TRUE(wheel_scroll_latching_enabled_);
- // Since the MWEQ must wait for ack of the sent event before sending the
- // next queued event, when wheel events are blocking only one queued
- // event will be sent regardless of the number of the queued wheel
- // events.
- // Expecting a GSU or GSB+GSU for ACKing the previous MouseWheel, plus an
- // additional MouseWheel if the queue is not empty. GSE will be delayed by
- // scroll latching.
- if (is_first_ack)
- expected_events += "GestureScrollBegin ";
- expected_events += "GestureScrollUpdate ";
- if (enqueued_wheel_event_count != 0)
- expected_events += "MouseWheel";
- } else {
- // The MWEQ must wait for ack of the sent event before sending the
- // next queued event.
- // Expecting a GSB+GSU+GSE for ACKing the previous MouseWheel, plus an
- // additional MouseWheel if the queue is not empty.
- expected_events +=
- "GestureScrollBegin GestureScrollUpdate GestureScrollEnd ";
- if (enqueued_wheel_event_count != 0)
- expected_events += "MouseWheel";
- }
EXPECT_EQ(base::TrimWhitespaceASCII(expected_events, base::TRIM_TRAILING),
GetMessageNames(events));
@@ -1157,60 +1059,16 @@ class RenderWidgetHostViewAuraOverscrollTest
return events;
}
- void ExpectGestureScrollEventsAfterMouseWheelAckWhenOverscrolling() {
- MockWidgetInputHandler::MessageVector events =
- GetAndResetDispatchedMessages();
- // Wheel event ack either:
- // - does not generate a gesture scroll update (async wheel event); or
- // - generates a gesture scroll update that is consumed by the overscroll
- // controller to prevent content scroll (non-async wheel event).
- if (wheel_scroll_latching_enabled_) {
- EXPECT_EQ(0U, events.size());
- } else {
- // Wheel event ack generates a gesture scroll begin, a gesture scroll
- // update, and a gesture scroll end; of which the gesture scroll update is
- // consumed by the overscroll controller to prevent content scroll.
- EXPECT_EQ("GestureScrollBegin GestureScrollEnd", GetMessageNames(events));
- }
- }
-
- void WheelNotPreciseScrollEvent();
- void WheelScrollOverscrollToggle();
- void OverscrollMouseMoveCompletion();
- void WheelScrollEventOverscrolls();
- void WheelScrollConsumedDoNotOverscroll();
- void ScrollEventsOverscrollWithFling();
- void OverscrollDirectionChangeMouseWheel();
- void OverscrollStateResetsAfterScroll();
- void ScrollDeltasResetOnEnd();
- void ScrollEventsOverscrollWithZeroFling();
-
SyntheticWebTouchEvent touch_event_;
std::unique_ptr<TestOverscrollDelegate> overscroll_delegate_;
- bool wheel_scroll_latching_enabled_;
-
private:
base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraOverscrollTest);
};
-class RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest
- : public RenderWidgetHostViewAuraOverscrollTest {
- public:
- RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest()
- : RenderWidgetHostViewAuraOverscrollTest(kWheelScrollingModeNone) {}
-};
-
-class RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest
- : public RenderWidgetHostViewAuraOverscrollTest {
- public:
- RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest()
- : RenderWidgetHostViewAuraOverscrollTest(kAsyncWheelEvents) {}
-};
-
class RenderWidgetHostViewAuraShutdownTest
: public RenderWidgetHostViewAuraTest {
public:
@@ -2001,11 +1859,7 @@ TEST_F(RenderWidgetHostViewAuraTest,
}
}
-void RenderWidgetHostViewAuraTest::TimerBasedWheelEventPhaseInfo() {
- // The test is valid only when wheel scroll latching is enabled.
- if (wheel_scrolling_mode_ == kWheelScrollingModeNone)
- return;
-
+TEST_F(RenderWidgetHostViewAuraTest, TimerBasedWheelEventPhaseInfo) {
view_->InitAsChild(nullptr);
view_->Show();
sink_->ClearMessages();
@@ -2049,16 +1903,9 @@ void RenderWidgetHostViewAuraTest::TimerBasedWheelEventPhaseInfo() {
events[0]->ToEvent()->Event()->web_event.get());
base::TimeTicks wheel_event_timestamp = wheel_event->TimeStamp();
EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, wheel_event->phase);
- if (wheel_scrolling_mode_ == kWheelScrollLatching) {
- events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- events = GetAndResetDispatchedMessages();
- gesture_event = static_cast<const WebGestureEvent*>(
- events[0]->ToEvent()->Event()->web_event.get());
- } else { // wheel_scrolling_mode_ == kAsyncWheelEvents.
+
gesture_event = static_cast<const WebGestureEvent*>(
events[1]->ToEvent()->Event()->web_event.get());
- }
-
EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, gesture_event->GetType());
EXPECT_EQ(0U, gesture_event->data.scroll_update.delta_x);
EXPECT_EQ(2U, gesture_event->data.scroll_update.delta_y);
@@ -2085,23 +1932,11 @@ void RenderWidgetHostViewAuraTest::TimerBasedWheelEventPhaseInfo() {
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, gesture_event->GetType());
EXPECT_TRUE(gesture_event->data.scroll_end.synthetic);
}
-TEST_F(RenderWidgetHostViewAuraWheelScrollLatchingEnabledTest,
- TimerBasedWheelEventPhaseInfo) {
- TimerBasedWheelEventPhaseInfo();
-}
-TEST_F(RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest,
- TimerBasedWheelEventPhaseInfo) {
- TimerBasedWheelEventPhaseInfo();
-}
// Tests that latching breaks when the difference between location of the first
// wheel event in the sequence and the location of the current wheel event is
// larger than some maximum threshold.
-void RenderWidgetHostViewAuraTest::TimerBasedLatchingBreaksWithMouseMove() {
- // The test is valid only when wheel scroll latching is enabled.
- if (wheel_scrolling_mode_ == kWheelScrollingModeNone)
- return;
-
+TEST_F(RenderWidgetHostViewAuraTest, TimerBasedLatchingBreaksWithMouseMove) {
// Set the mouse_wheel_phase_handler_ timer timeout to a large value to make
// sure that the timer is still running when the wheel event with different
// location is sent.
@@ -2137,16 +1972,11 @@ void RenderWidgetHostViewAuraTest::TimerBasedLatchingBreaksWithMouseMove() {
view_->OnMouseEvent(&event2);
base::RunLoop().RunUntilIdle();
events = GetAndResetDispatchedMessages();
- if (wheel_scrolling_mode_ == kWheelScrollLatching)
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- else
- EXPECT_EQ("MouseWheel GestureScrollUpdate", GetMessageNames(events));
+ EXPECT_EQ("MouseWheel GestureScrollUpdate", GetMessageNames(events));
wheel_event = static_cast<const WebMouseWheelEvent*>(
events[0]->ToEvent()->Event()->web_event.get());
EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, wheel_event->phase);
- if (wheel_scrolling_mode_ == kWheelScrollLatching)
- events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
events = GetAndResetDispatchedMessages();
// Send the third wheel event with a location outside of the slop region. The
@@ -2167,23 +1997,11 @@ void RenderWidgetHostViewAuraTest::TimerBasedLatchingBreaksWithMouseMove() {
events[2]->ToEvent()->Event()->web_event.get());
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase);
}
-TEST_F(RenderWidgetHostViewAuraWheelScrollLatchingEnabledTest,
- TimerBasedLatchingBreaksWithMouseMove) {
- TimerBasedLatchingBreaksWithMouseMove();
-}
-TEST_F(RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest,
- TimerBasedLatchingBreaksWithMouseMove) {
- TimerBasedLatchingBreaksWithMouseMove();
-}
// Tests that latching breaks when the current wheel event has different
// modifiers.
-void RenderWidgetHostViewAuraTest::
- TimerBasedLatchingBreaksWithModifiersChange() {
- // The test is valid only when wheel scroll latching is enabled.
- if (wheel_scrolling_mode_ == kWheelScrollingModeNone)
- return;
-
+TEST_F(RenderWidgetHostViewAuraTest,
+ TimerBasedLatchingBreaksWithModifiersChange) {
// Set the mouse_wheel_phase_handler_ timer timeout to a large value to make
// sure that the timer is still running when the wheel event with different
// modifiers is sent.
@@ -2216,16 +2034,11 @@ void RenderWidgetHostViewAuraTest::
view_->OnMouseEvent(&event2);
base::RunLoop().RunUntilIdle();
events = GetAndResetDispatchedMessages();
- if (wheel_scrolling_mode_ == kWheelScrollLatching)
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- else
- EXPECT_EQ("MouseWheel GestureScrollUpdate", GetMessageNames(events));
+ EXPECT_EQ("MouseWheel GestureScrollUpdate", GetMessageNames(events));
wheel_event = static_cast<const WebMouseWheelEvent*>(
events[0]->ToEvent()->Event()->web_event.get());
EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, wheel_event->phase);
- if (wheel_scrolling_mode_ == kWheelScrollLatching)
- events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
events = GetAndResetDispatchedMessages();
// Send the third wheel event with a ctrl key down. The third wheel event will
@@ -2245,24 +2058,12 @@ void RenderWidgetHostViewAuraTest::
events[2]->ToEvent()->Event()->web_event.get());
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase);
}
-TEST_F(RenderWidgetHostViewAuraWheelScrollLatchingEnabledTest,
- TimerBasedLatchingBreaksWithModifiersChange) {
- TimerBasedLatchingBreaksWithModifiersChange();
-}
-TEST_F(RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest,
- TimerBasedLatchingBreaksWithModifiersChange) {
- TimerBasedLatchingBreaksWithModifiersChange();
-}
// Tests that latching breaks when the new wheel event goes a different
// direction from previous wheel events and the previous GSU events are not
// consumed.
-void RenderWidgetHostViewAuraTest::
- TimerBasedLatchingBreaksWithDirectionChange() {
- // The test is valid only when wheel scroll latching is enabled.
- if (wheel_scrolling_mode_ == kWheelScrollingModeNone)
- return;
-
+TEST_F(RenderWidgetHostViewAuraTest,
+ TimerBasedLatchingBreaksWithDirectionChange) {
// Set the mouse_wheel_phase_handler_ timer timeout to a large value to make
// sure that the timer is still running when the wheel event with different
// modifiers is sent.
@@ -2312,21 +2113,9 @@ void RenderWidgetHostViewAuraTest::
events[2]->ToEvent()->Event()->web_event.get());
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase);
}
-TEST_F(RenderWidgetHostViewAuraWheelScrollLatchingEnabledTest,
- TimerBasedLatchingBreaksWithDirectionChange) {
- TimerBasedLatchingBreaksWithDirectionChange();
-}
-TEST_F(RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest,
- TimerBasedLatchingBreaksWithDirectionChange) {
- TimerBasedLatchingBreaksWithDirectionChange();
-}
-
-void RenderWidgetHostViewAuraTest::
- TimerBasedLatchingBreaksWithAutoscrollStart() {
- // The test is valid only when wheel scroll latching is enabled.
- if (wheel_scrolling_mode_ == kWheelScrollingModeNone)
- return;
+TEST_F(RenderWidgetHostViewAuraTest,
+ TimerBasedLatchingBreaksWithAutoscrollStart) {
// Set the mouse_wheel_phase_handler_ timer timeout to a large value to make
// sure that the timer is still running when the Autoscroll starts.
view_->event_handler()->set_mouse_wheel_wheel_phase_handler_timeout(
@@ -2349,7 +2138,7 @@ void RenderWidgetHostViewAuraTest::
events[0]->ToEvent()->Event()->web_event.get());
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase);
events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(view_->GetMouseWheelPhaseHandler()->HasPendingWheelEndEvent());
+ EXPECT_TRUE(GetMouseWheelPhaseHandler()->HasPendingWheelEndEvent());
events = GetAndResetDispatchedMessages();
// Autoscroll start breaks wheel scroll latching sequence by sending the
@@ -2357,7 +2146,7 @@ void RenderWidgetHostViewAuraTest::
// immediately and a GSE will be sent. The next wheel event will start a new
// scrolling sequence.
view_->OnAutoscrollStart();
- EXPECT_FALSE(view_->GetMouseWheelPhaseHandler()->HasPendingWheelEndEvent());
+ EXPECT_FALSE(GetMouseWheelPhaseHandler()->HasPendingWheelEndEvent());
ui::MouseWheelEvent event2(gfx::Vector2d(0, 5), gfx::Point(2, 2),
gfx::Point(2, 2), ui::EventTimeForNow(), 0, 0);
view_->OnMouseEvent(&event2);
@@ -2373,18 +2162,10 @@ void RenderWidgetHostViewAuraTest::
events[2]->ToEvent()->Event()->web_event.get());
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase);
}
-TEST_F(RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest,
- TimerBasedLatchingBreaksWithAutoscrollStart) {
- TimerBasedLatchingBreaksWithAutoscrollStart();
-}
// Tests that a gesture fling start with touchpad source resets wheel phase
// state.
-void RenderWidgetHostViewAuraTest::TouchpadFlingStartResetsWheelPhaseState() {
- // The test is valid only when wheel scroll latching is enabled.
- if (wheel_scrolling_mode_ == kWheelScrollingModeNone)
- return;
-
+TEST_F(RenderWidgetHostViewAuraTest, TouchpadFlingStartResetsWheelPhaseState) {
// Set the mouse_wheel_phase_handler_ timer timeout to a large value to make
// sure that the timer is still running when the touchpad fling start is sent.
view_->event_handler()->set_mouse_wheel_wheel_phase_handler_timeout(
@@ -2436,26 +2217,14 @@ void RenderWidgetHostViewAuraTest::TouchpadFlingStartResetsWheelPhaseState() {
view_->OnScrollEvent(&scroll1);
base::RunLoop().RunUntilIdle();
events = GetAndResetDispatchedMessages();
- if (wheel_scrolling_mode_ == kWheelScrollLatching)
- EXPECT_EQ(1U, events.size());
- else
- EXPECT_EQ(2U, events.size());
+ EXPECT_EQ(2U, events.size());
wheel_event = static_cast<const WebMouseWheelEvent*>(
events[0]->ToEvent()->Event()->web_event.get());
EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, wheel_event->phase);
- if (wheel_scrolling_mode_ == kWheelScrollLatching) {
- events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("GestureScrollUpdate", GetMessageNames(events));
- gesture_event = static_cast<const WebGestureEvent*>(
- events[0]->ToEvent()->Event()->web_event.get());
- events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
- } else { // wheel_scrolling_mode_ == kAsyncWheelEvents
- EXPECT_EQ("MouseWheel GestureScrollUpdate", GetMessageNames(events));
- gesture_event = static_cast<const WebGestureEvent*>(
- events[1]->ToEvent()->Event()->web_event.get());
- events[1]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
- }
+ EXPECT_EQ("MouseWheel GestureScrollUpdate", GetMessageNames(events));
+ gesture_event = static_cast<const WebGestureEvent*>(
+ events[1]->ToEvent()->Event()->web_event.get());
+ events[1]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, gesture_event->GetType());
EXPECT_EQ(0U, gesture_event->data.scroll_update.delta_x);
EXPECT_EQ(15U, gesture_event->data.scroll_update.delta_y);
@@ -2488,21 +2257,64 @@ void RenderWidgetHostViewAuraTest::TouchpadFlingStartResetsWheelPhaseState() {
events[2]->ToEvent()->Event()->web_event.get());
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase);
}
-TEST_F(RenderWidgetHostViewAuraWheelScrollLatchingEnabledTest,
- TouchpadFlingStartResetsWheelPhaseState) {
- TouchpadFlingStartResetsWheelPhaseState();
-}
-TEST_F(RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest,
- TouchpadFlingStartResetsWheelPhaseState) {
- TouchpadFlingStartResetsWheelPhaseState();
+
+// Tests that the touchpad scroll state in mouse wheel phase handler gets reset
+// when a mouse wheel event from an external mouse arrives.
+TEST_F(RenderWidgetHostViewAuraTest, MouseWheelScrollingAfterGFCWithoutGFS) {
+ // Set the mouse_wheel_phase_handler_ timer timeout to a large value to make
+ // sure that the timer is still running when we are checking for the pending
+ // wheel end event after sending ui::MouseWheelEvent.
+ view_->event_handler()->set_mouse_wheel_wheel_phase_handler_timeout(
+ TestTimeouts::action_max_timeout());
+
+ view_->InitAsChild(nullptr);
+ view_->Show();
+ sink_->ClearMessages();
+
+ // When the user puts their fingers down a GFC is received. This will change
+ // the touchpad scroll state in mouse wheel phase handler to may_begin.
+ EXPECT_EQ(
+ content::TOUCHPAD_SCROLL_STATE_UNKNOWN,
+ GetMouseWheelPhaseHandler()->touchpad_scroll_phase_state_for_test());
+ ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL, gfx::Point(2, 2),
+ ui::EventTimeForNow(), 0, 0, 0, 0, 0, 2);
+ view_->OnScrollEvent(&fling_cancel);
+ GetAndResetDispatchedMessages();
+ EXPECT_EQ(
+ content::TOUCHPAD_SCROLL_MAY_BEGIN,
+ GetMouseWheelPhaseHandler()->touchpad_scroll_phase_state_for_test());
+ EXPECT_FALSE(GetMouseWheelPhaseHandler()->HasPendingWheelEndEvent());
+
+ // The user lifts their fingers without doing any touchpad scroll
+ // (ui::ScrollEevent), the touchpad scroll state must still be may_begin since
+ // without touchpad scrolling no GFS is recieved to reset the state.
+ EXPECT_EQ(
+ content::TOUCHPAD_SCROLL_MAY_BEGIN,
+ GetMouseWheelPhaseHandler()->touchpad_scroll_phase_state_for_test());
+
+ // The user starts scrolling by external mouse device.
+ ui::MouseWheelEvent wheel(gfx::Vector2d(0, 5), gfx::Point(2, 2),
+ gfx::Point(2, 2), ui::EventTimeForNow(), 0, 0);
+ view_->OnMouseEvent(&wheel);
+ base::RunLoop().RunUntilIdle();
+ MockWidgetInputHandler::MessageVector events =
+ GetAndResetDispatchedMessages();
+ const WebMouseWheelEvent* wheel_event =
+ static_cast<const WebMouseWheelEvent*>(
+ events[0]->ToEvent()->Event()->web_event.get());
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase);
+
+ // After arrival of the mouse wheel event, the touchpad scroll state must get
+ // reset and the timer based wheel scroll latching must be active.
+ EXPECT_EQ(
+ content::TOUCHPAD_SCROLL_STATE_UNKNOWN,
+ GetMouseWheelPhaseHandler()->touchpad_scroll_phase_state_for_test());
+ EXPECT_TRUE(GetMouseWheelPhaseHandler()->HasPendingWheelEndEvent());
}
-TEST_F(RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest,
+TEST_F(RenderWidgetHostViewAuraTest,
ScrollingWithExternalMouseBreaksTouchpadScrollLatching) {
- // The test is valid only when wheel scroll latching is enabled.
- if (wheel_scrolling_mode_ == kWheelScrollingModeNone)
- return;
-
// Set the mouse_wheel_phase_handler_ timer timeout to a large value to make
// sure that the timer is still running when we are checking for the pending
// wheel end event after sending ui::MouseWheelEvent.
@@ -2572,12 +2384,8 @@ TEST_F(RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest,
EXPECT_TRUE(GetMouseWheelPhaseHandler()->HasPendingWheelEndEvent());
}
-void RenderWidgetHostViewAuraTest::
- GSBWithTouchSourceStopsWheelScrollSequence() {
- // The test is valid only when wheel scroll latching is enabled.
- if (wheel_scrolling_mode_ == kWheelScrollingModeNone)
- return;
-
+TEST_F(RenderWidgetHostViewAuraTest,
+ GSBWithTouchSourceStopsWheelScrollSequence) {
// Set the mouse_wheel_phase_handler_ timer timeout to a large value to make
// sure that the timer is still running when the GSB event with touch source
// is sent.
@@ -2609,6 +2417,16 @@ void RenderWidgetHostViewAuraTest::
EXPECT_EQ(5U, gesture_event->data.scroll_update.delta_y);
events[1]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
+ ui::GestureEventDetails gesture_tap_down_details(ui::ET_GESTURE_TAP_DOWN);
+ gesture_tap_down_details.set_is_source_touch_event_set_non_blocking(true);
+ gesture_tap_down_details.set_device_type(
+ ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent gesture_tap_down(2, 2, 0, ui::EventTimeForNow(),
+ gesture_tap_down_details);
+ view_->OnGestureEvent(&gesture_tap_down);
+ base::RunLoop().RunUntilIdle();
+ events = GetAndResetDispatchedMessages();
+
ui::GestureEventDetails event_details(ui::ET_GESTURE_SCROLL_BEGIN);
event_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
ui::GestureEvent scroll_begin(2, 2, 0, ui::EventTimeForNow(), event_details);
@@ -2637,14 +2455,41 @@ void RenderWidgetHostViewAuraTest::
EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, gesture_event->SourceDevice());
}
-TEST_F(RenderWidgetHostViewAuraWheelScrollLatchingEnabledTest,
- GSBWithTouchSourceStopsWheelScrollSequence) {
- GSBWithTouchSourceStopsWheelScrollSequence();
-}
+TEST_F(RenderWidgetHostViewAuraTest,
+ SyntheticFlingCancelAtTouchpadScrollBegin) {
+ ui::ScrollEvent scroll_event(ui::ET_SCROLL, gfx::Point(2, 2),
+ ui::EventTimeForNow(), 0, 0, 5, 0, 5, 2);
-TEST_F(RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest,
- GSBWithTouchSourceStopsWheelScrollSequence) {
- GSBWithTouchSourceStopsWheelScrollSequence();
+ // Send the beginning scroll event. This should generate a synthetic fling
+ // cancel to cancel any ongoing flings before the start of this scroll.
+ view_->OnScrollEvent(&scroll_event);
+ base::RunLoop().RunUntilIdle();
+ base::Optional<WebGestureEvent> last_gesture =
+ widget_host_->GetAndResetLastForwardedGestureEvent();
+ ASSERT_TRUE(last_gesture);
+ EXPECT_EQ(WebInputEvent::kGestureFlingCancel, last_gesture->GetType());
+
+ // Consume the wheel to prevent gesture scrolls from interfering with the
+ // rest of the test.
+ MockWidgetInputHandler::MessageVector dispatched_events =
+ GetAndResetDispatchedMessages();
+ EXPECT_EQ("MouseWheel", GetMessageNames(dispatched_events));
+ dispatched_events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
+ dispatched_events = GetAndResetDispatchedMessages();
+ EXPECT_EQ(0U, dispatched_events.size());
+
+ // Send a scroll update. A synthetic fling cancel has already been sent for
+ // this sequence, so we should not generate another.
+ view_->OnScrollEvent(&scroll_event);
+ base::RunLoop().RunUntilIdle();
+ last_gesture = widget_host_->GetAndResetLastForwardedGestureEvent();
+ EXPECT_FALSE(last_gesture);
+
+ dispatched_events = GetAndResetDispatchedMessages();
+ EXPECT_EQ("MouseWheel", GetMessageNames(dispatched_events));
+ dispatched_events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
+ dispatched_events = GetAndResetDispatchedMessages();
+ EXPECT_EQ(0U, dispatched_events.size());
}
// Checks that touch-event state is maintained correctly for multiple touch
@@ -2659,6 +2504,8 @@ TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) {
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
view_->OnTouchEvent(&press0);
+ view_->GetFocusedWidget()->input_router()->OnSetTouchAction(
+ cc::kTouchActionAuto);
base::RunLoop().RunUntilIdle();
MockWidgetInputHandler::MessageVector events =
@@ -3188,7 +3035,7 @@ viz::CompositorFrame MakeDelegatedFrame(float scale_factor,
// This test verifies that returned resources do not require a pending ack.
TEST_F(RenderWidgetHostViewAuraTest, ReturnedResources) {
// TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ if (!features::IsAshInBrowserProcess())
return;
gfx::Size view_size(100, 100);
@@ -3219,9 +3066,12 @@ TEST_F(RenderWidgetHostViewAuraTest, ReturnedResources) {
// This test verifies that when the CompositorFrameSink changes, the old
// resources are not returned.
TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
+ // https://crbug.com/844469
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
+ !features::IsAshInBrowserProcess()) {
return;
+ }
viz::FakeSurfaceObserver manager_observer;
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
@@ -3361,7 +3211,7 @@ TEST_F(RenderWidgetHostViewAuraTest, ZeroSizeStillGetsLocalSurfaceId) {
TEST_F(RenderWidgetHostViewAuraTest, BackgroundColorMatchesCompositorFrame) {
// TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ if (!features::IsAshInBrowserProcess())
return;
gfx::Size frame_size(100, 100);
@@ -3377,7 +3227,7 @@ TEST_F(RenderWidgetHostViewAuraTest, BackgroundColorMatchesCompositorFrame) {
cc::RenderFrameMetadata metadata;
metadata.root_background_color = SK_ColorRED;
view_->SetRenderFrameMetadata(metadata);
- view_->OnRenderFrameMetadataChanged();
+ view_->OnRenderFrameMetadataChangedAfterActivation();
ui::Layer* parent_layer = view_->GetNativeView()->layer();
EXPECT_EQ(gfx::Rect(0, 0, 100, 100), parent_layer->bounds());
@@ -3398,7 +3248,7 @@ TEST_F(RenderWidgetHostViewAuraTest, BackgroundColorOrder) {
cc::RenderFrameMetadata metadata;
metadata.root_background_color = SK_ColorWHITE;
view_->SetRenderFrameMetadata(metadata);
- view_->OnRenderFrameMetadataChanged();
+ view_->OnRenderFrameMetadataChangedAfterActivation();
ASSERT_TRUE(view_->GetBackgroundColor());
EXPECT_EQ(static_cast<unsigned>(SK_ColorWHITE), *view_->GetBackgroundColor());
@@ -3523,9 +3373,12 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_Resize) {
}
TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
+ // https://crbug.com/844469
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
+ !features::IsAshInBrowserProcess()) {
return;
+ }
gfx::Rect view_rect(100, 100);
gfx::Size frame_size = view_rect.size();
@@ -3583,10 +3436,6 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
// then the fallback is dropped.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DropFallbackWhenHidden) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
- return;
-
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -3601,21 +3450,16 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
EXPECT_FALSE(view_->HasPrimarySurface());
// Submitting a CompositorFrame should not update the fallback SurfaceId
- view_->SubmitCompositorFrame(
- kArbitraryLocalSurfaceId,
- MakeDelegatedFrame(1.f, gfx::Size(400, 400), gfx::Rect(400, 400)),
- base::nullopt);
+ viz::SurfaceId surface_id(view_->GetFrameSinkId(), kArbitraryLocalSurfaceId);
+ view_->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id, 1.f, gfx::Size(400, 400)));
EXPECT_FALSE(view_->HasPrimarySurface());
EXPECT_FALSE(view_->HasFallbackSurface());
}
// This test verifies that the primary SurfaceId is populated on resize and
-// the fallback SurfaceId is populated on SubmitCompositorFrame.
+// the fallback SurfaceId is populated in OnFirstSurfaceActivation.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
- return;
-
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -3637,12 +3481,14 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
EXPECT_EQ(gfx::Size(400, 400),
view_->delegated_frame_host_->CurrentFrameSizeInDipForTesting());
+ // Fallback SurfaceId should be updated in OnFirstSurfaceActivation.
// Submitting a CompositorFrame should update the fallback SurfaceId
- view_->SubmitCompositorFrame(
- kArbitraryLocalSurfaceId,
- MakeDelegatedFrame(1.f, gfx::Size(400, 400), gfx::Rect(400, 400)),
- base::nullopt);
+ viz::SurfaceId surface_id(view_->GetFrameSinkId(),
+ view_->GetLocalSurfaceId());
+ view_->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id, 1.f, gfx::Size(400, 400)));
EXPECT_EQ(gfx::Size(400, 400), view_->window_->layer()->size());
+ EXPECT_EQ(surface_id, *view_->window_->layer()->GetFallbackSurfaceId());
}
// This test verifies that the primary SurfaceId is updated on device scale
@@ -3650,7 +3496,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DeviceScaleFactorChanges) {
// TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ if (!features::IsAshInBrowserProcess())
return;
view_->InitAsChild(nullptr);
@@ -3677,9 +3523,12 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// the current surface) does not crash,
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
CompositorFrameSinkChange) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
+ // https://crbug.com/844469
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
+ !features::IsAshInBrowserProcess()) {
return;
+ }
gfx::Rect view_rect(100, 100);
gfx::Size frame_size = view_rect.size();
@@ -3711,10 +3560,6 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// RenderWidgetHostViewAuraTest.DiscardDelegatedFrame.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DiscardDelegatedFrames) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
- return;
-
view_->InitAsChild(nullptr);
size_t max_renderer_frames =
@@ -3755,9 +3600,10 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
views[i]->Show();
ASSERT_TRUE(views[i]->HasPrimarySurface());
ASSERT_FALSE(views[i]->HasFallbackSurface());
- views[i]->SubmitCompositorFrame(
- views[i]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
+ viz::SurfaceId surface_id(views[i]->GetFrameSinkId(),
+ views[i]->GetLocalSurfaceId());
+ views[i]->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id, 1.f, frame_size));
ASSERT_TRUE(views[i]->HasPrimarySurface());
EXPECT_TRUE(views[i]->HasFallbackSurface());
views[i]->Hide();
@@ -3775,9 +3621,10 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
EXPECT_TRUE(views[1]->HasFallbackSurface());
// Swap a frame on it, it should evict the next LRU [1].
- views[0]->SubmitCompositorFrame(
- views[0]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
+ viz::SurfaceId surface_id0(views[0]->GetFrameSinkId(),
+ views[0]->GetLocalSurfaceId());
+ views[0]->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id0, 1.f, frame_size));
EXPECT_TRUE(views[0]->HasFallbackSurface());
EXPECT_FALSE(views[1]->HasFallbackSurface());
views[0]->Hide();
@@ -3785,9 +3632,10 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// LRU renderer is [1], which is still hidden. Showing it and submitting a
// CompositorFrame to it should evict the next LRU [2].
views[1]->Show();
- views[1]->SubmitCompositorFrame(
- views[1]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
+ viz::SurfaceId surface_id1(views[1]->GetFrameSinkId(),
+ views[1]->GetLocalSurfaceId());
+ views[1]->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id1, 1.f, frame_size));
EXPECT_TRUE(views[0]->HasFallbackSurface());
EXPECT_TRUE(views[1]->HasFallbackSurface());
EXPECT_FALSE(views[2]->HasFallbackSurface());
@@ -3800,25 +3648,24 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
views[i]->Show();
// The renderers who don't have a frame should be waiting. The ones that
// have a frame should not.
- views[i]->SubmitCompositorFrame(
- views[i]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
+ viz::SurfaceId surface_id(views[i]->GetFrameSinkId(),
+ views[i]->GetLocalSurfaceId());
+ views[i]->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id, 1.f, frame_size));
EXPECT_TRUE(views[i]->HasFallbackSurface());
}
EXPECT_FALSE(views[0]->HasFallbackSurface());
// Swap a frame on [0], it should be evicted immediately.
- views[0]->SubmitCompositorFrame(
- views[0]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
+ views[0]->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id0, 1.f, frame_size));
EXPECT_FALSE(views[0]->HasFallbackSurface());
// Make [0] visible, and swap a frame on it. Nothing should be evicted
// although we're above the limit.
views[0]->Show();
- views[0]->SubmitCompositorFrame(
- views[0]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
+ views[0]->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id0, 1.f, frame_size));
for (size_t i = 0; i < renderer_count; ++i)
EXPECT_TRUE(views[i]->HasFallbackSurface()) << i;
@@ -3839,9 +3686,8 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
EXPECT_FALSE(views[1]->HasFallbackSurface());
// Show it, it should block until we give it a frame.
views[1]->Show();
- views[1]->SubmitCompositorFrame(
- views[1]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, size2, gfx::Rect(size2)), base::nullopt);
+ views[1]->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id1, 1.f, frame_size));
for (size_t i = 0; i < renderer_count; ++i) {
views[i]->Destroy();
@@ -3850,10 +3696,6 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
}
TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
- return;
-
view_->InitAsChild(nullptr);
size_t max_renderer_frames =
@@ -3889,10 +3731,10 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
// occur because all frames are visible.
for (size_t i = 0; i < renderer_count; ++i) {
views[i]->Show();
- views[i]->SubmitCompositorFrame(
- i ? parent_local_surface_id_allocator_.GenerateId()
- : kArbitraryLocalSurfaceId,
- MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
+ viz::SurfaceId surface_id(views[i]->GetFrameSinkId(),
+ views[i]->GetLocalSurfaceId());
+ views[i]->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id, 1.f, frame_size));
EXPECT_TRUE(views[i]->HasFallbackSurface());
}
@@ -3902,9 +3744,10 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
// If we lock [0] before hiding it, then [0] should not be evicted.
views[0]->Show();
- views[0]->SubmitCompositorFrame(
- kArbitraryLocalSurfaceId, MakeDelegatedFrame(1.f, frame_size, view_rect),
- base::nullopt);
+ viz::SurfaceId surface_id(views[0]->GetFrameSinkId(),
+ views[0]->GetLocalSurfaceId());
+ views[0]->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id, 1.f, frame_size));
EXPECT_TRUE(views[0]->HasFallbackSurface());
views[0]->GetDelegatedFrameHost()->LockResources();
views[0]->Hide();
@@ -3923,10 +3766,6 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
// Test that changing the memory pressure should delete saved frames. This test
// only applies to ChromeOS.
TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithMemoryPressure) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
- return;
-
view_->InitAsChild(nullptr);
// The test logic below relies on having max_renderer_frames > 2. By default,
@@ -3967,9 +3806,10 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithMemoryPressure) {
// occur because all frames are visible.
for (size_t i = 0; i < renderer_count; ++i) {
views[i]->Show();
- views[i]->SubmitCompositorFrame(
- kArbitraryLocalSurfaceId,
- MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
+ viz::SurfaceId surface_id(views[i]->GetFrameSinkId(),
+ kArbitraryLocalSurfaceId);
+ views[i]->delegated_frame_host_->OnFirstSurfaceActivation(
+ viz::SurfaceInfo(surface_id, 1.f, frame_size));
EXPECT_TRUE(views[i]->HasFallbackSurface());
}
@@ -4027,9 +3867,12 @@ TEST_F(RenderWidgetHostViewAuraTest, SourceEventTypeExistsInLatencyInfo) {
// SwapCompositorFrame and OnDidNotProduceFrame IPCs through DelegatedFrameHost
// and its CompositorFrameSinkSupport.
TEST_F(RenderWidgetHostViewAuraTest, ForwardsBeginFrameAcks) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
+ // https://crbug.com/844469
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
+ !features::IsAshInBrowserProcess()) {
return;
+ }
gfx::Rect view_rect(100, 100);
gfx::Size frame_size = view_rect.size();
@@ -4124,15 +3967,15 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventPositionsArentRounded) {
}
// Tests that non-precise mouse-wheel events do not initiate overscroll.
-void RenderWidgetHostViewAuraOverscrollTest::WheelNotPreciseScrollEvent() {
+TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelNotPreciseScrollEvent) {
SetUpOverscrollEnvironment();
// Simulate wheel event. Does not cross start threshold.
- SimulateWheelEventPossiblyIncludingPhase(
- -5, 0, 0, false, WebMouseWheelEvent::kPhaseBegan); // sent directly
+ SimulateWheelEvent(-5, 0, 0, false,
+ WebMouseWheelEvent::kPhaseBegan); // sent directly
// Simulate wheel event. Crosses start threshold.
- SimulateWheelEventPossiblyIncludingPhase(
- -70, 1, 0, false, WebMouseWheelEvent::kPhaseChanged); // enqueued
+ SimulateWheelEvent(-70, 1, 0, false,
+ WebMouseWheelEvent::kPhaseChanged); // enqueued
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
MockWidgetInputHandler::MessageVector events =
@@ -4148,64 +3991,36 @@ void RenderWidgetHostViewAuraOverscrollTest::WheelNotPreciseScrollEvent() {
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- ExpectGestureScrollEndForWheelScrolling(false);
- SendNotConsumedAcks(events);
- events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
- }
-
SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- SimulateWheelEventWithPhase(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded);
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel GestureScrollEnd", GetMessageNames(events));
- } else if (wheel_scroll_latching_enabled_) {
- SimulateWheelEventWithPhase(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded);
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- SendNotConsumedAcks(events);
- ExpectGestureScrollEndForWheelScrolling(true);
- } else {
- ExpectGestureScrollEndForWheelScrolling(true);
- }
+ SimulateWheelEvent(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded);
+ events = GetAndResetDispatchedMessages();
+ EXPECT_EQ("MouseWheel GestureScrollEnd", GetMessageNames(events));
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
}
-TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelNotPreciseScrollEvent) {
- WheelNotPreciseScrollEvent();
-}
-TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest,
- WheelNotPreciseScrollEvent) {
- WheelNotPreciseScrollEvent();
-}
-TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest,
- WheelNotPreciseScrollEvent) {
- WheelNotPreciseScrollEvent();
-}
-
// Tests that precise mouse-wheel events initiate overscroll and a mouse move
// will cancel it.
-void RenderWidgetHostViewAuraOverscrollTest::WheelScrollEventOverscrolls() {
+TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelScrollEventOverscrolls) {
SetUpOverscrollEnvironment();
// Simulate wheel events. Do not cross start threshold.
- SimulateWheelEventPossiblyIncludingPhase(
- -5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan); // sent directly
- SimulateWheelEventPossiblyIncludingPhase(
- -10, 1, 0, true, WebMouseWheelEvent::kPhaseChanged); // enqueued
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(-5, 0, 0, true,
+ WebMouseWheelEvent::kPhaseBegan); // sent directly
+ SimulateWheelEvent(-10, 1, 0, true,
+ WebMouseWheelEvent::kPhaseChanged); // enqueued
+ SimulateWheelEvent(
-10, -3, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(
-15, -1, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
// Simulate wheel events. Cross start threshold.
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(
-30, -3, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(
-20, 6, 1, true,
WebMouseWheelEvent::kPhaseChanged); // enqueued, different modifiers
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
@@ -4222,22 +4037,9 @@ void RenderWidgetHostViewAuraOverscrollTest::WheelScrollEventOverscrolls() {
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- ExpectGestureScrollEndForWheelScrolling(false);
- // 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 ScrollUpdate event will be sent to the
- // renderer.
- SendNotConsumedAcks(events);
- events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 1);
- }
SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
ExpectGestureScrollEndForWheelScrolling(false);
SendNotConsumedAcks(events);
- ExpectGestureScrollEventsAfterMouseWheelAckWhenOverscrolling();
EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source());
@@ -4256,40 +4058,29 @@ void RenderWidgetHostViewAuraOverscrollTest::WheelScrollEventOverscrolls() {
events = GetAndResetDispatchedMessages();
EXPECT_EQ("MouseMove", GetMessageNames(events));
}
-TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelScrollEventOverscrolls) {
- WheelScrollEventOverscrolls();
-}
-TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest,
- WheelScrollEventOverscrolls) {
- WheelScrollEventOverscrolls();
-}
-TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest,
- WheelScrollEventOverscrolls) {
- WheelScrollEventOverscrolls();
-}
// Tests that if some scroll events are consumed towards the start, then
// subsequent scrolls do not overscroll.
-void RenderWidgetHostViewAuraOverscrollTest::
- WheelScrollConsumedDoNotOverscroll() {
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ WheelScrollConsumedDoNotOverscroll) {
SetUpOverscrollEnvironment();
// Simulate wheel events. Do not cross start threshold.
- SimulateWheelEventPossiblyIncludingPhase(
- -5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan); // sent directly
- SimulateWheelEventPossiblyIncludingPhase(
- -10, -1, 0, true, WebMouseWheelEvent::kPhaseChanged); // enqueued
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(-5, 0, 0, true,
+ WebMouseWheelEvent::kPhaseBegan); // sent directly
+ SimulateWheelEvent(-10, -1, 0, true,
+ WebMouseWheelEvent::kPhaseChanged); // enqueued
+ SimulateWheelEvent(
-10, -3, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(
-15, -1, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
// Simulate wheel events. Cross start threshold.
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(
-30, -3, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(
-20, 6, 1, true,
WebMouseWheelEvent::kPhaseChanged); // enqueued, different modifiers
@@ -4308,68 +4099,24 @@ void RenderWidgetHostViewAuraOverscrollTest::
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_CONSUMED);
- ExpectGestureScrollEndForWheelScrolling(false);
- // 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.
- SendNotConsumedAcks(events);
- events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 1);
- }
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
-
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
// The GSU events are coalesced. This is the ack for the coalesced event.
// Since it is the first GSU, the ack should be consumed.
SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_CONSUMED);
- } else {
- SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- events = ExpectGestureScrollEndForWheelScrolling(false);
- SendNotConsumedAcks(events);
- events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
- SendNotConsumedAcks(events);
- }
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- SimulateWheelEventWithPhase(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded);
+ SimulateWheelEvent(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded);
events = GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel GestureScrollEnd", GetMessageNames(events));
- } else if (wheel_scroll_latching_enabled_) {
- SimulateWheelEventWithPhase(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded);
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- SendNotConsumedAcks(events);
- events = ExpectGestureScrollEndForWheelScrolling(true);
- } else {
- events = ExpectGestureScrollEndForWheelScrolling(true);
- }
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
}
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- WheelScrollConsumedDoNotOverscroll) {
- WheelScrollConsumedDoNotOverscroll();
-}
-TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest,
- WheelScrollConsumedDoNotOverscroll) {
- WheelScrollConsumedDoNotOverscroll();
-}
-TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest,
- WheelScrollConsumedDoNotOverscroll) {
- WheelScrollConsumedDoNotOverscroll();
-}
// Tests that wheel-scrolling correctly turns overscroll on and off.
-void RenderWidgetHostViewAuraOverscrollTest::WheelScrollOverscrollToggle() {
+TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelScrollOverscrollToggle) {
SetUpOverscrollEnvironment();
// 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.
- SimulateWheelEventPossiblyIncludingPhase(10, 0, 0, true,
- WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEvent(10, 0, 0, true, WebMouseWheelEvent::kPhaseBegan);
MockWidgetInputHandler::MessageVector events =
GetAndResetDispatchedMessages();
@@ -4387,16 +4134,8 @@ void RenderWidgetHostViewAuraOverscrollTest::WheelScrollOverscrollToggle() {
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
// Scroll some more so as to not overscroll.
- SimulateWheelEventPossiblyIncludingPhase(10, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- events = ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
- } else {
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- SendNotConsumedAcks(events);
- events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
- }
+ SimulateWheelEvent(10, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);
+ events = ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
ExpectGestureScrollEndForWheelScrolling(false);
@@ -4405,16 +4144,9 @@ void RenderWidgetHostViewAuraOverscrollTest::WheelScrollOverscrollToggle() {
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
// Scroll some more to initiate an overscroll.
- SimulateWheelEventPossiblyIncludingPhase(50, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- events = ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
- } else {
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- SendNotConsumedAcks(events);
- events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
- }
+ SimulateWheelEvent(50, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);
+
+ events = ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
ExpectGestureScrollEndForWheelScrolling(false);
@@ -4427,29 +4159,18 @@ void RenderWidgetHostViewAuraOverscrollTest::WheelScrollOverscrollToggle() {
EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
// Scroll in the reverse direction enough to abort the overscroll.
- SimulateWheelEventPossiblyIncludingPhase(-20, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
+ SimulateWheelEvent(-20, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);
events = GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel", GetMessageNames(events));
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- SendNotConsumedAcks(events);
- ExpectGestureScrollEventsAfterMouseWheelAckWhenOverscrolling();
- }
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
// Continue to scroll in the reverse direction.
- SimulateWheelEventPossiblyIncludingPhase(-20, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
+ SimulateWheelEvent(-20, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);
events = GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel", GetMessageNames(events));
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- SendNotConsumedAcks(events);
- ExpectGestureScrollEventsAfterMouseWheelAckWhenOverscrolling();
- }
-
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
@@ -4457,27 +4178,13 @@ void RenderWidgetHostViewAuraOverscrollTest::WheelScrollOverscrollToggle() {
// Continue to scroll in the reverse direction enough to initiate overscroll
// in that direction. However, overscroll should not be initiated as the
// overscroll mode is locked to east mode.
- SimulateWheelEventPossiblyIncludingPhase(-65, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
+ SimulateWheelEvent(-65, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);
events = GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel", GetMessageNames(events));
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- SendNotConsumedAcks(events);
- ExpectGestureScrollEventsAfterMouseWheelAckWhenOverscrolling();
- }
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- SimulateWheelEventWithPhase(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded);
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel GestureScrollEnd", GetMessageNames(events));
- } else if (wheel_scroll_latching_enabled_) {
- SimulateWheelEventWithPhase(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded);
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- SendNotConsumedAcks(events);
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("GestureScrollEnd", GetMessageNames(events));
- }
+ SimulateWheelEvent(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded);
+ events = GetAndResetDispatchedMessages();
+ EXPECT_EQ("MouseWheel GestureScrollEnd", GetMessageNames(events));
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
@@ -4486,26 +4193,15 @@ void RenderWidgetHostViewAuraOverscrollTest::WheelScrollOverscrollToggle() {
EXPECT_EQ(0.f, overscroll_delegate()->delta_x());
EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
}
-TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelScrollOverscrollToggle) {
- WheelScrollOverscrollToggle();
-}
-TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest,
- WheelScrollOverscrollToggle) {
- WheelScrollOverscrollToggle();
-}
-TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest,
- WheelScrollOverscrollToggle) {
- WheelScrollOverscrollToggle();
-}
// Tests that a small fling after overscroll is initiated aborts the overscroll.
-void RenderWidgetHostViewAuraOverscrollTest::ScrollEventsOverscrollWithFling() {
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ ScrollEventsOverscrollWithFling) {
SetUpOverscrollEnvironment();
// 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.
- SimulateWheelEventPossiblyIncludingPhase(10, 0, 0, true,
- WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEvent(10, 0, 0, true, WebMouseWheelEvent::kPhaseBegan);
MockWidgetInputHandler::MessageVector events =
GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel", GetMessageNames(events));
@@ -4521,32 +4217,18 @@ void RenderWidgetHostViewAuraOverscrollTest::ScrollEventsOverscrollWithFling() {
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
// Scroll some more so as to not overscroll.
- SimulateWheelEventPossiblyIncludingPhase(20, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
- } else {
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- SendNotConsumedAcks(events);
- events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
- }
+ SimulateWheelEvent(20, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);
+ ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
+
SendNotConsumedAcks(events);
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
// Scroll some more to initiate an overscroll.
- SimulateWheelEventPossiblyIncludingPhase(40, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
- } else {
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- SendNotConsumedAcks(events);
- events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
- }
+ SimulateWheelEvent(40, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);
+ ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
+
SendNotConsumedAcks(events);
ExpectGestureScrollEndForWheelScrolling(false);
@@ -4579,29 +4261,16 @@ void RenderWidgetHostViewAuraOverscrollTest::ScrollEventsOverscrollWithFling() {
}
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
}
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- ScrollEventsOverscrollWithFling) {
- ScrollEventsOverscrollWithFling();
-}
-TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest,
- ScrollEventsOverscrollWithFling) {
- ScrollEventsOverscrollWithFling();
-}
-TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest,
- ScrollEventsOverscrollWithFling) {
- ScrollEventsOverscrollWithFling();
-}
// Same as ScrollEventsOverscrollWithFling, but with zero velocity. Checks that
// the zero-velocity fling does not reach the renderer.
-void RenderWidgetHostViewAuraOverscrollTest::
- ScrollEventsOverscrollWithZeroFling() {
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ ScrollEventsOverscrollWithZeroFling) {
SetUpOverscrollEnvironment();
// 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.
- SimulateWheelEventPossiblyIncludingPhase(10, 0, 0, true,
- WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEvent(10, 0, 0, true, WebMouseWheelEvent::kPhaseBegan);
MockWidgetInputHandler::MessageVector events =
GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel", GetMessageNames(events));
@@ -4617,16 +4286,8 @@ void RenderWidgetHostViewAuraOverscrollTest::
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
// Scroll some more so as to not overscroll.
- SimulateWheelEventPossiblyIncludingPhase(20, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
- } else {
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- SendNotConsumedAcks(events);
- ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
- }
+ SimulateWheelEvent(20, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);
+ ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
ExpectGestureScrollEndForWheelScrolling(false);
@@ -4635,16 +4296,8 @@ void RenderWidgetHostViewAuraOverscrollTest::
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
// Scroll some more to initiate an overscroll.
- SimulateWheelEventPossiblyIncludingPhase(40, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
- } else {
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- SendNotConsumedAcks(events);
- ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
- }
+ SimulateWheelEvent(40, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);
+ ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
SendNotConsumedAcks(events);
ExpectGestureScrollEndForWheelScrolling(false);
@@ -4678,18 +4331,6 @@ void RenderWidgetHostViewAuraOverscrollTest::
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
}
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- ScrollEventsOverscrollWithZeroFling) {
- ScrollEventsOverscrollWithZeroFling();
-}
-TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest,
- ScrollEventsOverscrollWithZeroFling) {
- ScrollEventsOverscrollWithZeroFling();
-}
-TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest,
- ScrollEventsOverscrollWithZeroFling) {
- ScrollEventsOverscrollWithZeroFling();
-}
// Tests that a fling in the opposite direction of the overscroll cancels the
// overscroll instead of completing it.
@@ -4705,6 +4346,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
SetUpOverscrollEnvironment();
{
+ PressAndSetTouchActionAuto();
// Start and end a gesture in the same direction without processing the
// gesture events in the renderer. This should initiate and complete an
// overscroll.
@@ -4727,9 +4369,11 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ("GestureScrollEnd", GetMessageNames(events));
EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->completed_mode());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ ReleaseAndResetDispatchedMessages();
}
{
+ PressAndSetTouchActionAuto();
// Start over, except instead of ending the gesture with ScrollEnd, end it
// with a FlingStart, with velocity in the reverse direction. This should
// initiate an overscroll, the overscroll mode should get reset after the
@@ -4762,6 +4406,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(17);
widget_host_->ProgressFlingIfNeeded(progress_time);
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ ReleaseAndResetDispatchedMessages();
}
}
@@ -4771,6 +4416,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
TEST_F(RenderWidgetHostViewAuraOverscrollTest, GestureScrollOverscrolls) {
SetUpOverscrollEnvironment();
+ PressAndSetTouchActionAuto();
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
MockWidgetInputHandler::MessageVector events =
@@ -4819,6 +4465,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, GestureScrollOverscrolls) {
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ ReleaseAndResetDispatchedMessages();
}
// Tests that when a cap is set for overscroll delta, extra overscroll delta is
@@ -4826,6 +4473,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, GestureScrollOverscrolls) {
TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDeltaCap) {
SetUpOverscrollEnvironment();
+ PressAndSetTouchActionAuto();
// Set overscroll cap and start scrolling.
overscroll_delegate()->set_delta_cap(50);
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
@@ -4884,6 +4532,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDeltaCap) {
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ ReleaseAndResetDispatchedMessages();
}
// Tests that if the page is scrolled because of a scroll-gesture, then that
@@ -4891,6 +4540,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDeltaCap) {
TEST_F(RenderWidgetHostViewAuraOverscrollTest, GestureScrollConsumed) {
SetUpOverscrollEnvironment();
+ PressAndSetTouchActionAuto();
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
SimulateGestureScrollUpdateEvent(10, 0, 0);
@@ -4916,6 +4566,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, GestureScrollConsumed) {
SendNotConsumedAcks(events);
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
+ ReleaseAndResetDispatchedMessages();
}
// Tests that the overscroll controller plays nice with touch-scrolls and the
@@ -4924,6 +4575,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
GestureScrollDebounceOverscrolls) {
SetUpOverscrollEnvironmentWithDebounce(100);
+ PressAndSetTouchActionAuto();
// Start scrolling. Receive ACK as it being processed.
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
@@ -4944,7 +4596,9 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
MockWidgetInputHandler::MessageVector second_scroll_update_events =
GetAndResetDispatchedMessages();
EXPECT_EQ(0U, second_scroll_update_events.size());
+ ReleaseAndResetDispatchedMessages();
+ PressAndSetTouchActionAuto();
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
second_scroll_update_events = GetAndResetDispatchedMessages();
@@ -4993,6 +4647,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(65.f, overscroll_delta_x());
EXPECT_EQ(15.f, overscroll_delegate()->delta_x());
EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
+ ReleaseAndResetDispatchedMessages();
}
// Tests that the gesture debounce timer plays nice with the overscroll
@@ -5001,6 +4656,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
GestureScrollDebounceTimerOverscroll) {
SetUpOverscrollEnvironmentWithDebounce(10);
+ PressAndSetTouchActionAuto();
// Start scrolling. Receive ACK as it being processed.
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
@@ -5018,6 +4674,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(0U, GetAndResetDispatchedMessages().size());
+ ReleaseAndResetDispatchedMessages();
// Receive ACK for the scroll-update event.
SendNotConsumedAcks(events);
@@ -5052,6 +4709,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) {
// The test sends an intermingled sequence of touch and gesture events.
PressTouchPoint(0, 1);
SendTouchEvent();
+ widget_host_->input_router()->OnSetTouchAction(cc::kTouchActionAuto);
MockWidgetInputHandler::MessageVector events =
GetAndResetDispatchedMessages();
EXPECT_EQ("TouchStart", GetMessageNames(events));
@@ -5172,6 +4830,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
SetUpOverscrollEnvironmentWithDebounce(10);
widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
+ PressAndSetTouchActionAuto();
// Start scrolling. Receive ACK as it being processed.
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
@@ -5215,7 +4874,9 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->completed_mode());
events = GetAndResetDispatchedMessages();
EXPECT_EQ("GestureScrollEnd", GetMessageNames(events));
+ ReleaseAndResetDispatchedMessages();
+ PressAndSetTouchActionAuto();
// Start scrolling. Receive ACK as it being processed.
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
@@ -5256,6 +4917,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->completed_mode());
events = GetAndResetDispatchedMessages();
EXPECT_EQ("GestureScrollEnd", GetMessageNames(events));
+ ReleaseAndResetDispatchedMessages();
}
// Tests that after touchscreen overscroll is initiated, scrolling in the
@@ -5265,6 +4927,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDirectionChange) {
SetUpOverscrollEnvironmentWithDebounce(100);
+ PressAndSetTouchActionAuto();
// Start scrolling. Receive ACK as it being processed.
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
@@ -5300,12 +4963,14 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDirectionChange) {
EXPECT_EQ(0U, events.size());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
+ ReleaseAndResetDispatchedMessages();
}
TEST_F(RenderWidgetHostViewAuraOverscrollTest,
CompleteOverscrollOnGestureScrollEndAck) {
SetUpOverscrollEnvironment();
+ PressAndSetTouchActionAuto();
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
MockWidgetInputHandler::MessageVector events =
@@ -5332,12 +4997,14 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->completed_mode());
+ ReleaseAndResetDispatchedMessages();
}
TEST_F(RenderWidgetHostViewAuraOverscrollTest,
InterleavedScrollUpdateAckAndScrollEnd) {
SetUpOverscrollEnvironment();
+ PressAndSetTouchActionAuto();
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
SimulateGestureScrollUpdateEvent(30, -5, 0);
@@ -5368,19 +5035,19 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(2U, overscroll_delegate()->historical_modes().size());
EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->historical_modes().at(0));
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->historical_modes().at(1));
+ ReleaseAndResetDispatchedMessages();
}
// Tests that after touchpad overscroll is initiated, scrolling in the opposite
// direction ends the overscroll in the original direction without initiating
// overscroll in the opposite direction. The scroll-update events should still
// be consumed to prevent content scroll.
-void RenderWidgetHostViewAuraOverscrollTest::
- OverscrollDirectionChangeMouseWheel() {
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ OverscrollDirectionChangeMouseWheel) {
SetUpOverscrollEnvironment();
// Send wheel event and receive ack as not consumed.
- SimulateWheelEventPossiblyIncludingPhase(125, -5, 0, true,
- WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEvent(125, -5, 0, true, WebMouseWheelEvent::kPhaseBegan);
MockWidgetInputHandler::MessageVector events =
GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel", GetMessageNames(events));
@@ -5400,15 +5067,10 @@ void RenderWidgetHostViewAuraOverscrollTest::
// Send another wheel event, but in the reverse direction. Although the
// overscroll controller is not triggering overscroll, it will consume the
// ScrollUpdate event to prevent content scroll.
- SimulateWheelEventPossiblyIncludingPhase(-260, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
+ SimulateWheelEvent(-260, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);
events = GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel", GetMessageNames(events));
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- SendNotConsumedAcks(events);
- ExpectGestureScrollEventsAfterMouseWheelAckWhenOverscrolling();
- }
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
@@ -5419,48 +5081,31 @@ void RenderWidgetHostViewAuraOverscrollTest::
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- SimulateWheelEventPossiblyIncludingPhase(-20, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
+ SimulateWheelEvent(-20, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);
events = GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel", GetMessageNames(events));
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- SendNotConsumedAcks(events);
- ExpectGestureScrollEventsAfterMouseWheelAckWhenOverscrolling();
- }
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
}
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- OverscrollDirectionChangeMouseWheel) {
- OverscrollDirectionChangeMouseWheel();
-}
-TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest,
- OverscrollDirectionChangeMouseWheel) {
- OverscrollDirectionChangeMouseWheel();
-}
-TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest,
- OverscrollDirectionChangeMouseWheel) {
- OverscrollDirectionChangeMouseWheel();
-}
// Tests that mouse-move completes overscoll if it has passed activation
// threshold and aborts it otherwise.
-void RenderWidgetHostViewAuraOverscrollTest::OverscrollMouseMoveCompletion() {
+TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollMouseMoveCompletion) {
SetUpOverscrollEnvironment();
- SimulateWheelEventPossiblyIncludingPhase(
- -5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan); // sent directly
- SimulateWheelEventPossiblyIncludingPhase(
- -10, 0, 0, true, WebMouseWheelEvent::kPhaseChanged); // enqueued
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(-5, 0, 0, true,
+ WebMouseWheelEvent::kPhaseBegan); // sent directly
+ SimulateWheelEvent(-10, 0, 0, true,
+ WebMouseWheelEvent::kPhaseChanged); // enqueued
+ SimulateWheelEvent(
-10, -3, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(
-15, -1, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(
-30, -3, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
@@ -5479,14 +5124,6 @@ void RenderWidgetHostViewAuraOverscrollTest::OverscrollMouseMoveCompletion() {
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- ExpectGestureScrollEndForWheelScrolling(false);
- SendNotConsumedAcks(events);
- // Receive ACK for the second (coalesced) event as not processed. This will
- // start an overcroll gesture.
- ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
- }
-
SendNotConsumedAcks(events);
ExpectGestureScrollEndForWheelScrolling(false);
@@ -5514,6 +5151,7 @@ void RenderWidgetHostViewAuraOverscrollTest::OverscrollMouseMoveCompletion() {
SendNotConsumedAcks(events);
// Now try with gestures.
+ PressAndSetTouchActionAuto();
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
@@ -5542,38 +5180,28 @@ void RenderWidgetHostViewAuraOverscrollTest::OverscrollMouseMoveCompletion() {
events = GetAndResetDispatchedMessages();
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
EXPECT_EQ("GestureScrollEnd", GetMessageNames(events));
+ ReleaseAndResetDispatchedMessages();
// Move mouse some more. The mouse-move events should reach the renderer.
SimulateMouseMove(5, 10, 0);
events = GetAndResetDispatchedMessages();
EXPECT_EQ("MouseMove", GetMessageNames(events));
}
-TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollMouseMoveCompletion) {
- OverscrollMouseMoveCompletion();
-}
-TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest,
- OverscrollMouseMoveCompletion) {
- OverscrollMouseMoveCompletion();
-}
-TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest,
- OverscrollMouseMoveCompletion) {
- OverscrollMouseMoveCompletion();
-}
// Tests that if a page scrolled, then the overscroll controller's states are
// reset after the end of the scroll.
-void RenderWidgetHostViewAuraOverscrollTest::
- OverscrollStateResetsAfterScroll() {
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ OverscrollStateResetsAfterScroll) {
SetUpOverscrollEnvironment();
- SimulateWheelEventPossiblyIncludingPhase(
- 0, 5, 0, true, WebMouseWheelEvent::kPhaseBegan); // sent directly
- SimulateWheelEventPossiblyIncludingPhase(
- 0, 30, 0, true, WebMouseWheelEvent::kPhaseChanged); // enqueued
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(0, 5, 0, true,
+ WebMouseWheelEvent::kPhaseBegan); // sent directly
+ SimulateWheelEvent(0, 30, 0, true,
+ WebMouseWheelEvent::kPhaseChanged); // enqueued
+ SimulateWheelEvent(
0, 40, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(
0, 10, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
@@ -5589,13 +5217,6 @@ void RenderWidgetHostViewAuraOverscrollTest::
SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_TRUE(ScrollStateIsContentConsuming());
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- ExpectGestureScrollEndForWheelScrolling(false);
- // The second wheel event is not consumed.
- SendNotConsumedAcks(events);
-
- events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
- }
SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_TRUE(ScrollStateIsContentConsuming());
@@ -5619,11 +5240,11 @@ void RenderWidgetHostViewAuraOverscrollTest::
// consumed and have triggered a fling animation (as tracked by the router).
EXPECT_FALSE(parent_host_->input_router()->HasPendingEvents());
- SimulateWheelEventPossiblyIncludingPhase(
- -5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan); // sent directly
- SimulateWheelEventPossiblyIncludingPhase(
- -60, 0, 0, true, WebMouseWheelEvent::kPhaseChanged); // enqueued
- SimulateWheelEventPossiblyIncludingPhase(
+ SimulateWheelEvent(-5, 0, 0, true,
+ WebMouseWheelEvent::kPhaseBegan); // sent directly
+ SimulateWheelEvent(-60, 0, 0, true,
+ WebMouseWheelEvent::kPhaseChanged); // enqueued
+ SimulateWheelEvent(
-100, 0, 0, true,
WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
@@ -5639,12 +5260,6 @@ void RenderWidgetHostViewAuraOverscrollTest::
EXPECT_TRUE(ScrollStateIsUnknown());
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- events = ExpectGestureScrollEndForWheelScrolling(false);
- SendNotConsumedAcks(events);
- events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
- }
-
SendNotConsumedAcks(events);
EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
@@ -5674,24 +5289,13 @@ void RenderWidgetHostViewAuraOverscrollTest::
events = GetAndResetDispatchedMessages();
EXPECT_EQ(0u, events.size());
}
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- OverscrollStateResetsAfterScroll) {
- OverscrollStateResetsAfterScroll();
-}
-TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest,
- OverscrollStateResetsAfterScroll) {
- OverscrollStateResetsAfterScroll();
-}
-TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest,
- OverscrollStateResetsAfterScroll) {
- OverscrollStateResetsAfterScroll();
-}
// Tests that overscroll is reset when window loses focus. It should not affect
// subsequent overscrolls.
TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollResetsOnBlur) {
SetUpOverscrollEnvironment();
+ PressAndSetTouchActionAuto();
// Start an overscroll with gesture scroll. In the middle of the scroll, blur
// the host.
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
@@ -5719,7 +5323,9 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollResetsOnBlur) {
blink::kWebGestureDeviceTouchscreen);
events = GetAndResetDispatchedMessages();
EXPECT_EQ("SetFocus GestureScrollEnd", GetMessageNames(events));
+ ReleaseAndResetDispatchedMessages();
+ PressAndSetTouchActionAuto();
// Start a scroll gesture again. This should correctly start the overscroll
// after the threshold.
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
@@ -5742,6 +5348,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollResetsOnBlur) {
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->completed_mode());
EXPECT_EQ("GestureScrollEnd", GetMessageNames(events));
+ ReleaseAndResetDispatchedMessages();
}
#if defined(OS_CHROMEOS)
@@ -5900,13 +5507,20 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCanScrollForWebMouseWheelEvent) {
base::RunLoop().RunUntilIdle();
events = GetAndResetDispatchedMessages();
+ // Since the modifiers has changed a wheel end event will be sent before
+ // dispatching the wheel event.
+ EXPECT_EQ(2u, events.size());
wheel_event = static_cast<const WebMouseWheelEvent*>(
events[0]->ToEvent()->Event()->web_event.get());
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, wheel_event->phase);
+
// Check if scroll is caused when no modifier is applied to the
// mouse wheel event.
+ wheel_event = static_cast<const WebMouseWheelEvent*>(
+ events[1]->ToEvent()->Event()->web_event.get());
EXPECT_TRUE(WebInputEventTraits::CanCauseScroll(*wheel_event));
- events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
+ events[1]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
// Simulates the scroll event with ctrl modifier applied.
ui::ScrollEvent scroll(ui::ET_SCROLL, gfx::Point(2, 2), ui::EventTimeForNow(),
@@ -5915,10 +5529,16 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCanScrollForWebMouseWheelEvent) {
base::RunLoop().RunUntilIdle();
events = GetAndResetDispatchedMessages();
+ // Since the modifiers has changed a wheel end event will be sent before
+ // dispatching the wheel event.
+ EXPECT_EQ(2u, events.size());
wheel_event = static_cast<const WebMouseWheelEvent*>(
events[0]->ToEvent()->Event()->web_event.get());
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, wheel_event->phase);
// Check if scroll is caused when ctrl-touchpad-scroll is generated
// from scroll event.
+ wheel_event = static_cast<const WebMouseWheelEvent*>(
+ events[1]->ToEvent()->Event()->web_event.get());
EXPECT_TRUE(WebInputEventTraits::CanCauseScroll(*wheel_event));
}
@@ -5955,11 +5575,13 @@ TEST_F(RenderWidgetHostViewAuraTest, CorrectNumberOfAcksAreDispatched) {
// 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.
-void RenderWidgetHostViewAuraOverscrollTest::ScrollDeltasResetOnEnd() {
+TEST_F(RenderWidgetHostViewAuraOverscrollTest, ScrollDeltasResetOnEnd) {
SetUpOverscrollEnvironment();
+
+ PressAndSetTouchActionAuto();
// Wheel event scroll ending with mouse move.
- SimulateWheelEventPossiblyIncludingPhase(
- -30, -10, 0, true, WebMouseWheelEvent::kPhaseBegan); // sent directly
+ SimulateWheelEvent(-30, -10, 0, true,
+ WebMouseWheelEvent::kPhaseBegan); // sent directly
MockWidgetInputHandler::MessageVector events =
GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel", GetMessageNames(events));
@@ -5977,8 +5599,7 @@ void RenderWidgetHostViewAuraOverscrollTest::ScrollDeltasResetOnEnd() {
// A wheel event with phase ended is sent before a GSB with touchscreen
// device.
- SimulateWheelEventPossiblyIncludingPhase(0, 0, 0, true,
- WebMouseWheelEvent::kPhaseEnded);
+ SimulateWheelEvent(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded);
events = GetAndResetDispatchedMessages();
SendNotConsumedAcks(events);
@@ -5999,11 +5620,11 @@ void RenderWidgetHostViewAuraOverscrollTest::ScrollDeltasResetOnEnd() {
EXPECT_EQ(0.f, overscroll_delta_y());
events = GetAndResetDispatchedMessages();
SendNotConsumedAcks(events);
+ ReleaseAndResetDispatchedMessages();
// Wheel event scroll ending with a fling. This is the first wheel event after
// touchscreen scrolling ends so it will have phase = kPhaseBegan.
- SimulateWheelEventPossiblyIncludingPhase(5, 0, 0, true,
- WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEvent(5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan);
// ACK the MouseWheel event
events = GetAndResetDispatchedMessages();
SendNotConsumedAcks(events);
@@ -6012,17 +5633,10 @@ void RenderWidgetHostViewAuraOverscrollTest::ScrollDeltasResetOnEnd() {
SendScrollBeginAckIfNeeded(events, INPUT_EVENT_ACK_STATE_CONSUMED);
SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- SimulateWheelEventPossiblyIncludingPhase(10, -5, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel GestureScrollUpdate", GetMessageNames(events));
- } else {
- events = GetAndResetDispatchedMessages();
- EXPECT_EQ("MouseWheel", GetMessageNames(events));
- SendNotConsumedAcks(events);
- events = GetAndResetDispatchedMessages();
- }
+ SimulateWheelEvent(10, -5, 0, true, WebMouseWheelEvent::kPhaseChanged);
+ events = GetAndResetDispatchedMessages();
+ EXPECT_EQ("MouseWheel GestureScrollUpdate", GetMessageNames(events));
+
SendNotConsumedAcks(events);
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
@@ -6041,17 +5655,6 @@ void RenderWidgetHostViewAuraOverscrollTest::ScrollDeltasResetOnEnd() {
progress_time += base::TimeDelta::FromMilliseconds(17);
}
}
-TEST_F(RenderWidgetHostViewAuraOverscrollTest, ScrollDeltasResetOnEnd) {
- ScrollDeltasResetOnEnd();
-}
-TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest,
- ScrollDeltasResetOnEnd) {
- ScrollDeltasResetOnEnd();
-}
-TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest,
- ScrollDeltasResetOnEnd) {
- ScrollDeltasResetOnEnd();
-}
TEST_F(RenderWidgetHostViewAuraTest, ForwardMouseEvent) {
aura::Window* root = parent_view_->GetNativeView()->GetRootWindow();
@@ -6096,6 +5699,50 @@ TEST_F(RenderWidgetHostViewAuraTest, ForwardMouseEvent) {
view_ = nullptr;
}
+// Test that we elide touchpad pinch gesture steams consisting of only begin
+// and end events.
+TEST_F(RenderWidgetHostViewAuraTest, ElideEmptyTouchpadPinchSequence) {
+ ui::GestureEventDetails begin_details(ui::ET_GESTURE_PINCH_BEGIN);
+ begin_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+ ui::GestureEvent begin_event(0, 0, 0, ui::EventTimeForNow(), begin_details);
+
+ ui::GestureEventDetails update_details(ui::ET_GESTURE_PINCH_UPDATE);
+ update_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+ update_details.set_scale(1.23);
+ ui::GestureEvent update_event(0, 0, 0, ui::EventTimeForNow(), update_details);
+
+ ui::GestureEventDetails end_details(ui::ET_GESTURE_PINCH_END);
+ end_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+ ui::GestureEvent end_event(0, 0, 0, ui::EventTimeForNow(), end_details);
+
+ view_->OnGestureEvent(&begin_event);
+ base::RunLoop().RunUntilIdle();
+ MockWidgetInputHandler::MessageVector events =
+ GetAndResetDispatchedMessages();
+ // Since we don't know if we'll have GesturePinchUpdates at this point, the
+ // GesturePinchBegin should not be sent yet.
+ EXPECT_EQ(0U, events.size());
+
+ view_->OnGestureEvent(&update_event);
+ base::RunLoop().RunUntilIdle();
+ events = GetAndResetDispatchedMessages();
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
+
+ // If the page consumes the update, then no GesturePinchUpdate is sent and
+ // we continue to postpone sending the GesturePinchBegin.
+ events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
+ events = GetAndResetDispatchedMessages();
+ EXPECT_EQ(0U, events.size());
+
+ view_->OnGestureEvent(&end_event);
+ base::RunLoop().RunUntilIdle();
+ events = GetAndResetDispatchedMessages();
+ // Since we have not sent any GesturePinchUpdates by the time we get to the
+ // end of the pinch, the GesturePinchBegin and GesturePinchEnd events should
+ // be elided.
+ EXPECT_EQ(0U, events.size());
+}
+
TEST_F(RenderWidgetHostViewAuraTest, GestureTapFromStylusHasPointerType) {
view_->InitAsFullscreen(parent_view_);
view_->Show();
@@ -6108,6 +5755,7 @@ TEST_F(RenderWidgetHostViewAuraTest, GestureTapFromStylusHasPointerType) {
// Simulate touch press and release to generate a GestureTap.
generator.EnterPenPointerMode();
generator.PressTouch();
+ widget_host_->input_router()->OnSetTouchAction(cc::kTouchActionAuto);
generator.ReleaseTouch();
base::RunLoop().RunUntilIdle();
MockWidgetInputHandler::MessageVector events =
@@ -6130,9 +5778,12 @@ TEST_F(RenderWidgetHostViewAuraTest, GestureTapFromStylusHasPointerType) {
// SubmitCompositorFrame becomes the active hit test region in the
// viz::HitTestManager.
TEST_F(RenderWidgetHostViewAuraTest, HitTestRegionListSubmitted) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
+ // https://crbug.com/844469
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
+ !features::IsAshInBrowserProcess()) {
return;
+ }
gfx::Rect view_rect(0, 0, 100, 100);
gfx::Size frame_size = view_rect.size();
@@ -6172,7 +5823,7 @@ TEST_F(RenderWidgetHostViewAuraTest, HitTestRegionListSubmitted) {
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
NewContentRenderingTimeout) {
// TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ if (!features::IsAshInBrowserProcess())
return;
constexpr base::TimeDelta kTimeout = base::TimeDelta::FromMicroseconds(10);
@@ -6187,8 +5838,8 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
viz::LocalSurfaceId id0 = view_->GetLocalSurfaceId();
EXPECT_TRUE(id0.is_valid());
- // No new LocalSurfaceId should be allocated for the first navigation but the
- // timer should fire.
+ // No new LocalSurfaceId should be allocated for the first navigation and the
+ // timer should not fire.
widget_host_->DidNavigate(1);
viz::LocalSurfaceId id1 = view_->GetLocalSurfaceId();
EXPECT_EQ(id0, id1);
@@ -6198,7 +5849,15 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
FROM_HERE, run_loop.QuitClosure(), 2 * kTimeout);
run_loop.Run();
}
- EXPECT_TRUE(widget_host_->new_content_rendering_timeout_fired());
+ if (base::FeatureList::IsEnabled(features::kEnableSurfaceSynchronization)) {
+ // When using surface sync, the timer should not fire, because the surface
+ // id did not change.
+ EXPECT_FALSE(widget_host_->new_content_rendering_timeout_fired());
+ } else {
+ // When not using surface sync, the timer will fire because the source id
+ // changed.
+ EXPECT_TRUE(widget_host_->new_content_rendering_timeout_fired());
+ }
widget_host_->reset_new_content_rendering_timeout_fired();
// Start the timer. Verify that a new LocalSurfaceId is allocated.
@@ -6242,7 +5901,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
AllocateLocalSurfaceIdOnEviction) {
// TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ if (!features::IsAshInBrowserProcess())
return;
view_->InitAsChild(nullptr);
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 1c52a5fd396..5561b7a1f38 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
@@ -27,7 +27,6 @@
#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/content_switches_internal.h"
-#include "content/public/common/content_features.h"
#include "ui/base/layout.h"
#include "ui/base/ui_base_types.h"
#include "ui/display/screen.h"
@@ -52,8 +51,6 @@ RenderWidgetHostViewBase::RenderWidgetHostViewBase(RenderWidgetHost* host)
current_device_scale_factor_(0),
current_display_rotation_(display::Display::ROTATE_0),
text_input_manager_(nullptr),
- wheel_scroll_latching_enabled_(base::FeatureList::IsEnabled(
- features::kTouchpadAndWheelScrollLatching)),
web_contents_accessibility_(nullptr),
is_currently_scrolling_viewport_(false),
use_viz_hit_test_(features::IsVizHitTestingEnabled()),
@@ -64,7 +61,7 @@ RenderWidgetHostViewBase::RenderWidgetHostViewBase(RenderWidgetHost* host)
RenderWidgetHostViewBase::~RenderWidgetHostViewBase() {
DCHECK(!keyboard_locked_);
- DCHECK(!mouse_locked_);
+ DCHECK(!IsMouseLocked());
// 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
@@ -116,7 +113,10 @@ bool RenderWidgetHostViewBase::OnMessageReceived(const IPC::Message& msg){
return false;
}
-void RenderWidgetHostViewBase::OnRenderFrameMetadataChanged() {
+void RenderWidgetHostViewBase::OnRenderFrameMetadataChangedBeforeActivation(
+ const cc::RenderFrameMetadata& metadata) {}
+
+void RenderWidgetHostViewBase::OnRenderFrameMetadataChangedAfterActivation() {
is_scroll_offset_at_top_ = host_->render_frame_metadata_provider()
->LastRenderFrameMetadata()
.is_scroll_offset_at_top;
@@ -221,6 +221,18 @@ base::string16 RenderWidgetHostViewBase::GetSelectedText() {
return GetTextInputManager()->GetTextSelection(this)->selected_text();
}
+base::string16 RenderWidgetHostViewBase::GetSurroundingText() {
+ if (!GetTextInputManager())
+ return base::string16();
+ return GetTextInputManager()->GetTextSelection(this)->text();
+}
+
+gfx::Range RenderWidgetHostViewBase::GetSelectedRange() {
+ if (!GetTextInputManager())
+ return gfx::Range();
+ return GetTextInputManager()->GetTextSelection(this)->range();
+}
+
void RenderWidgetHostViewBase::SetBackgroundColor(SkColor color) {
DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
SkColorGetA(color) == SK_AlphaTRANSPARENT);
@@ -243,7 +255,7 @@ base::Optional<SkColor> RenderWidgetHostViewBase::GetBackgroundColor() const {
}
bool RenderWidgetHostViewBase::IsMouseLocked() {
- return mouse_locked_;
+ return false;
}
bool RenderWidgetHostViewBase::LockKeyboard(
@@ -288,6 +300,52 @@ void RenderWidgetHostViewBase::GestureEventAck(
InputEventAckState ack_result) {
}
+void RenderWidgetHostViewBase::ForwardTouchpadPinchIfNecessary(
+ const blink::WebGestureEvent& event,
+ InputEventAckState ack_result) {
+ if (!blink::WebInputEvent::IsPinchGestureEventType(event.GetType()))
+ return;
+ if (event.SourceDevice() !=
+ blink::WebGestureDevice::kWebGestureDeviceTouchpad)
+ return;
+ if (!event.NeedsWheelEvent())
+ return;
+
+ switch (event.GetType()) {
+ case blink::WebInputEvent::kGesturePinchBegin:
+ // Don't send the begin event until we get the first unconsumed update, so
+ // that we elide pinch gesture steams consisting of only a begin and end.
+ pending_touchpad_pinch_begin_ = event;
+ pending_touchpad_pinch_begin_->SetNeedsWheelEvent(false);
+ break;
+ case blink::WebInputEvent::kGesturePinchUpdate:
+ if (ack_result != INPUT_EVENT_ACK_STATE_CONSUMED &&
+ !event.data.pinch_update.zoom_disabled) {
+ if (pending_touchpad_pinch_begin_) {
+ host()->ForwardGestureEvent(*pending_touchpad_pinch_begin_);
+ pending_touchpad_pinch_begin_.reset();
+ }
+ // Now that the synthetic wheel event has gone unconsumed, we have the
+ // pinch event actually change the page scale.
+ blink::WebGestureEvent pinch_event(event);
+ pinch_event.SetNeedsWheelEvent(false);
+ host()->ForwardGestureEvent(pinch_event);
+ }
+ break;
+ case blink::WebInputEvent::kGesturePinchEnd:
+ if (pending_touchpad_pinch_begin_) {
+ pending_touchpad_pinch_begin_.reset();
+ } else {
+ blink::WebGestureEvent pinch_end_event(event);
+ pinch_end_event.SetNeedsWheelEvent(false);
+ host()->ForwardGestureEvent(pinch_end_event);
+ }
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
void RenderWidgetHostViewBase::SetPopupType(blink::WebPopupType popup_type) {
popup_type_ = popup_type;
}
@@ -473,14 +531,6 @@ void RenderWidgetHostViewBase::OnFrameTokenChangedForView(
host()->DidProcessFrame(frame_token);
}
-viz::FrameSinkId RenderWidgetHostViewBase::GetFrameSinkId() {
- return viz::FrameSinkId();
-}
-
-viz::LocalSurfaceId RenderWidgetHostViewBase::GetLocalSurfaceId() const {
- return viz::LocalSurfaceId();
-}
-
viz::FrameSinkId RenderWidgetHostViewBase::FrameSinkIdAtPoint(
viz::SurfaceHittestDelegate* delegate,
const gfx::PointF& point,
@@ -495,6 +545,8 @@ viz::FrameSinkId RenderWidgetHostViewBase::FrameSinkIdAtPoint(
gfx::ConvertPointToPixel(device_scale_factor, point);
viz::SurfaceId surface_id = GetCurrentSurfaceId();
if (!surface_id.is_valid()) {
+ // Force a query of the renderer if we don't have a surface id yet.
+ *out_query_renderer = true;
return GetFrameSinkId();
}
viz::SurfaceHittest hittest(delegate,
@@ -518,6 +570,11 @@ viz::FrameSinkId RenderWidgetHostViewBase::FrameSinkIdAtPoint(
void RenderWidgetHostViewBase::ProcessMouseEvent(
const blink::WebMouseEvent& event,
const ui::LatencyInfo& latency) {
+ // TODO(crbug.com/814674): Figure out the reason |host| is null here in all
+ // Process* functions.
+ if (!host())
+ return;
+
PreProcessMouseEvent(event);
host()->ForwardMouseEventWithLatencyInfo(event, latency);
}
@@ -525,12 +582,17 @@ void RenderWidgetHostViewBase::ProcessMouseEvent(
void RenderWidgetHostViewBase::ProcessMouseWheelEvent(
const blink::WebMouseWheelEvent& event,
const ui::LatencyInfo& latency) {
+ if (!host())
+ return;
host()->ForwardWheelEventWithLatencyInfo(event, latency);
}
void RenderWidgetHostViewBase::ProcessTouchEvent(
const blink::WebTouchEvent& event,
const ui::LatencyInfo& latency) {
+ if (!host())
+ return;
+
PreProcessTouchEvent(event);
host()->ForwardTouchEventWithLatencyInfo(event, latency);
}
@@ -538,6 +600,8 @@ void RenderWidgetHostViewBase::ProcessTouchEvent(
void RenderWidgetHostViewBase::ProcessGestureEvent(
const blink::WebGestureEvent& event,
const ui::LatencyInfo& latency) {
+ if (!host())
+ return;
host()->ForwardGestureEventWithLatencyInfo(event, latency);
}
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 048fd7d3a8b..8ed6ffd3a28 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
@@ -116,6 +116,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
void WasOccluded() override {}
void SetIsInVR(bool is_in_vr) override;
base::string16 GetSelectedText() override;
+ base::string16 GetSurroundingText() override;
+ gfx::Range GetSelectedRange() override;
bool IsMouseLocked() override;
bool LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes) override;
void SetBackgroundColor(SkColor color) override;
@@ -153,7 +155,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
bool OnMessageReceived(const IPC::Message& msg) override;
// RenderFrameMetadataProvider::Observer
- void OnRenderFrameMetadataChanged() override;
+ void OnRenderFrameMetadataChangedBeforeActivation(
+ const cc::RenderFrameMetadata& metadata) override;
+ void OnRenderFrameMetadataChangedAfterActivation() override;
void OnRenderFrameSubmission() override;
void OnLocalSurfaceIdChanged(
const cc::RenderFrameMetadata& metadata) override;
@@ -301,6 +305,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// the GestureRecognizer until invocation of ProcessAckedTouchEvent releases
// it to be consumed (when |ack_result| is NOT_CONSUMED OR NO_CONSUMER_EXISTS)
// or ignored (when |ack_result| is CONSUMED).
+ // |touch|'s coordinates are in the coordinate space of the view to which it
+ // was targeted.
virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) {}
@@ -309,12 +315,11 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual void DidStopFlinging() {}
// Returns the ID associated with the CompositorFrameSink of this view.
- // TODO(fsamuel): Return by const ref.
- virtual viz::FrameSinkId GetFrameSinkId();
+ virtual const viz::FrameSinkId& GetFrameSinkId() const = 0;
// Returns the LocalSurfaceId allocated by the parent client for this view.
// TODO(fsamuel): Return by const ref.
- virtual viz::LocalSurfaceId GetLocalSurfaceId() const;
+ virtual const viz::LocalSurfaceId& GetLocalSurfaceId() const = 0;
// When there are multiple RenderWidgetHostViews for a single page, input
// events need to be targeted to the correct one for handling. The following
@@ -532,10 +537,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
bool is_fullscreen() { return is_fullscreen_; }
- bool wheel_scroll_latching_enabled() {
- return wheel_scroll_latching_enabled_;
- }
-
void set_web_contents_accessibility(WebContentsAccessibility* wcax) {
web_contents_accessibility_ = wcax;
}
@@ -596,6 +597,13 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
ui::mojom::WindowTreeClientPtr GetWindowTreeClientFromRenderer();
#endif
+ // If |event| is a touchpad pinch event for which we've sent a synthetic
+ // wheel event, forward the |event| to the renderer, subject to |ack_result|
+ // which is the ACK result of the synthetic wheel.
+ virtual void ForwardTouchpadPinchIfNecessary(
+ const blink::WebGestureEvent& event,
+ InputEventAckState ack_result);
+
// The model object. Members will become private when
// RenderWidgetHostViewGuest is removed.
RenderWidgetHostImpl* host_;
@@ -610,13 +618,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// Indicates whether keyboard lock is active for this view.
bool keyboard_locked_ = false;
- // While the mouse is locked, the cursor is hidden from the user. Mouse events
- // are still generated. However, the position they report is the last known
- // mouse position just as mouse lock was entered; the movement they report
- // indicates what the change in position of the mouse would be had it not been
- // locked.
- bool mouse_locked_ = false;
-
// Indicates whether the scroll offset of the root layer is at top, i.e.,
// whether scroll_offset.y() == 0.
bool is_scroll_offset_at_top_ = true;
@@ -643,8 +644,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// |content_background_color|.
base::Optional<SkColor> default_background_color_;
- const bool wheel_scroll_latching_enabled_;
-
WebContentsAccessibility* web_contents_accessibility_;
bool is_currently_scrolling_viewport_;
@@ -701,6 +700,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
base::flat_map<int, int> pending_embeds_;
#endif
+ base::Optional<blink::WebGestureEvent> pending_touchpad_pinch_begin_;
+
base::WeakPtrFactory<RenderWidgetHostViewBase> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewBase);
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 801847175d3..f4540058c6a 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
@@ -152,13 +152,14 @@ class CommitBeforeSwapAckSentHelper
private:
// DidCommitProvisionalLoadInterceptor:
- void WillDispatchDidCommitProvisionalLoad(
+ bool WillDispatchDidCommitProvisionalLoad(
RenderFrameHost* render_frame_host,
::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
service_manager::mojom::InterfaceProviderRequest*
interface_provider_request) override {
base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
frame_observer_->WaitForAnyFrameSubmission();
+ return true;
}
// Not owned.
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc
index 2891bddd1be..08e68296f2a 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -16,6 +16,7 @@
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
+#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/surfaces/surface.h"
@@ -69,13 +70,11 @@ RenderWidgetHostViewChildFrame::RenderWidgetHostViewChildFrame(
frame_sink_id_(
base::checked_cast<uint32_t>(widget_host->GetProcess()->GetID()),
base::checked_cast<uint32_t>(widget_host->GetRoutingID())),
- current_surface_scale_factor_(1.f),
frame_connector_(nullptr),
enable_viz_(
base::FeatureList::IsEnabled(features::kVizDisplayCompositor)),
- scroll_bubbling_state_(NO_ACTIVE_GESTURE_SCROLL),
weak_factory_(this) {
- if (base::FeatureList::IsEnabled(features::kMash)) {
+ if (!features::IsAshInBrowserProcess()) {
// In Mus the RenderFrameProxy will eventually assign a viz::FrameSinkId
// until then set ours invalid, as operations using it will be disregarded.
frame_sink_id_ = viz::FrameSinkId();
@@ -94,7 +93,7 @@ RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() {
if (frame_connector_)
DetachFromTouchSelectionClientManagerIfNecessary();
- if (!base::FeatureList::IsEnabled(features::kMash)) {
+ if (features::IsAshInBrowserProcess()) {
ResetCompositorFrameSinkSupport();
if (GetHostFrameSinkManager())
GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
@@ -134,7 +133,6 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
if (frame_connector_) {
SetParentFrameSinkId(viz::FrameSinkId());
- last_received_local_surface_id_ = viz::LocalSurfaceId();
// Unlocks the mouse if this RenderWidgetHostView holds the lock.
UnlockMouse();
@@ -149,7 +147,7 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
if (parent_view) {
DCHECK(parent_view->GetFrameSinkId().is_valid() ||
- base::FeatureList::IsEnabled(features::kMash));
+ !features::IsAshInBrowserProcess());
SetParentFrameSinkId(parent_view->GetFrameSinkId());
}
@@ -170,17 +168,19 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
}
#if defined(USE_AURA)
- if (features::IsMashEnabled()) {
+ if (!features::IsAshInBrowserProcess()) {
frame_connector_->EmbedRendererWindowTreeClientInParent(
GetWindowTreeClientFromRenderer());
}
#endif
+
+ SendSurfaceInfoToEmbedder();
}
#if defined(USE_AURA)
void RenderWidgetHostViewChildFrame::SetFrameSinkId(
const viz::FrameSinkId& frame_sink_id) {
- if (base::FeatureList::IsEnabled(features::kMash))
+ if (!features::IsAshInBrowserProcess())
frame_sink_id_ = frame_sink_id;
}
#endif // defined(USE_AURA)
@@ -258,7 +258,7 @@ void RenderWidgetHostViewChildFrame::Show() {
if (!CanBecomeVisible())
return;
- host()->WasShown(ui::LatencyInfo());
+ host()->WasShown(false /* record_presentation_time */);
if (frame_connector_)
frame_connector_->SetVisibilityForChildViews(true);
@@ -397,11 +397,6 @@ void RenderWidgetHostViewChildFrame::SetIsLoading(bool is_loading) {
// is a RenderWidgetHostViewChildFrame. In contrast, when there is no
// inner/outer WebContents, only subframe's RenderWidgetHostView can be a
// RenderWidgetHostViewChildFrame which do not get a SetIsLoading() call.
- if (GuestMode::IsCrossProcessFrameGuest(
- WebContents::FromRenderViewHost(RenderViewHost::From(host()))))
- return;
-
- NOTREACHED();
}
void RenderWidgetHostViewChildFrame::RenderProcessGone(
@@ -511,69 +506,56 @@ void RenderWidgetHostViewChildFrame::UpdateRenderThrottlingStatus() {
void RenderWidgetHostViewChildFrame::GestureEventAck(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
- bool should_bubble =
+ if (!frame_connector_)
+ return;
+
+ if (blink::WebInputEvent::IsPinchGestureEventType(event.GetType()))
+ ProcessTouchpadPinchAckInRoot(event, ack_result);
+
+ const bool should_bubble =
ack_result == INPUT_EVENT_ACK_STATE_NOT_CONSUMED ||
ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS ||
ack_result == INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE;
- if (!frame_connector_)
- return;
- if (wheel_scroll_latching_enabled()) {
- if ((event.GetType() == blink::WebInputEvent::kGestureScrollBegin) &&
- should_bubble) {
- DCHECK(!is_scroll_sequence_bubbling_);
- is_scroll_sequence_bubbling_ = true;
- } else if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
- event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
- is_scroll_sequence_bubbling_ = false;
- }
-
- // GestureScrollBegin is a blocking event; It is forwarded for bubbling if
- // its ack is not consumed. For the rest of the scroll events
- // (GestureScrollUpdate, GestureScrollEnd, GestureFlingStart) the
- // frame_connector_ decides to forward them for bubbling if the
- // GestureScrollBegin event is forwarded.
- if ((event.GetType() == blink::WebInputEvent::kGestureScrollBegin &&
- should_bubble) ||
- event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
- event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
- event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
- frame_connector_->BubbleScrollEvent(event);
- }
- } else {
- // Consumption of the first GestureScrollUpdate determines whether to
- // bubble the sequence of GestureScrollUpdates.
- // If the child consumed some scroll, then stopped consuming once it could
- // no longer scroll, we don't want to bubble those unconsumed GSUs as we
- // want the user to start a new gesture in order to scroll the parent.
- // Unfortunately, this is only effective for touch scrolling as wheel
- // scrolling wraps GSUs in GSB/GSE pairs.
- if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
- DCHECK_EQ(NO_ACTIVE_GESTURE_SCROLL, scroll_bubbling_state_);
- scroll_bubbling_state_ = AWAITING_FIRST_UPDATE;
- } else if (scroll_bubbling_state_ == AWAITING_FIRST_UPDATE &&
- event.GetType() == blink::WebInputEvent::kGestureScrollUpdate) {
- scroll_bubbling_state_ = (should_bubble ? BUBBLE : SCROLL_CHILD);
- } else if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
- event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
- scroll_bubbling_state_ = NO_ACTIVE_GESTURE_SCROLL;
- }
+ if ((event.GetType() == blink::WebInputEvent::kGestureScrollBegin) &&
+ should_bubble) {
+ DCHECK(!is_scroll_sequence_bubbling_);
+ is_scroll_sequence_bubbling_ = true;
+ } else if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
+ event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
+ is_scroll_sequence_bubbling_ = false;
+ }
- // GestureScrollBegin is consumed by the target frame and not forwarded,
- // because we don't know whether we will need to bubble scroll until we
- // receive a GestureScrollUpdate ACK. GestureScrollUpdates are forwarded
- // for bubbling if the first GSU has unused scroll extent,
- // while GestureScrollEnd is always forwarded and handled according to
- // current scroll state in the RenderWidgetHostInputEventRouter.
- if ((event.GetType() == blink::WebInputEvent::kGestureScrollUpdate &&
- scroll_bubbling_state_ == BUBBLE) ||
- event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
- event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
- frame_connector_->BubbleScrollEvent(event);
- }
+ // GestureScrollBegin is a blocking event; It is forwarded for bubbling if
+ // its ack is not consumed. For the rest of the scroll events
+ // (GestureScrollUpdate, GestureScrollEnd, GestureFlingStart) the
+ // frame_connector_ decides to forward them for bubbling if the
+ // GestureScrollBegin event is forwarded.
+ if ((event.GetType() == blink::WebInputEvent::kGestureScrollBegin &&
+ should_bubble) ||
+ event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
+ event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
+ event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
+ frame_connector_->BubbleScrollEvent(event);
}
}
+void RenderWidgetHostViewChildFrame::ProcessTouchpadPinchAckInRoot(
+ const blink::WebGestureEvent& event,
+ InputEventAckState ack_result) {
+ DCHECK(blink::WebInputEvent::IsPinchGestureEventType(event.GetType()));
+
+ frame_connector_->ForwardAckedTouchpadPinchGestureEvent(event, ack_result);
+}
+
+void RenderWidgetHostViewChildFrame::ForwardTouchpadPinchIfNecessary(
+ const blink::WebGestureEvent& event,
+ InputEventAckState ack_result) {
+ // ACKs of synthetic wheel events for touchpad pinch are processed in the
+ // root RWHV.
+ NOTREACHED();
+}
+
void RenderWidgetHostViewChildFrame::DidReceiveCompositorFrameAck(
const std::vector<viz::ReturnedResource>& resources) {
if (renderer_compositor_frame_sink_)
@@ -582,15 +564,11 @@ void RenderWidgetHostViewChildFrame::DidReceiveCompositorFrameAck(
void RenderWidgetHostViewChildFrame::DidPresentCompositorFrame(
uint32_t presentation_token,
- base::TimeTicks time,
- base::TimeDelta refresh,
- uint32_t flags) {
- NOTIMPLEMENTED();
-}
-void RenderWidgetHostViewChildFrame::DidDiscardCompositorFrame(
- uint32_t presentation_token) {
- NOTIMPLEMENTED();
+ const gfx::PresentationFeedback& feedback) {
+ renderer_compositor_frame_sink_->DidPresentCompositorFrame(presentation_token,
+ feedback);
}
+
void RenderWidgetHostViewChildFrame::DidCreateNewRendererCompositorFrameSink(
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
ResetCompositorFrameSinkSupport();
@@ -602,7 +580,7 @@ void RenderWidgetHostViewChildFrame::DidCreateNewRendererCompositorFrameSink(
void RenderWidgetHostViewChildFrame::SetParentFrameSinkId(
const viz::FrameSinkId& parent_frame_sink_id) {
if (parent_frame_sink_id_ == parent_frame_sink_id ||
- base::FeatureList::IsEnabled(features::kMash))
+ !features::IsAshInBrowserProcess())
return;
auto* host_frame_sink_manager = GetHostFrameSinkManager();
@@ -623,18 +601,17 @@ void RenderWidgetHostViewChildFrame::SetParentFrameSinkId(
}
void RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedder() {
- if (base::FeatureList::IsEnabled(features::kMash))
+ if (!features::IsAshInBrowserProcess())
return;
- viz::SurfaceId surface_id(frame_sink_id_, last_received_local_surface_id_);
- viz::SurfaceInfo surface_info(surface_id, current_surface_scale_factor_,
- current_surface_size_);
- SendSurfaceInfoToEmbedderImpl(surface_info);
+ if (!last_activated_surface_info_.is_valid())
+ return;
+ FirstSurfaceActivation(last_activated_surface_info_);
}
-void RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedderImpl(
+void RenderWidgetHostViewChildFrame::FirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
if (frame_connector_)
- frame_connector_->SetChildFrameSurface(surface_info);
+ frame_connector_->FirstSurfaceActivation(surface_info);
}
void RenderWidgetHostViewChildFrame::SubmitCompositorFrame(
@@ -644,20 +621,8 @@ void RenderWidgetHostViewChildFrame::SubmitCompositorFrame(
DCHECK(!enable_viz_);
TRACE_EVENT0("content",
"RenderWidgetHostViewChildFrame::OnSwapCompositorFrame");
- current_surface_size_ = frame.size_in_pixels();
- current_surface_scale_factor_ = frame.device_scale_factor();
-
support_->SubmitCompositorFrame(local_surface_id, std::move(frame),
std::move(hit_test_region_list));
- has_frame_ = true;
-
- if (last_received_local_surface_id_ != local_surface_id ||
- HasEmbedderChanged()) {
- last_received_local_surface_id_ = local_surface_id;
- SendSurfaceInfoToEmbedder();
- }
-
- ProcessFrameSwappedCallbacks();
}
void RenderWidgetHostViewChildFrame::OnDidNotProduceFrame(
@@ -729,14 +694,15 @@ bool RenderWidgetHostViewChildFrame::IsMouseLocked() {
return host()->delegate()->HasMouseLock(host());
}
-viz::FrameSinkId RenderWidgetHostViewChildFrame::GetFrameSinkId() {
+const viz::FrameSinkId& RenderWidgetHostViewChildFrame::GetFrameSinkId() const {
return frame_sink_id_;
}
-viz::LocalSurfaceId RenderWidgetHostViewChildFrame::GetLocalSurfaceId() const {
+const viz::LocalSurfaceId& RenderWidgetHostViewChildFrame::GetLocalSurfaceId()
+ const {
if (frame_connector_)
return frame_connector_->local_surface_id();
- return viz::LocalSurfaceId();
+ return viz::ParentLocalSurfaceIdAllocator::InvalidLocalSurfaceId();
}
void RenderWidgetHostViewChildFrame::PreProcessTouchEvent(
@@ -760,7 +726,7 @@ viz::FrameSinkId RenderWidgetHostViewChildFrame::GetRootFrameSinkId() {
}
viz::SurfaceId RenderWidgetHostViewChildFrame::GetCurrentSurfaceId() const {
- return viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_);
+ return last_activated_surface_info_.id();
}
bool RenderWidgetHostViewChildFrame::HasSize() const {
@@ -771,12 +737,12 @@ gfx::PointF RenderWidgetHostViewChildFrame::TransformPointToRootCoordSpaceF(
const gfx::PointF& point) {
// LocalSurfaceId is not needed in Viz hit-test.
if (!frame_connector_ ||
- (!use_viz_hit_test_ && !last_received_local_surface_id_.is_valid())) {
+ (!use_viz_hit_test_ && !last_activated_surface_info_.is_valid())) {
return point;
}
return frame_connector_->TransformPointToRootCoordSpace(
- point, viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_));
+ point, last_activated_surface_info_.id());
}
bool RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpaceLegacy(
@@ -784,12 +750,11 @@ bool RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpaceLegacy(
const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point) {
*transformed_point = point;
- if (!frame_connector_ || !last_received_local_surface_id_.is_valid())
+ if (!frame_connector_ || !last_activated_surface_info_.is_valid())
return false;
return frame_connector_->TransformPointToLocalCoordSpaceLegacy(
- point, original_surface,
- viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_),
+ point, original_surface, last_activated_surface_info_.id(),
transformed_point);
}
@@ -800,7 +765,7 @@ bool RenderWidgetHostViewChildFrame::TransformPointToCoordSpaceForView(
viz::EventSource source) {
// LocalSurfaceId is not needed in Viz hit-test.
if (!frame_connector_ ||
- (!use_viz_hit_test_ && !last_received_local_surface_id_.is_valid())) {
+ (!use_viz_hit_test_ && !last_activated_surface_info_.is_valid())) {
return false;
}
@@ -810,9 +775,8 @@ bool RenderWidgetHostViewChildFrame::TransformPointToCoordSpaceForView(
}
return frame_connector_->TransformPointToCoordSpaceForView(
- point, target_view,
- viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_),
- transformed_point, source);
+ point, target_view, last_activated_surface_info_.id(), transformed_point,
+ source);
}
gfx::PointF RenderWidgetHostViewChildFrame::TransformRootPointToViewCoordSpace(
@@ -903,14 +867,20 @@ void RenderWidgetHostViewChildFrame::CopyFromSurface(
std::move(callback)));
if (src_subrect.IsEmpty()) {
- request->set_area(gfx::Rect(current_surface_size_));
+ request->set_area(gfx::Rect(last_activated_surface_info_.size_in_pixels()));
} else {
// |src_subrect| is in DIP coordinates; convert to Surface coordinates.
- request->set_area(
- gfx::ScaleToRoundedRect(src_subrect, current_surface_scale_factor_));
+ request->set_area(gfx::ScaleToRoundedRect(
+ src_subrect, last_activated_surface_info_.device_scale_factor()));
}
if (!output_size.IsEmpty()) {
+ if (request->area().IsEmpty()) {
+ // Viz would normally return an empty result for an empty source area.
+ // However, this guard here is still necessary to protect against setting
+ // an illegal scaling ratio.
+ return;
+ }
request->set_result_selection(gfx::Rect(output_size));
request->SetScaleRatio(
gfx::Vector2d(request->area().width(), request->area().height()),
@@ -918,8 +888,7 @@ void RenderWidgetHostViewChildFrame::CopyFromSurface(
}
GetHostFrameSinkManager()->RequestCopyOfOutput(
- viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_),
- std::move(request));
+ last_activated_surface_info_.id(), std::move(request));
}
void RenderWidgetHostViewChildFrame::ReclaimResources(
@@ -942,7 +911,10 @@ void RenderWidgetHostViewChildFrame::OnBeginFramePausedChanged(bool paused) {
void RenderWidgetHostViewChildFrame::OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
- SendSurfaceInfoToEmbedderImpl(surface_info);
+ last_activated_surface_info_ = surface_info;
+ has_frame_ = true;
+ FirstSurfaceActivation(surface_info);
+ ProcessFrameSwappedCallbacks();
}
void RenderWidgetHostViewChildFrame::OnFrameTokenChanged(uint32_t frame_token) {
@@ -965,8 +937,9 @@ RenderWidgetHostViewChildFrame::GetTouchSelectionControllerClientManager() {
return root_view->GetTouchSelectionControllerClientManager();
}
-void RenderWidgetHostViewChildFrame::OnRenderFrameMetadataChanged() {
- RenderWidgetHostViewBase::OnRenderFrameMetadataChanged();
+void RenderWidgetHostViewChildFrame::
+ OnRenderFrameMetadataChangedAfterActivation() {
+ RenderWidgetHostViewBase::OnRenderFrameMetadataChangedAfterActivation();
if (selection_controller_client_) {
const cc::RenderFrameMetadata& metadata =
host()->render_frame_metadata_provider()->LastRenderFrameMetadata();
@@ -987,17 +960,20 @@ void RenderWidgetHostViewChildFrame::TakeFallbackContentFrom(
InputEventAckState RenderWidgetHostViewChildFrame::FilterInputEvent(
const blink::WebInputEvent& input_event) {
- // A child renderer should not receive touchscreen pinch events. Ideally, we
- // would DCHECK this, but since touchscreen pinch events may be targeted to
- // a child in order to have the child's TouchActionFilter filter them, we
- // may encounter https://crbug.com/771330 which would let the pinch events
- // through.
+ // A child renderer should never receive a GesturePinch event. Pinch events
+ // can still be targeted to a child, but they must be processed without
+ // sending the pinch event to the child (e.g. touchpad pinch synthesizes
+ // wheel events to send to the child renderer).
if (blink::WebInputEvent::IsPinchGestureEventType(input_event.GetType())) {
const blink::WebGestureEvent& gesture_event =
static_cast<const blink::WebGestureEvent&>(input_event);
+ // Touchscreen pinch events may be targeted to a child in order to have the
+ // child's TouchActionFilter filter them, but we may encounter
+ // https://crbug.com/771330 which would let the pinch events through.
if (gesture_event.SourceDevice() == blink::kWebGestureDeviceTouchscreen) {
return INPUT_EVENT_ACK_STATE_CONSUMED;
}
+ NOTREACHED();
}
if (input_event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
@@ -1020,7 +996,7 @@ InputEventAckState RenderWidgetHostViewChildFrame::FilterInputEvent(
}
}
- if (wheel_scroll_latching_enabled() && is_scroll_sequence_bubbling_ &&
+ if (is_scroll_sequence_bubbling_ &&
(input_event.GetType() == blink::WebInputEvent::kGestureScrollUpdate) &&
frame_connector_) {
// If we're bubbling, then to preserve latching behaviour, the child should
@@ -1034,20 +1010,6 @@ InputEventAckState RenderWidgetHostViewChildFrame::FilterInputEvent(
return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
}
- // Allow the root RWHV a chance to consume the child's GestureScrollUpdates
- // in case the root needs to prevent the child from scrolling. For example,
- // if the root has started an overscroll gesture, it needs to process the
- // scroll events that would normally be processed by the child.
- // TODO(mcnee): With scroll-latching enabled, the child would not scroll
- // in this case. Remove this once scroll-latching lands. crbug.com/751782
- if (!wheel_scroll_latching_enabled() && frame_connector_ &&
- input_event.GetType() == blink::WebInputEvent::kGestureScrollUpdate) {
- const blink::WebGestureEvent& gesture_event =
- static_cast<const blink::WebGestureEvent&>(input_event);
- return frame_connector_->GetRootRenderWidgetHostView()
- ->FilterChildGestureEvent(gesture_event);
- }
-
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
@@ -1105,7 +1067,7 @@ RenderWidgetHostViewChildFrame::DidUpdateVisualProperties(
}
void RenderWidgetHostViewChildFrame::CreateCompositorFrameSinkSupport() {
- if (base::FeatureList::IsEnabled(features::kMash) || enable_viz_)
+ if (!features::IsAshInBrowserProcess() || enable_viz_)
return;
DCHECK(!support_);
@@ -1131,10 +1093,6 @@ void RenderWidgetHostViewChildFrame::ResetCompositorFrameSinkSupport() {
support_.reset();
}
-bool RenderWidgetHostViewChildFrame::HasEmbedderChanged() {
- return false;
-}
-
bool RenderWidgetHostViewChildFrame::GetSelectionRange(
gfx::Range* range) const {
if (!text_input_manager_ || !GetFocusedWidget())
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h
index 07982e165bf..f5a326cdc98 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -143,8 +143,8 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void DidStopFlinging() override;
bool LockMouse() override;
void UnlockMouse() override;
- viz::FrameSinkId GetFrameSinkId() override;
- viz::LocalSurfaceId GetLocalSurfaceId() const override;
+ const viz::FrameSinkId& GetFrameSinkId() const override;
+ const viz::LocalSurfaceId& GetLocalSurfaceId() const override;
void PreProcessTouchEvent(const blink::WebTouchEvent& event) override;
viz::FrameSinkId GetRootFrameSinkId() override;
viz::SurfaceId GetCurrentSurfaceId() const override;
@@ -165,7 +165,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
const gfx::PointF& point) override;
TouchSelectionControllerClientManager*
GetTouchSelectionControllerClientManager() override;
- void OnRenderFrameMetadataChanged() override;
+ void OnRenderFrameMetadataChangedAfterActivation() override;
bool IsRenderWidgetHostViewChildFrame() override;
@@ -195,11 +195,9 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
// viz::mojom::CompositorFrameSinkClient implementation.
void DidReceiveCompositorFrameAck(
const std::vector<viz::ReturnedResource>& resources) override;
- void DidPresentCompositorFrame(uint32_t presentation_token,
- base::TimeTicks time,
- base::TimeDelta refresh,
- uint32_t flags) override;
- void DidDiscardCompositorFrame(uint32_t presentation_token) override;
+ void DidPresentCompositorFrame(
+ uint32_t presentation_token,
+ const gfx::PresentationFeedback& feedback) override;
void OnBeginFrame(const viz::BeginFrameArgs& args) override;
void ReclaimResources(
const std::vector<viz::ReturnedResource>& resources) override;
@@ -214,7 +212,9 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
}
// Returns the current surface scale factor.
- float current_surface_scale_factor() { return current_surface_scale_factor_; }
+ float current_surface_scale_factor() {
+ return last_activated_surface_info_.device_scale_factor();
+ }
// Returns the view into which this view is directly embedded. This can
// return nullptr when this view's associated child frame is not connected
@@ -269,9 +269,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
// Surface-related state.
std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
- viz::LocalSurfaceId last_received_local_surface_id_;
- gfx::Size current_surface_size_;
- float current_surface_scale_factor_;
+ viz::SurfaceInfo last_activated_surface_info_;
gfx::Rect last_screen_rect_;
// frame_connector_ provides a platform abstraction. Messages
@@ -288,16 +286,15 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
FRIEND_TEST_ALL_PREFIXES(
SitePerProcessBrowserTest,
HiddenOOPIFWillNotGenerateCompositorFramesAfterNavigation);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ SubframeVisibleAfterRenderViewBecomesSwappedOut);
- virtual void SendSurfaceInfoToEmbedderImpl(
- const viz::SurfaceInfo& surface_info);
+ virtual void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info);
void CreateCompositorFrameSinkSupport();
void ResetCompositorFrameSinkSupport();
void DetachFromTouchSelectionClientManagerIfNecessary();
- virtual bool HasEmbedderChanged();
-
// Returns false if the view cannot be shown. This is the case where the frame
// associated with this view or a cross process ancestor frame has been hidden
// using CSS.
@@ -306,6 +303,11 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void OnDidUpdateVisualPropertiesComplete(
const cc::RenderFrameMetadata& metadata);
+ void ProcessTouchpadPinchAckInRoot(const blink::WebGestureEvent& event,
+ InputEventAckState ack_result);
+ void ForwardTouchpadPinchIfNecessary(const blink::WebGestureEvent& event,
+ InputEventAckState ack_result) override;
+
std::vector<base::OnceClosure> frame_swapped_callbacks_;
// The surface client ID of the parent RenderWidgetHostView. 0 if none.
@@ -324,17 +326,6 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
// True if there is currently a scroll sequence being bubbled to our parent.
bool is_scroll_sequence_bubbling_ = false;
- // Used to prevent bubbling of subsequent GestureScrollUpdates in a scroll
- // gesture if the child consumed the first GSU.
- // TODO(mcnee): This is only needed for |!wheel_scroll_latching_enabled()|
- // and can be removed once scroll-latching lands. crbug.com/526463
- enum ScrollBubblingState {
- NO_ACTIVE_GESTURE_SCROLL,
- AWAITING_FIRST_UPDATE,
- BUBBLE,
- SCROLL_CHILD,
- } scroll_bubbling_state_;
-
base::WeakPtrFactory<RenderWidgetHostViewChildFrame> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewChildFrame);
};
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
index e6ee8ec9bc1..6c9a0a1bc04 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
@@ -6,6 +6,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/test/test_timeouts.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -75,6 +76,13 @@ class RenderWidgetHostViewChildFrameTest : public ContentBrowserTest {
actual_frame_sink_id_.sink_id());
}
+ void GiveItSomeTime() {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
+ run_loop.Run();
+ }
+
void set_expected_frame_sink_id(viz::FrameSinkId frame_sink_id) {
expected_frame_sink_id_ = frame_sink_id;
}
@@ -152,7 +160,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest,
IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest, ChildFrameSinkId) {
// Only when mus hosts viz do we expect a RenderFrameProxy to provide the
// FrameSinkId.
- if (!base::FeatureList::IsEnabled(features::kMash))
+ if (features::IsAshInBrowserProcess())
return;
GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
@@ -182,4 +190,35 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest, ChildFrameSinkId) {
base::Unretained(this)));
}
+// Validate that OOPIFs receive presentation feedbacks.
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest,
+ PresentationFeedback) {
+ base::HistogramTester histogram_tester;
+ GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
+ NavigateToURL(shell(), main_url);
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ // Load cross-site page into iframe.
+ GURL cross_site_url(
+ embedded_test_server()->GetURL("foo.com", "/title2.html"));
+ NavigateFrameToURL(root->child_at(0), cross_site_url);
+
+ auto* child_rwh_impl =
+ root->child_at(0)->current_frame_host()->GetRenderWidgetHost();
+ // Hide the frame and make it visible again, to force it to record the
+ // tab-switch time, which is generated from presentation-feedback.
+ child_rwh_impl->WasHidden();
+ child_rwh_impl->WasShown(true /* record_presentation_time */);
+ // Force the child to submit a new frame.
+ ASSERT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
+ "document.write('Force a new frame.');"));
+ do {
+ FetchHistogramsFromChildProcesses();
+ GiveItSomeTime();
+ } while (histogram_tester.GetAllSamples("MPArch.RWH_TabSwitchPaintDuration")
+ .size() != 1);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
index c190e59907d..d888709145d 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -31,7 +31,6 @@
#include "content/common/frame_visual_properties.h"
#include "content/common/view_messages.h"
#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/common/content_features.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -58,7 +57,7 @@ class MockFrameConnectorDelegate : public FrameConnectorDelegate {
: FrameConnectorDelegate(use_zoom_for_device_scale_factor) {}
~MockFrameConnectorDelegate() override {}
- void SetChildFrameSurface(const viz::SurfaceInfo& surface_info) override {
+ void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override {
last_surface_info_ = surface_info;
}
@@ -141,12 +140,11 @@ class RenderWidgetHostViewChildFrameTest : public testing::Test {
}
viz::SurfaceId GetSurfaceId() const {
- return viz::SurfaceId(view_->frame_sink_id_,
- view_->last_received_local_surface_id_);
+ return view_->last_activated_surface_info_.id();
}
viz::LocalSurfaceId GetLocalSurfaceId() const {
- return view_->last_received_local_surface_id_;
+ return GetSurfaceId().local_surface_id();
}
protected:
@@ -197,44 +195,22 @@ TEST_F(RenderWidgetHostViewChildFrameTest, VisibilityTest) {
ASSERT_FALSE(view_->IsShowing());
}
-// Verify that SubmitCompositorFrame behavior is correct when a delegated
-// frame is received from a renderer process.
-TEST_F(RenderWidgetHostViewChildFrameTest, SwapCompositorFrame) {
- // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
- // https://crbug.com/844469
- if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- base::FeatureList::IsEnabled(features::kMash)) {
- return;
- }
-
+// Verify that RenderWidgetHostViewChildFrame passes the child's SurfaceId to
+// FrameConnectorDelegate to be sent to the embedding renderer.
+TEST_F(RenderWidgetHostViewChildFrameTest, PassesSurfaceId) {
gfx::Size view_size(100, 100);
gfx::Rect view_rect(view_size);
float scale_factor = 1.f;
- viz::LocalSurfaceId local_surface_id(1, base::UnguessableToken::Create());
view_->SetSize(view_size);
view_->Show();
- view_->SubmitCompositorFrame(
- local_surface_id,
- CreateDelegatedFrame(scale_factor, view_size, view_rect), base::nullopt);
-
- viz::SurfaceId id = GetSurfaceId();
- if (id.is_valid()) {
-#if !defined(OS_ANDROID)
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- viz::SurfaceManager* manager = factory->GetContextFactoryPrivate()
- ->GetFrameSinkManager()
- ->surface_manager();
- viz::Surface* surface = manager->GetSurfaceForId(id);
- EXPECT_TRUE(surface);
-#endif
+ viz::SurfaceId surface_id(view_->GetFrameSinkId(),
+ view_->GetLocalSurfaceId());
+ viz::SurfaceInfo surface_info(surface_id, scale_factor, view_size);
+ view_->OnFirstSurfaceActivation(surface_info);
- // Surface ID should have been passed to FrameConnectorDelegate to
- // be sent to the embedding renderer.
- EXPECT_EQ(viz::SurfaceInfo(id, scale_factor, view_size),
- test_frame_connector_->last_surface_info_);
- }
+ EXPECT_EQ(surface_info, test_frame_connector_->last_surface_info_);
}
// Tests that the viewport intersection rect is dispatched to the RenderWidget
@@ -261,29 +237,6 @@ TEST_F(RenderWidgetHostViewChildFrameTest, ViewportIntersectionUpdated) {
EXPECT_EQ(intersection_rect, std::get<1>(sent_rects));
}
-// Tests specific to non-scroll-latching behaviour.
-// TODO(mcnee): Remove once scroll-latching lands. crbug.com/526463
-class RenderWidgetHostViewChildFrameScrollLatchingDisabledTest
- : public RenderWidgetHostViewChildFrameTest {
- public:
- RenderWidgetHostViewChildFrameScrollLatchingDisabledTest() {}
-
- void SetUp() override {
- feature_list_.InitWithFeatures({},
- {features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents});
-
- RenderWidgetHostViewChildFrameTest::SetUp();
- DCHECK(!view_->wheel_scroll_latching_enabled());
- }
-
- private:
- base::test::ScopedFeatureList feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(
- RenderWidgetHostViewChildFrameScrollLatchingDisabledTest);
-};
-
class RenderWidgetHostViewChildFrameZoomForDSFTest
: public RenderWidgetHostViewChildFrameTest {
public:
@@ -297,26 +250,6 @@ class RenderWidgetHostViewChildFrameZoomForDSFTest
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewChildFrameZoomForDSFTest);
};
-// Test that when a child scrolls and then stops consuming once it hits the
-// extent, we don't bubble the subsequent unconsumed GestureScrollUpdates
-// in the same gesture.
-TEST_F(RenderWidgetHostViewChildFrameScrollLatchingDisabledTest,
- DoNotBubbleIfChildHasAlreadyScrolled) {
- blink::WebGestureEvent gesture_scroll(
- blink::WebGestureEvent::kGestureScrollBegin,
- blink::WebInputEvent::kNoModifiers,
- blink::WebInputEvent::GetStaticTimeStampForTests());
- view_->GestureEventAck(gesture_scroll, INPUT_EVENT_ACK_STATE_IGNORED);
-
- gesture_scroll.SetType(blink::WebGestureEvent::kGestureScrollUpdate);
- view_->GestureEventAck(gesture_scroll, INPUT_EVENT_ACK_STATE_CONSUMED);
- ASSERT_FALSE(test_frame_connector_->seen_bubbled_gsu_);
-
- view_->GestureEventAck(gesture_scroll,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
- EXPECT_FALSE(test_frame_connector_->seen_bubbled_gsu_);
-}
-
// Tests that moving the child around does not affect the physical backing size.
TEST_F(RenderWidgetHostViewChildFrameZoomForDSFTest,
CompositorViewportPixelSize) {
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h
index 0fd6933ba64..b2d9cecb8e2 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h
@@ -15,6 +15,7 @@
#include "base/optional.h"
#include "content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h"
#include "content/common/edit_command.h"
+#include "content/common/render_widget_host_ns_view.mojom.h"
#import "ui/base/cocoa/command_dispatcher.h"
#import "ui/base/cocoa/tool_tip_base_view.h"
#include "ui/base/ime/ime_text_span.h"
@@ -26,7 +27,11 @@ class WebGestureEvent;
}
namespace content {
+namespace mojom {
class RenderWidgetHostNSViewClient;
+}
+
+class RenderWidgetHostNSViewLocalClient;
class RenderWidgetHostViewMac;
class RenderWidgetHostViewMacEditCommandHelper;
}
@@ -39,7 +44,7 @@ struct DidOverscrollParams;
@protocol RenderWidgetHostViewMacDelegate;
@protocol RenderWidgetHostNSViewClientOwner
-- (content::RenderWidgetHostNSViewClient*)renderWidgetHostNSViewClient;
+- (content::mojom::RenderWidgetHostNSViewClient*)renderWidgetHostNSViewClient;
@end
// This is the view that lives in the Cocoa view hierarchy. In Windows-land,
@@ -54,12 +59,24 @@ struct DidOverscrollParams;
@private
// The communications channel to the RenderWidgetHostViewMac. This pointer is
// always valid. When the original client disconnects, |client_| is changed to
- // point to |noopClient_|, to avoid having to preface every dereference with
+ // point to |dummyClient_|, to avoid having to preface every dereference with
// a nullptr check.
- content::RenderWidgetHostNSViewClient* client_;
+ content::mojom::RenderWidgetHostNSViewClient* client_;
+
+ // A separate client interface for the parts of the interface to
+ // RenderWidgetHostViewMac that cannot or should not be forwarded over mojo.
+ // This includes events (where the extra translation is unnecessary or loses
+ // information) and access to accessibility structures (only present in the
+ // browser process).
+ content::RenderWidgetHostNSViewLocalClient* localClient_;
+
+ // An implementation of the in-process interface that will translate and
+ // forward messages through |client_|.
+ std::unique_ptr<content::RenderWidgetHostNSViewLocalClient>
+ forwardingLocalClient_;
- // Dummy client that is always valid (see above).
- std::unique_ptr<content::RenderWidgetHostNSViewClient> noopClient_;
+ // Dummy client that is always valid (see above comments about client_).
+ content::mojom::RenderWidgetHostNSViewClientPtr dummyClient_;
// This ivar is the cocoa delegate of the NSResponder.
base::scoped_nsobject<NSObject<RenderWidgetHostViewMacDelegate>>
@@ -227,7 +244,8 @@ struct DidOverscrollParams;
- (void)unlockKeyboard;
// Methods previously marked as private.
-- (id)initWithClient:(content::RenderWidgetHostNSViewClient*)client;
+- (id)initWithClient:(content::mojom::RenderWidgetHostNSViewClient*)client
+ withLocalClient:(content::RenderWidgetHostNSViewLocalClient*)localClient;
- (void)setResponderDelegate:
(NSObject<RenderWidgetHostViewMacDelegate>*)delegate;
- (void)processedGestureScrollEvent:(const blink::WebGestureEvent&)event
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
index d86576cc36a..8b84322baa8 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
@@ -20,6 +20,7 @@
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
#import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h"
#import "content/public/browser/render_widget_host_view_mac_delegate.h"
+#include "ui/accessibility/platform/ax_platform_node.h"
#import "ui/base/clipboard/clipboard_util_mac.h"
#import "ui/base/cocoa/appkit_utils.h"
#include "ui/base/cocoa/cocoa_base_utils.h"
@@ -32,8 +33,10 @@
using content::BrowserAccessibility;
using content::BrowserAccessibilityManager;
using content::EditCommand;
+using content::InputEvent;
using content::NativeWebKeyboardEvent;
-using content::RenderWidgetHostNSViewClient;
+using content::mojom::RenderWidgetHostNSViewClient;
+using content::RenderWidgetHostNSViewLocalClient;
using content::RenderWidgetHostViewMacEditCommandHelper;
using content::WebGestureEventBuilder;
using content::WebMouseEventBuilder;
@@ -45,84 +48,76 @@ using blink::WebGestureEvent;
namespace {
-// No-op client used to avoid scattering of nullptr checks (see comments in
-// the client_ member of RenderWidgetHostViewCocoa).
-class NoopClient : public RenderWidgetHostNSViewClient {
+class ForwardingLocalClient : public RenderWidgetHostNSViewLocalClient {
public:
- NoopClient() {}
- ~NoopClient() override{};
+ explicit ForwardingLocalClient(RenderWidgetHostNSViewClient* client)
+ : client_(client) {}
- // RenderWidgetHostNSViewClient implementation:
+ private:
+ std::unique_ptr<InputEvent> TranslateEvent(
+ const blink::WebInputEvent& web_event) {
+ return std::make_unique<InputEvent>(web_event, ui::LatencyInfo());
+ }
+
+ // RenderWidgetHostNSViewLocalClient implementation.
BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override {
return nullptr;
}
- void OnNSViewSyncIsRenderViewHost(bool* is_render_view) override {}
- void OnNSViewRequestShutdown() override {}
- void OnNSViewIsFirstResponderChanged(bool is_first_responder) override {}
- void OnNSViewWindowIsKeyChanged(bool is_key) override {}
- void OnNSViewBoundsInWindowChanged(const gfx::Rect& view_bounds_in_window_dip,
- bool attached_to_window) override {}
- void OnNSViewWindowFrameInScreenChanged(
- const gfx::Rect& window_frame_in_screen_dip) override {}
- void OnNSViewDisplayChanged(const display::Display& display) override {}
- void OnNSViewBeginKeyboardEvent() override {}
- void OnNSViewEndKeyboardEvent() override {}
- void OnNSViewForwardKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info) override {}
- void OnNSViewForwardKeyboardEventWithCommands(
+ void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info) override {
+ const blink::WebKeyboardEvent* web_event =
+ static_cast<const blink::WebKeyboardEvent*>(&key_event);
+ std::unique_ptr<InputEvent> input_event =
+ std::make_unique<InputEvent>(*web_event, latency_info);
+ client_->ForwardKeyboardEvent(std::move(input_event),
+ key_event.skip_in_browser);
+ }
+ void ForwardKeyboardEventWithCommands(
const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency_info,
- const std::vector<EditCommand>& commands) override {}
- void OnNSViewRouteOrProcessMouseEvent(
- const blink::WebMouseEvent& web_event) override {}
- void OnNSViewRouteOrProcessWheelEvent(
- const blink::WebMouseWheelEvent& web_event) override {}
- void OnNSViewForwardMouseEvent(
- const blink::WebMouseEvent& web_event) override {}
- void OnNSViewForwardWheelEvent(
- const blink::WebMouseWheelEvent& web_event) override {}
- void OnNSViewGestureBegin(blink::WebGestureEvent begin_event,
- bool is_synthetically_injected) override {}
- void OnNSViewGestureUpdate(blink::WebGestureEvent update_event) override {}
- void OnNSViewGestureEnd(blink::WebGestureEvent end_event) override {}
- void OnNSViewSmartMagnify(
- const blink::WebGestureEvent& smart_magnify_event) override {}
- void OnNSViewImeSetComposition(
- const base::string16& text,
- const std::vector<ui::ImeTextSpan>& ime_text_spans,
- const gfx::Range& replacement_range,
- int selection_start,
- int selection_end) override {}
- void OnNSViewImeCommitText(const base::string16& text,
- const gfx::Range& replacement_range) override {}
- void OnNSViewImeFinishComposingText() override {}
- void OnNSViewImeCancelComposition() override {}
- void OnNSViewLookUpDictionaryOverlayAtPoint(
- const gfx::PointF& root_point) override {}
- void OnNSViewLookUpDictionaryOverlayFromRange(
- const gfx::Range& range) override {}
- void OnNSViewSyncGetCharacterIndexAtPoint(const gfx::PointF& root_point,
- uint32_t* index) override {}
- void OnNSViewSyncGetFirstRectForRange(const gfx::Range& requested_range,
- gfx::Rect* rect,
- gfx::Range* actual_range,
- bool* success) override {}
- void OnNSViewExecuteEditCommand(const std::string& command) override {}
- void OnNSViewUndo() override {}
- void OnNSViewRedo() override {}
- void OnNSViewCut() override {}
- void OnNSViewCopy() override {}
- void OnNSViewCopyToFindPboard() override {}
- void OnNSViewPaste() override {}
- void OnNSViewPasteAndMatchStyle() override {}
- void OnNSViewSelectAll() override {}
- void OnNSViewSpeakSelection() override {}
- void OnNSViewStopSpeaking() override {}
- void OnNSViewSyncIsSpeaking(bool* is_speaking) override {}
+ const std::vector<EditCommand>& commands) override {
+ const blink::WebKeyboardEvent* web_event =
+ static_cast<const blink::WebKeyboardEvent*>(&key_event);
+ std::unique_ptr<InputEvent> input_event =
+ std::make_unique<InputEvent>(*web_event, latency_info);
+ client_->ForwardKeyboardEventWithCommands(
+ std::move(input_event), key_event.skip_in_browser, commands);
+ }
+ void RouteOrProcessMouseEvent(
+ const blink::WebMouseEvent& web_event) override {
+ client_->RouteOrProcessMouseEvent(TranslateEvent(web_event));
+ }
+ void RouteOrProcessWheelEvent(
+ const blink::WebMouseWheelEvent& web_event) override {
+ client_->RouteOrProcessWheelEvent(TranslateEvent(web_event));
+ }
+ void ForwardMouseEvent(const blink::WebMouseEvent& web_event) override {
+ client_->ForwardMouseEvent(TranslateEvent(web_event));
+ }
+ void ForwardWheelEvent(const blink::WebMouseWheelEvent& web_event) override {
+ client_->ForwardWheelEvent(TranslateEvent(web_event));
+ }
+ void GestureBegin(blink::WebGestureEvent begin_event,
+ bool is_synthetically_injected) override {
+ // The gesture type is not yet known, but assign a type to avoid
+ // serialization asserts (the type will be stripped on the other side).
+ begin_event.SetType(blink::WebInputEvent::kGestureScrollBegin);
+ client_->GestureBegin(TranslateEvent(begin_event),
+ is_synthetically_injected);
+ }
+ void GestureUpdate(blink::WebGestureEvent update_event) override {
+ client_->GestureUpdate(TranslateEvent(update_event));
+ }
+ void GestureEnd(blink::WebGestureEvent end_event) override {
+ client_->GestureEnd(TranslateEvent(end_event));
+ }
+ void SmartMagnify(const blink::WebGestureEvent& web_event) override {
+ client_->SmartMagnify(TranslateEvent(web_event));
+ }
- private:
- DISALLOW_COPY_AND_ASSIGN(NoopClient);
+ RenderWidgetHostNSViewClient* client_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ForwardingLocalClient);
};
// Whether a keyboard event has been reserved by OSX.
@@ -203,22 +198,27 @@ void ExtractUnderlines(NSAttributedString* string,
- (void)sendViewBoundsInWindowToClient;
- (void)sendWindowFrameInScreenToClient;
- (bool)clientIsDisconnected;
-- (bool)isKeyLocked:(int)keyCode;
@end
@implementation RenderWidgetHostViewCocoa
@synthesize markedRange = markedRange_;
@synthesize textInputType = textInputType_;
-- (id)initWithClient:(RenderWidgetHostNSViewClient*)client {
+- (id)initWithClient:(RenderWidgetHostNSViewClient*)client
+ withLocalClient:(RenderWidgetHostNSViewLocalClient*)localClient {
self = [super initWithFrame:NSZeroRect];
if (self) {
self.acceptsTouchEvents = YES;
editCommandHelper_.reset(new RenderWidgetHostViewMacEditCommandHelper);
editCommandHelper_->AddEditingSelectorsToClass([self class]);
- noopClient_ = std::make_unique<NoopClient>();
client_ = client;
+ if (localClient) {
+ localClient_ = localClient;
+ } else {
+ forwardingLocalClient_ = std::make_unique<ForwardingLocalClient>(client_);
+ localClient_ = forwardingLocalClient_.get();
+ }
canBeKeyView_ = YES;
isStylusEnteringProximity_ = false;
keyboardLockActive_ = false;
@@ -238,15 +238,6 @@ void ExtractUnderlines(NSAttributedString* string,
[[self window] makeFirstResponder:nil];
[NSApp updateWindows];
- // Debug key to check if the current input context still holds onto the view.
- NSTextInputContext* currentContext = [NSTextInputContext currentInputContext];
- auto* crashKey = base::debug::AllocateCrashKeyString(
- "text-input-context-client", base::debug::CrashKeySize::Size32);
- base::debug::ScopedCrashKeyString textInputContextCrashKey(
- crashKey, currentContext && [currentContext client] == self
- ? "text input still held on"
- : "text input no longer held on");
-
[super dealloc];
}
@@ -259,7 +250,7 @@ void ExtractUnderlines(NSAttributedString* string,
NSRect viewBoundsInView = [self bounds];
NSWindow* enclosingWindow = [self window];
if (!enclosingWindow) {
- client_->OnNSViewBoundsInWindowChanged(gfx::Rect(viewBoundsInView), false);
+ client_->OnBoundsInWindowChanged(gfx::Rect(viewBoundsInView), false);
return;
}
@@ -267,7 +258,7 @@ void ExtractUnderlines(NSAttributedString* string,
gfx::Rect gfxViewBoundsInWindow(viewBoundsInWindow);
gfxViewBoundsInWindow.set_y(NSHeight([enclosingWindow frame]) -
NSMaxY(viewBoundsInWindow));
- client_->OnNSViewBoundsInWindowChanged(gfxViewBoundsInWindow, true);
+ client_->OnBoundsInWindowChanged(gfxViewBoundsInWindow, true);
}
- (void)setTextSelectionText:(base::string16)text
@@ -299,7 +290,7 @@ void ExtractUnderlines(NSAttributedString* string,
NSWindow* enclosingWindow = [self window];
if (!enclosingWindow)
return;
- client_->OnNSViewWindowFrameInScreenChanged(
+ client_->OnWindowFrameInScreenChanged(
gfx::ScreenRectFromNSRect([enclosingWindow frame]));
}
@@ -371,7 +362,13 @@ void ExtractUnderlines(NSAttributedString* string,
}
- (void)setClientDisconnected {
- client_ = noopClient_.get();
+ // Set the client to be an abandoned message pipe, and set the localClient
+ // to forward messages to that client.
+ content::mojom::RenderWidgetHostNSViewClientRequest dummyClientRequest =
+ mojo::MakeRequest(&dummyClient_);
+ client_ = dummyClient_.get();
+ forwardingLocalClient_ = std::make_unique<ForwardingLocalClient>(client_);
+ localClient_ = forwardingLocalClient_.get();
// |responderDelegate_| may attempt to access the RenderWidgetHostViewMac
// through its internal pointers, so detach it here.
@@ -384,7 +381,7 @@ void ExtractUnderlines(NSAttributedString* string,
}
- (bool)clientIsDisconnected {
- return client_ == noopClient_.get();
+ return client_ == dummyClient_.get();
}
- (void)setShowingContextMenu:(BOOL)showing {
@@ -414,7 +411,7 @@ void ExtractUnderlines(NSAttributedString* string,
WebMouseEvent web_event = WebMouseEventBuilder::Build(event, self);
web_event.SetModifiers(web_event.GetModifiers() |
WebInputEvent::kRelativeMotionEvent);
- client_->OnNSViewForwardMouseEvent(web_event);
+ localClient_->ForwardMouseEvent(web_event);
}
- (BOOL)shouldIgnoreMouseEvent:(NSEvent*)theEvent {
@@ -482,6 +479,13 @@ void ExtractUnderlines(NSAttributedString* string,
if (subtype != NSTabletPointEventSubtype &&
subtype != NSTabletProximityEventSubtype) {
pointerType_ = blink::WebPointerProperties::PointerType::kMouse;
+ } else if (subtype == NSTabletProximityEventSubtype) {
+ isStylusEnteringProximity_ = [theEvent isEnteringProximity];
+ NSPointingDeviceType deviceType = [theEvent pointingDeviceType];
+ // For all tablet events, the pointer type will be pen or eraser.
+ pointerType_ = deviceType == NSEraserPointingDevice
+ ? blink::WebPointerProperties::PointerType::kEraser
+ : blink::WebPointerProperties::PointerType::kPen;
}
}
@@ -497,7 +501,7 @@ void ExtractUnderlines(NSAttributedString* string,
WebMouseEventBuilder::Build(theEvent, self, pointerType_);
exitEvent.SetType(WebInputEvent::kMouseLeave);
exitEvent.button = WebMouseEvent::Button::kNoButton;
- client_->OnNSViewForwardMouseEvent(exitEvent);
+ localClient_->ForwardMouseEvent(exitEvent);
}
mouseEventWasIgnored_ = YES;
return;
@@ -510,7 +514,7 @@ void ExtractUnderlines(NSAttributedString* string,
WebMouseEventBuilder::Build(theEvent, self, pointerType_);
enterEvent.SetType(WebInputEvent::kMouseMove);
enterEvent.button = WebMouseEvent::Button::kNoButton;
- client_->OnNSViewRouteOrProcessMouseEvent(enterEvent);
+ localClient_->RouteOrProcessMouseEvent(enterEvent);
}
mouseEventWasIgnored_ = NO;
@@ -540,7 +544,7 @@ void ExtractUnderlines(NSAttributedString* string,
WebMouseEvent event =
WebMouseEventBuilder::Build(theEvent, self, pointerType_);
- client_->OnNSViewRouteOrProcessMouseEvent(event);
+ localClient_->RouteOrProcessMouseEvent(event);
}
- (void)tabletEvent:(NSEvent*)theEvent {
@@ -565,7 +569,9 @@ void ExtractUnderlines(NSAttributedString* string,
lockedKeys_.reset();
}
-- (bool)isKeyLocked:(int)keyCode {
+// CommandDispatcherTarget implementation:
+- (BOOL)isKeyLocked:(NSEvent*)event {
+ int keyCode = [event keyCode];
// Note: We do not want to treat the ESC key as locked as that key is used
// to exit fullscreen and we don't want to prevent them from exiting.
ui::DomCode domCode = ui::KeycodeConverter::NativeKeycodeToDomCode(keyCode);
@@ -587,20 +593,6 @@ void ExtractUnderlines(NSAttributedString* string,
if (EventIsReservedBySystem(theEvent))
return NO;
- // If we return |NO| from this function, cocoa will send the key event to
- // the menu and only if the menu does not process the event to |keyDown:|. We
- // want to send the event to a renderer _before_ sending it to the menu, so
- // we need to return |YES| for all events that might be swallowed by the menu.
- // We do not return |YES| for every keypress because we don't get |keyDown:|
- // events for keys that we handle this way.
- NSUInteger modifierFlags = [theEvent modifierFlags];
- if ((modifierFlags & NSCommandKeyMask) == 0) {
- // Make sure the menu does not contain key equivalents that don't
- // contain cmd.
- DCHECK(![[NSApp mainMenu] performKeyEquivalent:theEvent]);
- return NO;
- }
-
// Command key combinations are sent via performKeyEquivalent rather than
// keyDown:. We just forward this on and if WebCore doesn't want to handle
// it, we let the WebContentsView figure out how to reinject it.
@@ -650,9 +642,6 @@ void ExtractUnderlines(NSAttributedString* string,
if (EventIsReservedBySystem(theEvent))
return;
- DCHECK(eventType != NSKeyDown ||
- !equiv == !(modifierFlags & NSCommandKeyMask));
-
if (eventType == NSFlagsChanged) {
// Ignore NSFlagsChanged events from the NumLock and Fn keys as
// Safari does in -[WebHTMLView flagsChanged:] (of "WebHTMLView.mm").
@@ -673,11 +662,11 @@ void ExtractUnderlines(NSAttributedString* string,
latency_info.set_source_event_type(ui::SourceEventType::KEY_PRESS);
}
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT);
// If KeyboardLock has been requested for this keyCode, then mark the event
// so it skips the pre-handler and is delivered straight to the website.
- if ([self isKeyLocked:keyCode])
+ if ([self isKeyLocked:theEvent])
event.skip_in_browser = true;
// Do not forward key up events unless preceded by a matching key down,
@@ -693,7 +682,7 @@ void ExtractUnderlines(NSAttributedString* string,
// Tell the client that we are beginning a keyboard event. This ensures that
// all event and Ime messages target the same RenderWidgetHost throughout this
// function call.
- client_->OnNSViewBeginKeyboardEvent();
+ client_->BeginKeyboardEvent();
bool shouldAutohideCursor = textInputType_ != ui::TEXT_INPUT_TYPE_NONE &&
eventType == NSKeyDown &&
@@ -701,7 +690,7 @@ void ExtractUnderlines(NSAttributedString* string,
// We only handle key down events and just simply forward other events.
if (eventType != NSKeyDown) {
- client_->OnNSViewForwardKeyboardEvent(event, latency_info);
+ localClient_->ForwardKeyboardEvent(event, latency_info);
// Possibly autohide the cursor.
if (shouldAutohideCursor) {
@@ -709,7 +698,7 @@ void ExtractUnderlines(NSAttributedString* string,
cursorHidden_ = YES;
}
- client_->OnNSViewEndKeyboardEvent();
+ client_->EndKeyboardEvent();
return;
}
@@ -759,7 +748,7 @@ void ExtractUnderlines(NSAttributedString* string,
NativeWebKeyboardEvent fakeEvent = event;
fakeEvent.windows_key_code = 0xE5; // VKEY_PROCESSKEY
fakeEvent.skip_in_browser = true;
- client_->OnNSViewForwardKeyboardEvent(fakeEvent, latency_info);
+ localClient_->ForwardKeyboardEvent(fakeEvent, latency_info);
// If this key event was handled by the input method, but
// -doCommandBySelector: (invoked by the call to -interpretKeyEvents: above)
// enqueued edit commands, then in order to let webkit handle them
@@ -770,8 +759,8 @@ void ExtractUnderlines(NSAttributedString* string,
if (hasEditCommands_ && !hasMarkedText_)
delayEventUntilAfterImeCompostion = YES;
} else {
- client_->OnNSViewForwardKeyboardEventWithCommands(event, latency_info,
- editCommands_);
+ localClient_->ForwardKeyboardEventWithCommands(event, latency_info,
+ editCommands_);
}
// Then send keypress and/or composition related events.
@@ -788,8 +777,7 @@ void ExtractUnderlines(NSAttributedString* string,
BOOL textInserted = NO;
if (textToBeInserted_.length() >
((hasMarkedText_ || oldHasMarkedText) ? 0u : 1u)) {
- client_->OnNSViewImeCommitText(textToBeInserted_,
- gfx::Range::InvalidRange());
+ client_->ImeCommitText(textToBeInserted_, gfx::Range::InvalidRange());
textInserted = YES;
}
@@ -800,15 +788,15 @@ void ExtractUnderlines(NSAttributedString* string,
// composition node in WebKit.
// When marked text is available, |markedTextSelectedRange_| will be the
// range being selected inside the marked text.
- client_->OnNSViewImeSetComposition(markedText_, ime_text_spans_,
- setMarkedTextReplacementRange_,
- markedTextSelectedRange_.location,
- NSMaxRange(markedTextSelectedRange_));
+ client_->ImeSetComposition(markedText_, ime_text_spans_,
+ setMarkedTextReplacementRange_,
+ markedTextSelectedRange_.location,
+ NSMaxRange(markedTextSelectedRange_));
} else if (oldHasMarkedText && !hasMarkedText_ && !textInserted) {
if (unmarkTextCalled_) {
- client_->OnNSViewImeFinishComposingText();
+ client_->ImeFinishComposingText();
} else {
- client_->OnNSViewImeCancelComposition();
+ client_->ImeCancelCompositionFromCocoa();
}
}
@@ -830,8 +818,8 @@ void ExtractUnderlines(NSAttributedString* string,
fakeEvent.skip_in_browser = true;
ui::LatencyInfo fake_event_latency_info = latency_info;
fake_event_latency_info.set_source_event_type(ui::SourceEventType::OTHER);
- client_->OnNSViewForwardKeyboardEvent(fakeEvent, fake_event_latency_info);
- client_->OnNSViewForwardKeyboardEventWithCommands(
+ localClient_->ForwardKeyboardEvent(fakeEvent, fake_event_latency_info);
+ localClient_->ForwardKeyboardEventWithCommands(
event, fake_event_latency_info, editCommands_);
}
@@ -845,7 +833,7 @@ void ExtractUnderlines(NSAttributedString* string,
event.text[0] = textToBeInserted_[0];
event.text[1] = 0;
event.skip_in_browser = true;
- client_->OnNSViewForwardKeyboardEvent(event, latency_info);
+ localClient_->ForwardKeyboardEvent(event, latency_info);
} else if ((!textInserted || delayEventUntilAfterImeCompostion) &&
event.text[0] != '\0' &&
((modifierFlags & kCtrlCmdKeyMask) ||
@@ -855,7 +843,7 @@ void ExtractUnderlines(NSAttributedString* string,
// cases, unless the key event generated any other command.
event.SetType(blink::WebInputEvent::kChar);
event.skip_in_browser = true;
- client_->OnNSViewForwardKeyboardEvent(event, latency_info);
+ localClient_->ForwardKeyboardEvent(event, latency_info);
}
}
@@ -865,7 +853,7 @@ void ExtractUnderlines(NSAttributedString* string,
cursorHidden_ = YES;
}
- client_->OnNSViewEndKeyboardEvent();
+ client_->EndKeyboardEvent();
}
- (BOOL)suppressNextKeyUpForTesting:(int)keyCode {
@@ -886,7 +874,7 @@ void ExtractUnderlines(NSAttributedString* string,
// History-swiping is not possible if the logic reaches this point.
WebMouseWheelEvent webEvent = WebMouseWheelEventBuilder::Build(event, self);
webEvent.rails_mode = mouseWheelFilter_.UpdateRailsMode(webEvent);
- client_->OnNSViewForwardWheelEvent(webEvent);
+ localClient_->ForwardWheelEvent(webEvent);
if (endWheelMonitor_) {
[NSEvent removeMonitor:endWheelMonitor_];
@@ -900,7 +888,7 @@ void ExtractUnderlines(NSAttributedString* string,
WebGestureEvent gestureBeginEvent(WebGestureEventBuilder::Build(event, self));
- client_->OnNSViewGestureBegin(gestureBeginEvent, isSyntheticallyInjected);
+ localClient_->GestureBegin(gestureBeginEvent, isSyntheticallyInjected);
}
- (void)handleEndGestureWithEvent:(NSEvent*)event {
@@ -915,7 +903,8 @@ void ExtractUnderlines(NSAttributedString* string,
endEvent.SetType(WebInputEvent::kGesturePinchEnd);
endEvent.SetSourceDevice(
blink::WebGestureDevice::kWebGestureDeviceTouchpad);
- client_->OnNSViewGestureEnd(endEvent);
+ endEvent.SetNeedsWheelEvent(true);
+ localClient_->GestureEnd(endEvent);
}
}
@@ -970,11 +959,11 @@ void ExtractUnderlines(NSAttributedString* string,
- (void)smartMagnifyWithEvent:(NSEvent*)event {
const WebGestureEvent& smartMagnifyEvent =
WebGestureEventBuilder::Build(event, self);
- client_->OnNSViewSmartMagnify(smartMagnifyEvent);
+ localClient_->SmartMagnify(smartMagnifyEvent);
}
- (void)showLookUpDictionaryOverlayFromRange:(NSRange)range {
- client_->OnNSViewLookUpDictionaryOverlayFromRange(gfx::Range(range));
+ client_->LookUpDictionaryOverlayFromRange(gfx::Range(range));
}
// This is invoked only on 10.8 or newer when the user taps a word using
@@ -982,7 +971,7 @@ void ExtractUnderlines(NSAttributedString* string,
- (void)quickLookWithEvent:(NSEvent*)event {
NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
gfx::PointF rootPoint(point.x, NSHeight([self frame]) - point.y);
- client_->OnNSViewLookUpDictionaryOverlayAtPoint(rootPoint);
+ client_->LookUpDictionaryOverlayAtPoint(rootPoint);
}
// This method handles 2 different types of hardware events.
@@ -1052,7 +1041,7 @@ void ExtractUnderlines(NSAttributedString* string,
// This is responsible for content scrolling!
WebMouseWheelEvent webEvent = WebMouseWheelEventBuilder::Build(event, self);
webEvent.rails_mode = mouseWheelFilter_.UpdateRailsMode(webEvent);
- client_->OnNSViewRouteOrProcessWheelEvent(webEvent);
+ localClient_->RouteOrProcessWheelEvent(webEvent);
}
// Called repeatedly during a pinch gesture, with incremental change values.
@@ -1085,7 +1074,7 @@ void ExtractUnderlines(NSAttributedString* string,
}
WebGestureEvent updateEvent = WebGestureEventBuilder::Build(event, self);
- client_->OnNSViewGestureUpdate(updateEvent);
+ localClient_->GestureUpdate(updateEvent);
}
- (void)viewWillMoveToWindow:(NSWindow*)newWindow {
@@ -1148,7 +1137,7 @@ void ExtractUnderlines(NSAttributedString* string,
// nil. Do that call here to avoid sending bogus display info to the client.
display::Display display =
display::Screen::GetScreen()->GetDisplayNearestView(self);
- client_->OnNSViewDisplayChanged(display);
+ client_->OnDisplayChanged(display);
}
// This will be called when the NSView's NSWindow moves from one NSScreen to
@@ -1211,7 +1200,7 @@ void ExtractUnderlines(NSAttributedString* string,
if ([responderDelegate_ respondsToSelector:@selector(windowDidBecomeKey)])
[responderDelegate_ windowDidBecomeKey];
if ([self window].isKeyWindow && [[self window] firstResponder] == self)
- client_->OnNSViewWindowIsKeyChanged(true);
+ client_->OnWindowIsKeyChanged(true);
}
- (void)windowDidResignKey:(NSNotification*)notification {
@@ -1226,7 +1215,7 @@ void ExtractUnderlines(NSAttributedString* string,
return;
if ([[self window] firstResponder] == self)
- client_->OnNSViewWindowIsKeyChanged(false);
+ client_->OnWindowIsKeyChanged(false);
}
- (BOOL)becomeFirstResponder {
@@ -1235,7 +1224,7 @@ void ExtractUnderlines(NSAttributedString* string,
if ([responderDelegate_ respondsToSelector:@selector(becomeFirstResponder)])
[responderDelegate_ becomeFirstResponder];
- client_->OnNSViewIsFirstResponderChanged(true);
+ client_->OnFirstResponderChanged(true);
// Cancel any onging composition text which was left before we lost focus.
// TODO(suzhe): We should do it in -resignFirstResponder: method, but
@@ -1259,10 +1248,10 @@ void ExtractUnderlines(NSAttributedString* string,
if ([responderDelegate_ respondsToSelector:@selector(resignFirstResponder)])
[responderDelegate_ resignFirstResponder];
- client_->OnNSViewIsFirstResponderChanged(false);
+ client_->OnFirstResponderChanged(false);
if (closeOnDeactivate_) {
[self setHidden:YES];
- client_->OnNSViewRequestShutdown();
+ client_->RequestShutdown();
}
// We should cancel any onging composition whenever RWH's Blur() method gets
@@ -1285,10 +1274,10 @@ void ExtractUnderlines(NSAttributedString* string,
}
bool is_render_view = false;
- client_->OnNSViewSyncIsRenderViewHost(&is_render_view);
+ client_->SyncIsRenderViewHost(&is_render_view);
bool is_speaking = false;
- client_->OnNSViewSyncIsSpeaking(&is_speaking);
+ client_->SyncIsSpeaking(&is_speaking);
SEL action = [item action];
@@ -1333,7 +1322,7 @@ void ExtractUnderlines(NSAttributedString* string,
- (id)accessibilityAttributeValue:(NSString*)attribute {
BrowserAccessibilityManager* manager =
- client_->GetRootBrowserAccessibilityManager();
+ localClient_->GetRootBrowserAccessibilityManager();
// Contents specifies document view of RenderWidgetHostViewCocoa provided by
// BrowserAccessibilityManager. Children includes all subviews in addition to
@@ -1359,7 +1348,7 @@ void ExtractUnderlines(NSAttributedString* string,
- (id)accessibilityHitTest:(NSPoint)point {
BrowserAccessibilityManager* manager =
- client_->GetRootBrowserAccessibilityManager();
+ localClient_->GetRootBrowserAccessibilityManager();
if (!manager)
return self;
NSPoint pointInWindow =
@@ -1374,13 +1363,13 @@ void ExtractUnderlines(NSAttributedString* string,
- (BOOL)accessibilityIsIgnored {
BrowserAccessibilityManager* manager =
- client_->GetRootBrowserAccessibilityManager();
+ localClient_->GetRootBrowserAccessibilityManager();
return !manager;
}
- (NSUInteger)accessibilityGetIndexOf:(id)child {
BrowserAccessibilityManager* manager =
- client_->GetRootBrowserAccessibilityManager();
+ localClient_->GetRootBrowserAccessibilityManager();
// Only child is root.
if (manager && ToBrowserAccessibilityCocoa(manager->GetRoot()) == child) {
return 0;
@@ -1390,8 +1379,18 @@ void ExtractUnderlines(NSAttributedString* string,
}
- (id)accessibilityFocusedUIElement {
+ // If content is overlayed with a focused popup from native UI code, this
+ // getter must return the current menu item as the focused element, rather
+ // than the focus within the content. An example of this occurs with the
+ // Autofill feature, where focus is actually still in the textbox although
+ // the UX acts as if focus is in the popup.
+ gfx::NativeViewAccessible popup_focus_override =
+ ui::AXPlatformNode::GetPopupFocusOverride();
+ if (popup_focus_override)
+ return popup_focus_override;
+
BrowserAccessibilityManager* manager =
- client_->GetRootBrowserAccessibilityManager();
+ localClient_->GetRootBrowserAccessibilityManager();
if (manager) {
BrowserAccessibility* focused_item = manager->GetFocus();
DCHECK(focused_item);
@@ -1488,7 +1487,7 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
gfx::PointF rootPoint(thePoint.x, thePoint.y);
uint32_t index = UINT32_MAX;
- client_->OnNSViewSyncGetCharacterIndexAtPoint(rootPoint, &index);
+ client_->SyncGetCharacterIndexAtPoint(rootPoint, &index);
// |index| could be WTF::notFound (-1) and its value is different from
// NSNotFound so we need to convert it.
if (index == UINT32_MAX)
@@ -1504,8 +1503,9 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
bool success = false;
if (actualRange)
gfxActualRange = gfx::Range(*actualRange);
- client_->OnNSViewSyncGetFirstRectForRange(gfx::Range(theRange), &gfxRect,
- &gfxActualRange, &success);
+ client_->SyncGetFirstRectForRange(gfx::Range(theRange), gfxRect,
+ gfxActualRange, &gfxRect, &gfxActualRange,
+ &success);
if (!success) {
// The call to cancelComposition comes from https://crrev.com/350261.
[self cancelComposition];
@@ -1629,7 +1629,7 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
// If we are handling a key down event, then FinishComposingText() will be
// called in keyEvent: method.
if (!handlingKeyDown_) {
- client_->OnNSViewImeFinishComposingText();
+ client_->ImeFinishComposingText();
} else {
unmarkTextCalled_ = YES;
}
@@ -1672,9 +1672,9 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
if (handlingKeyDown_) {
setMarkedTextReplacementRange_ = gfx::Range(replacementRange);
} else {
- client_->OnNSViewImeSetComposition(
- markedText_, ime_text_spans_, gfx::Range(replacementRange),
- newSelRange.location, NSMaxRange(newSelRange));
+ client_->ImeSetComposition(markedText_, ime_text_spans_,
+ gfx::Range(replacementRange),
+ newSelRange.location, NSMaxRange(newSelRange));
}
}
@@ -1700,7 +1700,7 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
base::CompareCase::INSENSITIVE_ASCII))
editCommands_.push_back(EditCommand(command, ""));
} else {
- client_->OnNSViewExecuteEditCommand(command);
+ client_->ExecuteEditCommand(command);
}
}
@@ -1726,8 +1726,8 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
textToBeInserted_.append(base::SysNSStringToUTF16(im_text));
} else {
gfx::Range replacement_range(replacementRange);
- client_->OnNSViewImeCommitText(base::SysNSStringToUTF16(im_text),
- replacement_range);
+ client_->ImeCommitText(base::SysNSStringToUTF16(im_text),
+ replacement_range);
}
// Inserting text will delete all marked text automatically.
@@ -1744,8 +1744,7 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
[self sendWindowFrameInScreenToClient];
[self sendViewBoundsInWindowToClient];
[self updateScreenProperties];
- client_->OnNSViewIsFirstResponderChanged([[self window] firstResponder] ==
- self);
+ client_->OnFirstResponderChanged([[self window] firstResponder] == self);
// If we switch windows (or are removed from the view hierarchy), cancel any
// open mouse-downs.
@@ -1753,37 +1752,37 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
WebMouseEvent event(WebInputEvent::kMouseUp, WebInputEvent::kNoModifiers,
ui::EventTimeForNow());
event.button = WebMouseEvent::Button::kLeft;
- client_->OnNSViewForwardMouseEvent(event);
+ localClient_->ForwardMouseEvent(event);
hasOpenMouseDown_ = NO;
}
}
- (void)undo:(id)sender {
- client_->OnNSViewUndo();
+ client_->Undo();
}
- (void)redo:(id)sender {
- client_->OnNSViewRedo();
+ client_->Redo();
}
- (void)cut:(id)sender {
- client_->OnNSViewCut();
+ client_->Cut();
}
- (void)copy:(id)sender {
- client_->OnNSViewCopy();
+ client_->Copy();
}
- (void)copyToFindPboard:(id)sender {
- client_->OnNSViewCopyToFindPboard();
+ client_->CopyToFindPboard();
}
- (void)paste:(id)sender {
- client_->OnNSViewPaste();
+ client_->Paste();
}
- (void)pasteAndMatchStyle:(id)sender {
- client_->OnNSViewPasteAndMatchStyle();
+ client_->PasteAndMatchStyle();
}
- (void)selectAll:(id)sender {
@@ -1794,15 +1793,15 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
// menu handler, neither is true.
// Explicitly call SelectAll() here to make sure the renderer returns
// selection results.
- client_->OnNSViewSelectAll();
+ client_->SelectAll();
}
- (void)startSpeaking:(id)sender {
- client_->OnNSViewSpeakSelection();
+ client_->StartSpeaking();
}
- (void)stopSpeaking:(id)sender {
- client_->OnNSViewStopSpeaking();
+ client_->StopSpeaking();
}
- (void)cancelComposition {
@@ -1821,7 +1820,7 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
if (!hasMarkedText_)
return;
- client_->OnNSViewImeFinishComposingText();
+ client_->ImeFinishComposingText();
[self cancelComposition];
}
@@ -1881,7 +1880,7 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
- (void)popupWindowWillClose:(NSNotification*)notification {
[self setHidden:YES];
- client_->OnNSViewRequestShutdown();
+ client_->RequestShutdown();
}
@end
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc b/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc
index af9912a5f02..940d9c10766 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc
@@ -368,14 +368,12 @@ void RenderWidgetHostViewEventHandler::OnMouseEvent(ui::MouseEvent* event) {
if (mouse_wheel_event.delta_x != 0 || mouse_wheel_event.delta_y != 0) {
bool should_route_event = ShouldRouteEvent(event);
- if (host_view_->wheel_scroll_latching_enabled()) {
- // End the touchpad scrolling sequence (if such exists) before handling
- // a ui::ET_MOUSEWHEEL event.
- mouse_wheel_phase_handler_.SendWheelEndForTouchpadScrollingIfNeeded();
+ // End the touchpad scrolling sequence (if such exists) before handling
+ // a ui::ET_MOUSEWHEEL event.
+ mouse_wheel_phase_handler_.SendWheelEndForTouchpadScrollingIfNeeded();
- mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
- mouse_wheel_event, should_route_event);
- }
+ mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
+ mouse_wheel_event, should_route_event);
if (should_route_event) {
host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
host_view_, &mouse_wheel_event, *event->latency());
@@ -435,25 +433,29 @@ void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) {
if (event->finger_count() != 2)
return;
#endif
- blink::WebGestureEvent gesture_event = ui::MakeWebGestureEventFlingCancel();
- // Coordinates need to be transferred to the fling cancel gesture only
- // for Surface-targeting to ensure that it is targeted to the correct
- // RenderWidgetHost.
- gesture_event.SetPositionInWidget(event->location_f());
blink::WebMouseWheelEvent mouse_wheel_event = ui::MakeWebMouseWheelEvent(
*event, base::Bind(&GetScreenLocationFromEvent));
- if (host_view_->wheel_scroll_latching_enabled()) {
- mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
- mouse_wheel_event, should_route_event);
+ mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
+ mouse_wheel_event, should_route_event);
+
+ base::Optional<blink::WebGestureEvent> maybe_synthetic_fling_cancel;
+ if (mouse_wheel_event.phase == blink::WebMouseWheelEvent::kPhaseBegan) {
+ maybe_synthetic_fling_cancel =
+ ui::MakeWebGestureEventFlingCancel(mouse_wheel_event);
}
+
if (should_route_event) {
- host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
- host_view_, &gesture_event,
- ui::LatencyInfo(ui::SourceEventType::WHEEL));
+ if (maybe_synthetic_fling_cancel) {
+ host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
+ host_view_, &*maybe_synthetic_fling_cancel,
+ ui::LatencyInfo(ui::SourceEventType::WHEEL));
+ }
host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
host_view_, &mouse_wheel_event, *event->latency());
} else {
- host_->ForwardGestureEvent(gesture_event);
+ if (maybe_synthetic_fling_cancel) {
+ host_->ForwardGestureEvent(*maybe_synthetic_fling_cancel);
+ }
host_->ForwardWheelEventWithLatencyInfo(mouse_wheel_event,
*event->latency());
}
@@ -749,73 +751,75 @@ void RenderWidgetHostViewEventHandler::HandleMouseEventWhileLocked(
ProcessMouseWheelEvent(mouse_wheel_event, *event->latency());
}
}
- return;
- }
-
- gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
-
- // If we receive non client mouse messages while we are in the locked state
- // it probably means that the mouse left the borders of our window and
- // needs to be moved back to the center.
- if (event->flags() & ui::EF_IS_NON_CLIENT) {
- // TODO(jonross): ideally this would not be done for mus (crbug.com/621412)
- MoveCursorToCenter();
- return;
- }
+ } else {
+ gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
+
+ // If we receive non client mouse messages while we are in the locked state
+ // it probably means that the mouse left the borders of our window and
+ // needs to be moved back to the center.
+ if (event->flags() & ui::EF_IS_NON_CLIENT) {
+ // TODO(jonross): ideally this would not be done for mus
+ // (crbug.com/621412)
+ MoveCursorToCenter();
+ return;
+ }
- blink::WebMouseEvent mouse_event =
- ui::MakeWebMouseEvent(*event, base::Bind(&GetScreenLocationFromEvent));
-
- bool is_move_to_center_event =
- (event->type() == ui::ET_MOUSE_MOVED ||
- event->type() == ui::ET_MOUSE_DRAGGED) &&
- mouse_event.PositionInWidget().x == center.x() &&
- mouse_event.PositionInWidget().y == center.y();
-
- // For fractional scale factors, the conversion from pixels to dip and
- // vice versa could result in off by 1 or 2 errors which hurts us because
- // we want to avoid sending the artificial move to center event to the
- // renderer. Sending the move to center to the renderer cause the cursor
- // to bounce around the center of the screen leading to the lock operation
- // not working correctly.
- // Workaround is to treat a mouse move or drag event off by at most 2 px
- // from the center as a move to center event.
- if (synthetic_move_sent_ &&
- IsFractionalScaleFactor(host_view_->current_device_scale_factor())) {
- if (event->type() == ui::ET_MOUSE_MOVED ||
- event->type() == ui::ET_MOUSE_DRAGGED) {
- if ((std::abs(mouse_event.PositionInWidget().x - center.x()) <= 2) &&
- (std::abs(mouse_event.PositionInWidget().y - center.y()) <= 2)) {
- is_move_to_center_event = true;
+ blink::WebMouseEvent mouse_event =
+ ui::MakeWebMouseEvent(*event, base::Bind(&GetScreenLocationFromEvent));
+
+ bool is_move_to_center_event =
+ (event->type() == ui::ET_MOUSE_MOVED ||
+ event->type() == ui::ET_MOUSE_DRAGGED) &&
+ mouse_event.PositionInWidget().x == center.x() &&
+ mouse_event.PositionInWidget().y == center.y();
+
+ // For fractional scale factors, the conversion from pixels to dip and
+ // vice versa could result in off by 1 or 2 errors which hurts us because
+ // we want to avoid sending the artificial move to center event to the
+ // renderer. Sending the move to center to the renderer cause the cursor
+ // to bounce around the center of the screen leading to the lock operation
+ // not working correctly.
+ // Workaround is to treat a mouse move or drag event off by at most 2 px
+ // from the center as a move to center event.
+ if (synthetic_move_sent_ &&
+ IsFractionalScaleFactor(host_view_->current_device_scale_factor())) {
+ if (event->type() == ui::ET_MOUSE_MOVED ||
+ event->type() == ui::ET_MOUSE_DRAGGED) {
+ if ((std::abs(mouse_event.PositionInWidget().x - center.x()) <= 2) &&
+ (std::abs(mouse_event.PositionInWidget().y - center.y()) <= 2)) {
+ is_move_to_center_event = true;
+ }
}
}
- }
- ModifyEventMovementAndCoords(*event, &mouse_event);
+ ModifyEventMovementAndCoords(*event, &mouse_event);
- bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
- if (should_not_forward) {
- synthetic_move_sent_ = false;
- } else {
- // Check if the mouse has reached the border and needs to be centered.
- if (ShouldMoveToCenter())
- MoveCursorToCenter();
- bool is_selection_popup = NeedsInputGrab(popup_child_host_view_);
- // Forward event to renderer.
- if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
- !(event->flags() & ui::EF_FROM_TOUCH)) {
- if (ShouldRouteEvent(event)) {
- host_->delegate()->GetInputEventRouter()->RouteMouseEvent(
- host_view_, &mouse_event, *event->latency());
- } else {
- ProcessMouseEvent(mouse_event, *event->latency());
+ bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
+ if (should_not_forward) {
+ synthetic_move_sent_ = false;
+ } else {
+ // Check if the mouse has reached the border and needs to be centered.
+ if (ShouldMoveToCenter())
+ MoveCursorToCenter();
+ bool is_selection_popup = NeedsInputGrab(popup_child_host_view_);
+ // Forward event to renderer.
+ if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
+ !(event->flags() & ui::EF_FROM_TOUCH)) {
+ if (ShouldRouteEvent(event)) {
+ host_->delegate()->GetInputEventRouter()->RouteMouseEvent(
+ host_view_, &mouse_event, *event->latency());
+ } else {
+ ProcessMouseEvent(mouse_event, *event->latency());
+ }
+ // Ensure that we get keyboard focus on mouse down as a plugin window
+ // may have grabbed keyboard focus.
+ if (event->type() == ui::ET_MOUSE_PRESSED)
+ SetKeyboardFocus();
}
- // Ensure that we get keyboard focus on mouse down as a plugin window
- // may have grabbed keyboard focus.
- if (event->type() == ui::ET_MOUSE_PRESSED)
- SetKeyboardFocus();
}
}
+ if (!ShouldGenerateAppCommand(event))
+ event->SetHandled();
}
void RenderWidgetHostViewEventHandler::ModifyEventMovementAndCoords(
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h b/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h
index 2e4f30a6017..5db1ce0507a 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h
@@ -179,6 +179,8 @@ class CONTENT_EXPORT RenderWidgetHostViewEventHandler
FRIEND_TEST_ALL_PREFIXES(
RenderWidgetHostViewAuraTest,
KeyEventRoutingKeyboardLockAndChildPopupWithoutInputGrab);
+ friend class MockPointerLockRenderWidgetHostView;
+
// Returns true if the |event| passed in can be forwarded to the renderer.
bool CanRendererHandleEvent(const ui::MouseEvent* event,
bool mouse_locked,
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 7a4fdcecf33..052bcb2791c 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,21 +21,14 @@
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/content_export.h"
+#include "content/common/render_widget_host_ns_view.mojom.h"
#include "ipc/ipc_sender.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
+#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
#include "ui/accelerated_widget_mac/display_link_mac.h"
#include "ui/base/cocoa/remote_layer_api.h"
#include "ui/events/gesture_detection/filtered_gesture_provider.h"
-namespace content {
-class CursorManager;
-class RenderWidgetHost;
-class RenderWidgetHostNSViewBridge;
-class RenderWidgetHostViewMac;
-class WebContents;
-class WebCursor;
-}
-
namespace ui {
enum class DomCode;
class ScopedPasswordInputEnabler;
@@ -47,6 +40,13 @@ class ScopedPasswordInputEnabler;
namespace content {
+class CursorManager;
+class RenderWidgetHost;
+class RenderWidgetHostNSViewBridgeLocal;
+class RenderWidgetHostViewMac;
+class WebContents;
+class WebCursor;
+
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewMac
//
@@ -65,9 +65,11 @@ namespace content {
// RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
class CONTENT_EXPORT RenderWidgetHostViewMac
: public RenderWidgetHostViewBase,
- public RenderWidgetHostNSViewClient,
+ public RenderWidgetHostNSViewLocalClient,
+ public mojom::RenderWidgetHostNSViewClient,
public BrowserCompositorMacClient,
public TextInputManager::Observer,
+ public ui::CATransactionCoordinator::PreCommitObserver,
public ui::GestureProviderClient,
public ui::AcceleratedWidgetMacNSView,
public IPC::Sender {
@@ -104,6 +106,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void WasUnOccluded() override;
void WasOccluded() override;
gfx::Rect GetViewBounds() const override;
+ bool IsMouseLocked() override;
void SetActive(bool active) override;
void ShowDefinitionForSelection() override;
void SpeakSelection() override;
@@ -150,10 +153,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds) override;
- gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override;
+ gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
base::Optional<SkColor> GetBackgroundColor() const override;
- bool ShouldContinueToPauseForFrame() override;
void SetParentUiLayer(ui::Layer* parent_ui_layer) override;
void TransformPointToRootSurface(gfx::PointF* point) override;
gfx::Rect GetBoundsInRootWindow() override;
@@ -166,6 +168,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
bool LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes) override;
void UnlockKeyboard() override;
bool IsKeyboardLocked() override;
+ base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
void GestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result) override;
void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
@@ -176,8 +179,8 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
std::unique_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
override;
- viz::FrameSinkId GetFrameSinkId() override;
- viz::LocalSurfaceId GetLocalSurfaceId() const override;
+ const viz::FrameSinkId& GetFrameSinkId() const override;
+ const viz::LocalSurfaceId& GetLocalSurfaceId() const override;
// Returns true when we can do SurfaceHitTesting for the event type.
bool ShouldRouteEvent(const blink::WebInputEvent& event) const;
// This method checks |event| to see if a GesturePinch event can be routed
@@ -220,11 +223,15 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void OnTextSelectionChanged(TextInputManager* text_input_manager,
RenderWidgetHostViewBase* updated_view) override;
+ // ui::CATransactionCoordinator::PreCommitObserver implementation
+ bool ShouldWaitInPreCommit() override;
+ base::TimeDelta PreCommitTimeout() override;
+
// ui::GestureProviderClient implementation.
void OnGestureEvent(const ui::GestureEventData& gesture) override;
// RenderFrameMetadataProvider::Observer
- void OnRenderFrameMetadataChanged() override;
+ void OnRenderFrameMetadataChangedAfterActivation() override;
// IPC::Sender implementation.
bool Send(IPC::Message* message) override;
@@ -292,74 +299,94 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// RenderWidgetHostImpl as well.
void UpdateNSViewAndDisplayProperties();
- void PauseForPendingResizeOrRepaintsAndDraw();
-
- // RenderWidgetHostNSViewClient implementation.
+ // RenderWidgetHostNSViewLocalClient implementation.
BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override;
- void OnNSViewSyncIsRenderViewHost(bool* is_render_view) override;
- void OnNSViewRequestShutdown() override;
- void OnNSViewIsFirstResponderChanged(bool is_first_responder) override;
- void OnNSViewWindowIsKeyChanged(bool is_key) override;
- void OnNSViewBoundsInWindowChanged(const gfx::Rect& view_bounds_in_window_dip,
- bool attached_to_window) override;
- void OnNSViewWindowFrameInScreenChanged(
- const gfx::Rect& window_frame_in_screen_dip) override;
- void OnNSViewDisplayChanged(const display::Display& display) override;
- void OnNSViewBeginKeyboardEvent() override;
- void OnNSViewEndKeyboardEvent() override;
- void OnNSViewForwardKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info) override;
- void OnNSViewForwardKeyboardEventWithCommands(
+ void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info) override;
+ void ForwardKeyboardEventWithCommands(
const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency_info,
const std::vector<EditCommand>& commands) override;
- void OnNSViewRouteOrProcessMouseEvent(
- const blink::WebMouseEvent& web_event) override;
- void OnNSViewRouteOrProcessWheelEvent(
- const blink::WebMouseWheelEvent& web_event) override;
- void OnNSViewForwardMouseEvent(
- const blink::WebMouseEvent& web_event) override;
- void OnNSViewForwardWheelEvent(
+ void RouteOrProcessMouseEvent(const blink::WebMouseEvent& web_event) override;
+ void RouteOrProcessWheelEvent(
const blink::WebMouseWheelEvent& web_event) override;
- void OnNSViewGestureBegin(blink::WebGestureEvent begin_event,
- bool is_synthetically_injected) override;
- void OnNSViewGestureUpdate(blink::WebGestureEvent update_event) override;
- void OnNSViewGestureEnd(blink::WebGestureEvent end_event) override;
- void OnNSViewSmartMagnify(
- const blink::WebGestureEvent& smart_magnify_event) override;
- void OnNSViewImeSetComposition(
- const base::string16& text,
- const std::vector<ui::ImeTextSpan>& ime_text_spans,
- const gfx::Range& replacement_range,
- int selection_start,
- int selection_end) override;
- void OnNSViewImeCommitText(const base::string16& text,
- const gfx::Range& replacement_range) override;
- void OnNSViewImeFinishComposingText() override;
- void OnNSViewImeCancelComposition() override;
- void OnNSViewLookUpDictionaryOverlayAtPoint(
- const gfx::PointF& root_point) override;
- void OnNSViewLookUpDictionaryOverlayFromRange(
- const gfx::Range& range) override;
- void OnNSViewSyncGetCharacterIndexAtPoint(const gfx::PointF& root_point,
- uint32_t* index) override;
- void OnNSViewSyncGetFirstRectForRange(const gfx::Range& requested_range,
- gfx::Rect* rect,
- gfx::Range* actual_range,
- bool* success) override;
- void OnNSViewExecuteEditCommand(const std::string& command) override;
- void OnNSViewUndo() override;
- void OnNSViewRedo() override;
- void OnNSViewCut() override;
- void OnNSViewCopy() override;
- void OnNSViewCopyToFindPboard() override;
- void OnNSViewPaste() override;
- void OnNSViewPasteAndMatchStyle() override;
- void OnNSViewSelectAll() override;
- void OnNSViewSpeakSelection() override;
- void OnNSViewStopSpeaking() override;
- void OnNSViewSyncIsSpeaking(bool* is_speaking) override;
+ void ForwardMouseEvent(const blink::WebMouseEvent& web_event) override;
+ void ForwardWheelEvent(const blink::WebMouseWheelEvent& web_event) override;
+ void GestureBegin(blink::WebGestureEvent begin_event,
+ bool is_synthetically_injected) override;
+ void GestureUpdate(blink::WebGestureEvent update_event) override;
+ void GestureEnd(blink::WebGestureEvent end_event) override;
+ void SmartMagnify(const blink::WebGestureEvent& smart_magnify_event) override;
+
+ // mojom::RenderWidgetHostNSViewClient implementation.
+ void SyncIsRenderViewHost(SyncIsRenderViewHostCallback callback) override;
+ bool SyncIsRenderViewHost(bool* is_render_view) override;
+ void RequestShutdown() override;
+ void OnFirstResponderChanged(bool is_first_responder) override;
+ void OnWindowIsKeyChanged(bool is_key) override;
+ void OnBoundsInWindowChanged(const gfx::Rect& view_bounds_in_window_dip,
+ bool attached_to_window) override;
+ void OnWindowFrameInScreenChanged(
+ const gfx::Rect& window_frame_in_screen_dip) override;
+ void OnDisplayChanged(const display::Display& display) override;
+ void BeginKeyboardEvent() override;
+ void EndKeyboardEvent() override;
+
+ void ForwardKeyboardEvent(std::unique_ptr<InputEvent> event,
+ bool skip_in_browser) override;
+ void ForwardKeyboardEventWithCommands(
+ std::unique_ptr<InputEvent> event,
+ bool skip_in_browser,
+ const std::vector<EditCommand>& commands) override;
+ void RouteOrProcessMouseEvent(std::unique_ptr<InputEvent> event) override;
+ void RouteOrProcessWheelEvent(std::unique_ptr<InputEvent> event) override;
+ void ForwardMouseEvent(std::unique_ptr<InputEvent> event) override;
+ void ForwardWheelEvent(std::unique_ptr<InputEvent> event) override;
+ void GestureBegin(std::unique_ptr<InputEvent> event,
+ bool is_synthetically_injected) override;
+ void GestureUpdate(std::unique_ptr<InputEvent> event) override;
+ void GestureEnd(std::unique_ptr<InputEvent> event) override;
+ void SmartMagnify(std::unique_ptr<InputEvent> event) override;
+ void ImeSetComposition(const base::string16& text,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& replacement_range,
+ int selection_start,
+ int selection_end) override;
+ void ImeCommitText(const base::string16& text,
+ const gfx::Range& replacement_range) override;
+ void ImeFinishComposingText() override;
+ void ImeCancelCompositionFromCocoa() override;
+ void LookUpDictionaryOverlayAtPoint(const gfx::PointF& root_point) override;
+ void LookUpDictionaryOverlayFromRange(const gfx::Range& range) override;
+ void SyncGetCharacterIndexAtPoint(
+ const gfx::PointF& root_point,
+ SyncGetCharacterIndexAtPointCallback callback) override;
+ bool SyncGetCharacterIndexAtPoint(const gfx::PointF& root_point,
+ uint32_t* index) override;
+ void SyncGetFirstRectForRange(
+ const gfx::Range& requested_range,
+ const gfx::Rect& rect,
+ const gfx::Range& actual_range,
+ SyncGetFirstRectForRangeCallback callback) override;
+ bool SyncGetFirstRectForRange(const gfx::Range& requested_range,
+ const gfx::Rect& rect,
+ const gfx::Range& actual_range,
+ gfx::Rect* out_rect,
+ gfx::Range* out_actual_range,
+ bool* out_success) override;
+ void ExecuteEditCommand(const std::string& command) override;
+ void Undo() override;
+ void Redo() override;
+ void Cut() override;
+ void Copy() override;
+ void CopyToFindPboard() override;
+ void Paste() override;
+ void PasteAndMatchStyle() override;
+ void SelectAll() override;
+ void StartSpeaking() override;
+ void StopSpeaking() override;
+ bool SyncIsSpeaking(bool* is_speaking) override;
+ void SyncIsSpeaking(SyncIsSpeakingCallback callback) override;
// BrowserCompositorMacClient implementation.
SkColor BrowserCompositorMacGetGutterColor() const override;
@@ -367,10 +394,11 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void OnFrameTokenChanged(uint32_t frame_token) override;
void DidReceiveFirstFrameAfterNavigation() override;
void DestroyCompositorForShutdown() override;
- bool SynchronizeVisualProperties() override;
+ bool SynchronizeVisualProperties(
+ const base::Optional<viz::LocalSurfaceId>&
+ child_allocated_local_surface_id) override;
// AcceleratedWidgetMacNSView implementation.
- NSView* AcceleratedWidgetGetNSView() const override;
void AcceleratedWidgetCALayerParamsUpdated() override;
void SetShowingContextMenu(bool showing) override;
@@ -423,6 +451,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
private:
friend class RenderWidgetHostViewMacTest;
+ friend class MockPointerLockRenderWidgetHostView;
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewMacTest, GetPageTextForSpeech);
// Allocate a new FrameSinkId if this object is the platform view of a
@@ -465,8 +494,15 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
using SpeechCallback = base::OnceCallback<void(const base::string16&)>;
void GetPageTextForSpeech(SpeechCallback callback);
- // Interface through which the NSView is to be manipulated.
- std::unique_ptr<RenderWidgetHostNSViewBridge> ns_view_bridge_;
+ // Interface through which the NSView is to be manipulated. This points either
+ // to |ns_view_bridge_local_| or to (to-be-added) |ns_view_bridge_remote_|.
+ mojom::RenderWidgetHostNSViewBridge* ns_view_bridge_ = nullptr;
+
+ // If |ns_view_bridge_| is hosted in this process, then this will be non-null,
+ // and may be used to query the actual RenderWidgetHostViewCocoa that is being
+ // used for |this|. Any functionality that uses |new_view_bridge_local_| will
+ // not work when the RenderWidgetHostViewCocoa is hosted in an app process.
+ std::unique_ptr<RenderWidgetHostNSViewBridgeLocal> ns_view_bridge_local_;
// State tracked by Show/Hide/IsShowing.
bool is_visible_ = false;
@@ -492,9 +528,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Indicates if the page is loading.
bool is_loading_;
- // Whether it's allowed to pause waiting for a new frame.
- bool allow_pause_for_resize_or_repaint_;
-
// True when this view acts as a platform view hack for a
// RenderWidgetHostViewGuest.
bool is_guest_view_hack_;
@@ -524,8 +557,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// AcceleratedWidgetCALayerParamsUpdated).
SkColor last_frame_root_background_color_ = SK_ColorTRANSPARENT;
- int tab_show_sequence_ = 0;
-
std::unique_ptr<CursorManager> cursor_manager_;
// Used to track active password input sessions.
@@ -564,6 +595,13 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Tracks whether keyboard lock is active.
bool is_keyboard_locked_ = false;
+ // While the mouse is locked, the cursor is hidden from the user. Mouse events
+ // are still generated. However, the position they report is the last known
+ // mouse position just as mouse lock was entered; the movement they report
+ // indicates what the change in position of the mouse would be had it not been
+ // locked.
+ bool mouse_locked_ = false;
+
// Latest capture sequence number which is incremented when the caller
// requests surfaces be synchronized via
// EnsureSurfaceSynchronizedForLayoutTest().
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 8b012bcb8f7..0703dd02c90 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
@@ -27,7 +27,7 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
-#import "content/browser/renderer_host/render_widget_host_ns_view_bridge.h"
+#import "content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h"
#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
#import "content/browser/renderer_host/text_input_client_mac.h"
#import "content/browser/renderer_host/ui_events_helper.h"
@@ -51,6 +51,7 @@
#include "ui/display/screen.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/dom_keyboard_layout_map.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/mac/coordinate_conversion.h"
@@ -59,6 +60,10 @@ using blink::WebMouseEvent;
using blink::WebGestureEvent;
using blink::WebTouchEvent;
+namespace {
+constexpr auto kContentPaintTimeout = base::TimeDelta::FromMilliseconds(167);
+} // namespace
+
namespace content {
////////////////////////////////////////////////////////////////////////////////
@@ -98,17 +103,28 @@ void RenderWidgetHostViewMac::DestroyCompositorForShutdown() {
Destroy();
}
-bool RenderWidgetHostViewMac::SynchronizeVisualProperties() {
+bool RenderWidgetHostViewMac::SynchronizeVisualProperties(
+ const base::Optional<viz::LocalSurfaceId>&
+ child_allocated_local_surface_id) {
+ if (child_allocated_local_surface_id) {
+ browser_compositor_->UpdateRendererLocalSurfaceIdFromChild(
+ *child_allocated_local_surface_id);
+ } else {
+ browser_compositor_->AllocateNewRendererLocalSurfaceId();
+ }
+
+ if (auto* host = browser_compositor_->GetDelegatedFrameHost()) {
+ host->EmbedSurface(browser_compositor_->GetRendererLocalSurfaceId(),
+ browser_compositor_->GetRendererSize(),
+ cc::DeadlinePolicy::UseDefaultDeadline());
+ }
+
return host()->SynchronizeVisualProperties();
}
////////////////////////////////////////////////////////////////////////////////
// AcceleratedWidgetMacNSView, public:
-NSView* RenderWidgetHostViewMac::AcceleratedWidgetGetNSView() const {
- return cocoa_view();
-}
-
void RenderWidgetHostViewMac::AcceleratedWidgetCALayerParamsUpdated() {
// Set the background color for the root layer from the frame that just
// swapped. See RenderWidgetHostViewAura for more details. Note that this is
@@ -135,14 +151,15 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
page_at_minimum_scale_(true),
mouse_wheel_phase_handler_(this),
is_loading_(false),
- allow_pause_for_resize_or_repaint_(true),
is_guest_view_hack_(is_guest_view_hack),
gesture_provider_(ui::GetGestureProviderConfig(
ui::GestureProviderConfigType::CURRENT_PLATFORM),
this),
weak_factory_(this) {
// The NSView is on the other side of |ns_view_bridge_|.
- ns_view_bridge_ = RenderWidgetHostNSViewBridge::Create(this);
+ ns_view_bridge_local_ =
+ std::make_unique<RenderWidgetHostNSViewBridgeLocal>(this, this);
+ ns_view_bridge_ = ns_view_bridge_local_.get();
// Guess that the initial screen we will be on is the screen of the current
// window (since that's the best guess that we have, and is usually right).
@@ -154,9 +171,9 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
? AllocateFrameSinkIdForGuestViewHack()
: host()->GetFrameSinkId();
- browser_compositor_.reset(
- new BrowserCompositorMac(this, this, host()->is_hidden(),
- [cocoa_view() window], display_, frame_sink_id));
+ browser_compositor_.reset(new BrowserCompositorMac(
+ this, this, host()->is_hidden(), display_, frame_sink_id));
+ DCHECK(![cocoa_view() window]);
if (!is_guest_view_hack_)
host()->SetView(this);
@@ -193,13 +210,17 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
// startup raciness and decrease latency.
needs_begin_frames_ = needs_begin_frames;
UpdateNeedsBeginFramesInternal();
+ if (features::IsViewsBrowserCocoa())
+ ui::CATransactionCoordinator::Get().AddPreCommitObserver(this);
}
RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
+ if (features::IsViewsBrowserCocoa())
+ ui::CATransactionCoordinator::Get().RemovePreCommitObserver(this);
}
void RenderWidgetHostViewMac::SetParentUiLayer(ui::Layer* parent_ui_layer) {
- if (!display_only_using_parent_ui_layer_) {
+ if (parent_ui_layer && !display_only_using_parent_ui_layer_) {
// The first time that we display using a parent ui::Layer, permanently
// switch from drawing using Cocoa to only drawing using ui::Views. Erase
// the existing content being drawn by Cocoa (which may have been set due
@@ -214,7 +235,9 @@ void RenderWidgetHostViewMac::SetParentUiLayer(ui::Layer* parent_ui_layer) {
}
RenderWidgetHostViewCocoa* RenderWidgetHostViewMac::cocoa_view() const {
- return ns_view_bridge_->GetRenderWidgetHostViewCocoa();
+ if (ns_view_bridge_local_)
+ return ns_view_bridge_local_->GetRenderWidgetHostViewCocoa();
+ return nullptr;
}
void RenderWidgetHostViewMac::SetDelegate(
@@ -223,7 +246,8 @@ void RenderWidgetHostViewMac::SetDelegate(
}
void RenderWidgetHostViewMac::SetAllowPauseForResizeOrRepaint(bool allow) {
- allow_pause_for_resize_or_repaint_ = allow;
+ // TODO: Remove SetAllowPauseForResizeOrRepaint and SetAllowOtherViews, since
+ // they aren't used anymore.
}
ui::TextInputType RenderWidgetHostViewMac::GetTextInputType() {
@@ -326,6 +350,9 @@ void RenderWidgetHostViewMac::UpdateNSViewAndDisplayProperties() {
}
}
+ if (features::IsViewsBrowserCocoa())
+ ui::CATransactionCoordinator::Get().Synchronize();
+
// During auto-resize it is the responsibility of the caller to ensure that
// the NSView and RenderWidgetHostImpl are kept in sync.
if (host()->auto_resize_enabled())
@@ -353,32 +380,44 @@ void RenderWidgetHostViewMac::GetScreenInfo(ScreenInfo* screen_info) const {
void RenderWidgetHostViewMac::Show() {
is_visible_ = true;
ns_view_bridge_->SetVisible(is_visible_);
+ browser_compositor_->SetViewVisible(is_visible_);
browser_compositor_->SetRenderWidgetHostIsHidden(false);
- ui::LatencyInfo renderer_latency_info;
- renderer_latency_info.AddLatencyNumber(ui::TAB_SHOW_COMPONENT,
- host()->GetLatencyComponentId());
- renderer_latency_info.set_trace_id(++tab_show_sequence_);
- host()->WasShown(renderer_latency_info);
- TRACE_EVENT_ASYNC_BEGIN0("latency", "TabSwitching::Latency",
- tab_show_sequence_);
-
- // If there is not a frame being currently drawn, kick one, so that the below
- // pause will have a frame to wait on.
- host()->RequestRepaintForTesting();
- PauseForPendingResizeOrRepaintsAndDraw();
+ WasUnOccluded();
}
void RenderWidgetHostViewMac::Hide() {
is_visible_ = false;
ns_view_bridge_->SetVisible(is_visible_);
+ browser_compositor_->SetViewVisible(is_visible_);
host()->WasHidden();
browser_compositor_->SetRenderWidgetHostIsHidden(true);
}
void RenderWidgetHostViewMac::WasUnOccluded() {
browser_compositor_->SetRenderWidgetHostIsHidden(false);
- host()->WasShown(ui::LatencyInfo());
+
+ DelegatedFrameHost* delegated_frame_host =
+ browser_compositor_->GetDelegatedFrameHost();
+
+ bool has_saved_frame =
+ delegated_frame_host ? delegated_frame_host->HasSavedFrame() : false;
+
+ // If the primary surface was evicted, we should create a new primary.
+ if (delegated_frame_host && delegated_frame_host->IsPrimarySurfaceEvicted())
+ SynchronizeVisualProperties(base::nullopt);
+
+ const bool renderer_should_record_presentation_time = !has_saved_frame;
+ host()->WasShown(renderer_should_record_presentation_time);
+
+ if (delegated_frame_host) {
+ // If the frame for the renderer is already available, then the
+ // tab-switching time is the presentation time for the browser-compositor.
+ const bool record_presentation_time = has_saved_frame;
+ delegated_frame_host->WasShown(
+ browser_compositor_->GetRendererLocalSurfaceId(),
+ browser_compositor_->GetRendererSize(), record_presentation_time);
+ }
}
void RenderWidgetHostViewMac::WasOccluded() {
@@ -426,6 +465,10 @@ gfx::Rect RenderWidgetHostViewMac::GetViewBounds() const {
window_frame_in_screen_dip_.OffsetFromOrigin();
}
+bool RenderWidgetHostViewMac::IsMouseLocked() {
+ return mouse_locked_;
+}
+
void RenderWidgetHostViewMac::UpdateCursor(const WebCursor& cursor) {
GetCursorManager()->UpdateCursor(this, cursor);
}
@@ -548,6 +591,17 @@ void RenderWidgetHostViewMac::OnTextSelectionChanged(
return;
ns_view_bridge_->SetTextSelection(selection->text(), selection->offset(),
selection->range());
+ if (host() && host()->delegate())
+ host()->delegate()->DidChangeTextSelection(selection->text(),
+ selection->range());
+}
+
+bool RenderWidgetHostViewMac::ShouldWaitInPreCommit() {
+ return browser_compositor_->ShouldContinueToPauseForFrame();
+}
+
+base::TimeDelta RenderWidgetHostViewMac::PreCommitTimeout() {
+ return kContentPaintTimeout;
}
void RenderWidgetHostViewMac::OnGestureEvent(
@@ -566,12 +620,12 @@ void RenderWidgetHostViewMac::OnGestureEvent(
}
}
-void RenderWidgetHostViewMac::OnRenderFrameMetadataChanged() {
+void RenderWidgetHostViewMac::OnRenderFrameMetadataChangedAfterActivation() {
last_frame_root_background_color_ = host()
->render_frame_metadata_provider()
->LastRenderFrameMetadata()
.root_background_color;
- RenderWidgetHostViewBase::OnRenderFrameMetadataChanged();
+ RenderWidgetHostViewBase::OnRenderFrameMetadataChangedAfterActivation();
}
void RenderWidgetHostViewMac::RenderProcessGone(base::TerminationStatus status,
@@ -589,7 +643,8 @@ void RenderWidgetHostViewMac::Destroy() {
// Destroy the brige to the NSView. Note that the NSView on the other side
// of |ns_view_bridge_| may outlive us due to other retains.
- ns_view_bridge_.reset();
+ ns_view_bridge_ = nullptr;
+ ns_view_bridge_local_.reset();
// Delete the delegated frame state, which will reach back into
// host().
@@ -731,7 +786,7 @@ void RenderWidgetHostViewMac::CopyFromSurface(
void RenderWidgetHostViewMac::EnsureSurfaceSynchronizedForLayoutTest() {
++latest_capture_sequence_number_;
- SynchronizeVisualProperties();
+ SynchronizeVisualProperties(base::nullopt);
}
void RenderWidgetHostViewMac::SetNeedsBeginFrames(bool needs_begin_frames) {
@@ -746,7 +801,7 @@ void RenderWidgetHostViewMac::UpdateNeedsBeginFramesInternal() {
void RenderWidgetHostViewMac::OnDidUpdateVisualPropertiesComplete(
const cc::RenderFrameMetadata& metadata) {
browser_compositor_->SynchronizeVisualProperties(
- metadata.viewport_size_in_pixels,
+ metadata.device_scale_factor, metadata.viewport_size_in_pixels,
metadata.local_surface_id.value_or(viz::LocalSurfaceId()));
}
@@ -940,14 +995,6 @@ bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(
return true;
}
-bool RenderWidgetHostViewMac::ShouldContinueToPauseForFrame() {
- // Only pause for frames when drawing through a separate ui::Compositor.
- if (display_only_using_parent_ui_layer_)
- return false;
-
- return browser_compositor_->ShouldContinueToPauseForFrame();
-}
-
void RenderWidgetHostViewMac::FocusedNodeChanged(
bool is_editable_node,
const gfx::Rect& node_bounds_in_screen) {
@@ -998,8 +1045,7 @@ bool RenderWidgetHostViewMac::RequestRepaintForTesting() {
}
void RenderWidgetHostViewMac::TransformPointToRootSurface(gfx::PointF* point) {
- if (display_only_using_parent_ui_layer_)
- *point += view_bounds_in_window_dip_.OffsetFromOrigin();
+ browser_compositor_->TransformPointToRootSurface(point);
}
gfx::Rect RenderWidgetHostViewMac::GetBoundsInRootWindow() {
@@ -1033,8 +1079,14 @@ void RenderWidgetHostViewMac::UnlockMouse() {
bool RenderWidgetHostViewMac::LockKeyboard(
base::Optional<base::flat_set<ui::DomCode>> dom_codes) {
+ base::Optional<std::vector<uint32_t>> uint_dom_codes;
+ if (dom_codes) {
+ uint_dom_codes.emplace();
+ for (const auto& dom_code : *dom_codes)
+ uint_dom_codes->push_back(static_cast<uint32_t>(dom_code));
+ }
is_keyboard_locked_ = true;
- ns_view_bridge_->LockKeyboard(std::move(dom_codes));
+ ns_view_bridge_->LockKeyboard(uint_dom_codes);
return true;
}
@@ -1050,8 +1102,15 @@ bool RenderWidgetHostViewMac::IsKeyboardLocked() {
return is_keyboard_locked_;
}
+base::flat_map<std::string, std::string>
+RenderWidgetHostViewMac::GetKeyboardLayoutMap() {
+ return ui::GenerateDomKeyboardLayoutMap();
+}
+
void RenderWidgetHostViewMac::GestureEventAck(const WebGestureEvent& event,
InputEventAckState ack_result) {
+ ForwardTouchpadPinchIfNecessary(event, ack_result);
+
bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
switch (event.GetType()) {
case WebInputEvent::kGestureScrollBegin:
@@ -1095,11 +1154,11 @@ RenderWidgetHostViewMac::CreateSyntheticGestureTarget() {
new SyntheticGestureTargetMac(host, cocoa_view()));
}
-viz::LocalSurfaceId RenderWidgetHostViewMac::GetLocalSurfaceId() const {
+const viz::LocalSurfaceId& RenderWidgetHostViewMac::GetLocalSurfaceId() const {
return browser_compositor_->GetRendererLocalSurfaceId();
}
-viz::FrameSinkId RenderWidgetHostViewMac::GetFrameSinkId() {
+const viz::FrameSinkId& RenderWidgetHostViewMac::GetFrameSinkId() const {
return browser_compositor_->GetDelegatedFrameHost()->frame_sink_id();
}
@@ -1267,9 +1326,9 @@ gfx::Point RenderWidgetHostViewMac::AccessibilityOriginInScreen(
return gfx::Point(originInScreen.x, originInScreen.y);
}
-gfx::AcceleratedWidget
-RenderWidgetHostViewMac::AccessibilityGetAcceleratedWidget() {
- return browser_compositor_->GetAcceleratedWidget();
+gfx::NativeViewAccessible
+RenderWidgetHostViewMac::AccessibilityGetNativeViewAccessible() {
+ return cocoa_view();
}
void RenderWidgetHostViewMac::SetTextInputActive(bool active) {
@@ -1281,22 +1340,6 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) {
password_input_enabler_.reset();
}
-void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() {
- if (!host() || !browser_compositor_ || host()->is_hidden()) {
- return;
- }
-
- // Pausing for one view prevents others from receiving frames.
- // This may lead to large delays, causing overlaps. See crbug.com/352020.
- if (!allow_pause_for_resize_or_repaint_)
- return;
-
- // Wait for a frame of the right size to come in.
- browser_compositor_->BeginPauseForFrame(host()->auto_resize_enabled());
- host()->PauseForPendingResizeOrRepaints();
- browser_compositor_->EndPauseForFrame();
-}
-
// static
viz::FrameSinkId
RenderWidgetHostViewMac::AllocateFrameSinkIdForGuestViewHack() {
@@ -1310,19 +1353,27 @@ MouseWheelPhaseHandler* RenderWidgetHostViewMac::GetMouseWheelPhaseHandler() {
}
///////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostNSViewClient implementation:
+// RenderWidgetHostNSViewLocalClient and mojom::RenderWidgetHostNSViewClient
+// implementation:
BrowserAccessibilityManager*
RenderWidgetHostViewMac::GetRootBrowserAccessibilityManager() {
return host()->GetRootBrowserAccessibilityManager();
}
-void RenderWidgetHostViewMac::OnNSViewSyncIsRenderViewHost(
- bool* is_render_view) {
+bool RenderWidgetHostViewMac::SyncIsRenderViewHost(bool* is_render_view) {
*is_render_view = RenderViewHost::From(host()) != nullptr;
+ return true;
}
-void RenderWidgetHostViewMac::OnNSViewRequestShutdown() {
+void RenderWidgetHostViewMac::SyncIsRenderViewHost(
+ SyncIsRenderViewHostCallback callback) {
+ bool is_render_view;
+ SyncIsRenderViewHost(&is_render_view);
+ std::move(callback).Run(is_render_view);
+}
+
+void RenderWidgetHostViewMac::RequestShutdown() {
if (!weak_factory_.HasWeakPtrs()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&RenderWidgetHostViewMac::ShutdownHost,
@@ -1330,8 +1381,7 @@ void RenderWidgetHostViewMac::OnNSViewRequestShutdown() {
}
}
-void RenderWidgetHostViewMac::OnNSViewIsFirstResponderChanged(
- bool is_first_responder) {
+void RenderWidgetHostViewMac::OnFirstResponderChanged(bool is_first_responder) {
if (is_first_responder_ == is_first_responder)
return;
is_first_responder_ = is_first_responder;
@@ -1344,11 +1394,11 @@ void RenderWidgetHostViewMac::OnNSViewIsFirstResponderChanged(
}
}
-void RenderWidgetHostViewMac::OnNSViewWindowIsKeyChanged(bool is_key) {
+void RenderWidgetHostViewMac::OnWindowIsKeyChanged(bool is_key) {
SetActive(is_key);
}
-void RenderWidgetHostViewMac::OnNSViewBoundsInWindowChanged(
+void RenderWidgetHostViewMac::OnBoundsInWindowChanged(
const gfx::Rect& view_bounds_in_window_dip,
bool attached_to_window) {
bool view_size_changed =
@@ -1365,17 +1415,11 @@ void RenderWidgetHostViewMac::OnNSViewBoundsInWindowChanged(
view_bounds_in_window_dip_.set_size(view_bounds_in_window_dip.size());
}
- if (view_size_changed) {
+ if (view_size_changed)
UpdateNSViewAndDisplayProperties();
- // Wait for the frame that WasResize might have requested. If the view is
- // being made visible at a new size, then this call will have no effect
- // because the view widget is still hidden, and the pause call in WasShown
- // will have this effect for us.
- PauseForPendingResizeOrRepaintsAndDraw();
- }
}
-void RenderWidgetHostViewMac::OnNSViewWindowFrameInScreenChanged(
+void RenderWidgetHostViewMac::OnWindowFrameInScreenChanged(
const gfx::Rect& window_frame_in_screen_dip) {
if (window_frame_in_screen_dip_ == window_frame_in_screen_dip)
return;
@@ -1387,13 +1431,13 @@ void RenderWidgetHostViewMac::OnNSViewWindowFrameInScreenChanged(
host()->SendScreenRects();
}
-void RenderWidgetHostViewMac::OnNSViewDisplayChanged(
+void RenderWidgetHostViewMac::OnDisplayChanged(
const display::Display& display) {
display_ = display;
UpdateNSViewAndDisplayProperties();
}
-void RenderWidgetHostViewMac::OnNSViewBeginKeyboardEvent() {
+void RenderWidgetHostViewMac::BeginKeyboardEvent() {
DCHECK(!in_keyboard_event_);
in_keyboard_event_ = true;
RenderWidgetHostImpl* widget_host = host();
@@ -1407,13 +1451,13 @@ void RenderWidgetHostViewMac::OnNSViewBeginKeyboardEvent() {
}
}
-void RenderWidgetHostViewMac::OnNSViewEndKeyboardEvent() {
+void RenderWidgetHostViewMac::EndKeyboardEvent() {
in_keyboard_event_ = false;
keyboard_event_widget_process_id_ = 0;
keyboard_event_widget_routing_id_ = 0;
}
-void RenderWidgetHostViewMac::OnNSViewForwardKeyboardEvent(
+void RenderWidgetHostViewMac::ForwardKeyboardEvent(
const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency_info) {
if (auto* widget_host = GetWidgetForKeyboardEvent()) {
@@ -1421,7 +1465,7 @@ void RenderWidgetHostViewMac::OnNSViewForwardKeyboardEvent(
}
}
-void RenderWidgetHostViewMac::OnNSViewForwardKeyboardEventWithCommands(
+void RenderWidgetHostViewMac::ForwardKeyboardEventWithCommands(
const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency_info,
const std::vector<EditCommand>& commands) {
@@ -1431,11 +1475,11 @@ void RenderWidgetHostViewMac::OnNSViewForwardKeyboardEventWithCommands(
}
}
-void RenderWidgetHostViewMac::OnNSViewRouteOrProcessMouseEvent(
+void RenderWidgetHostViewMac::RouteOrProcessMouseEvent(
const blink::WebMouseEvent& const_web_event) {
blink::WebMouseEvent web_event = const_web_event;
ui::LatencyInfo latency_info(ui::SourceEventType::OTHER);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT);
if (ShouldRouteEvent(web_event)) {
host()->delegate()->GetInputEventRouter()->RouteMouseEvent(this, &web_event,
latency_info);
@@ -1444,20 +1488,18 @@ void RenderWidgetHostViewMac::OnNSViewRouteOrProcessMouseEvent(
}
}
-void RenderWidgetHostViewMac::OnNSViewRouteOrProcessWheelEvent(
+void RenderWidgetHostViewMac::RouteOrProcessWheelEvent(
const blink::WebMouseWheelEvent& const_web_event) {
blink::WebMouseWheelEvent web_event = const_web_event;
ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
- if (wheel_scroll_latching_enabled()) {
- mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
- web_event, ShouldRouteEvent(web_event));
- if (web_event.phase == blink::WebMouseWheelEvent::kPhaseEnded) {
- // A wheel end event is scheduled and will get dispatched if momentum
- // phase doesn't start in 100ms. Don't sent the wheel end event
- // immediately.
- return;
- }
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT);
+ mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
+ web_event, ShouldRouteEvent(web_event));
+ if (web_event.phase == blink::WebMouseWheelEvent::kPhaseEnded) {
+ // A wheel end event is scheduled and will get dispatched if momentum
+ // phase doesn't start in 100ms. Don't sent the wheel end event
+ // immediately.
+ return;
}
if (ShouldRouteEvent(web_event)) {
host()->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
@@ -1467,7 +1509,7 @@ void RenderWidgetHostViewMac::OnNSViewRouteOrProcessWheelEvent(
}
}
-void RenderWidgetHostViewMac::OnNSViewForwardMouseEvent(
+void RenderWidgetHostViewMac::ForwardMouseEvent(
const blink::WebMouseEvent& web_event) {
if (host())
host()->ForwardMouseEvent(web_event);
@@ -1476,23 +1518,16 @@ void RenderWidgetHostViewMac::OnNSViewForwardMouseEvent(
ns_view_bridge_->SetTooltipText(base::string16());
}
-void RenderWidgetHostViewMac::OnNSViewForwardWheelEvent(
+void RenderWidgetHostViewMac::ForwardWheelEvent(
const blink::WebMouseWheelEvent& const_web_event) {
blink::WebMouseWheelEvent web_event = const_web_event;
- if (wheel_scroll_latching_enabled()) {
- mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(web_event,
- false);
- } else {
- ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
- host()->ForwardWheelEventWithLatencyInfo(web_event, latency_info);
- }
+ mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(web_event,
+ false);
}
-void RenderWidgetHostViewMac::OnNSViewGestureBegin(
- blink::WebGestureEvent begin_event,
- bool is_synthetically_injected) {
- gesture_begin_event_.reset(new WebGestureEvent(begin_event));
+void RenderWidgetHostViewMac::GestureBegin(blink::WebGestureEvent begin_event,
+ bool is_synthetically_injected) {
+ gesture_begin_event_ = std::make_unique<WebGestureEvent>(begin_event);
// If the page is at the minimum zoom level, require a threshold be reached
// before the pinch has an effect. Synthetic pinches are not subject to this
@@ -1503,7 +1538,7 @@ void RenderWidgetHostViewMac::OnNSViewGestureBegin(
}
}
-void RenderWidgetHostViewMac::OnNSViewGestureUpdate(
+void RenderWidgetHostViewMac::GestureUpdate(
blink::WebGestureEvent update_event) {
// If, due to nesting of multiple gestures (e.g, from multiple touch
// devices), the beginning of the gesture has been lost, skip the remainder
@@ -1519,15 +1554,14 @@ void RenderWidgetHostViewMac::OnNSViewGestureUpdate(
// Send a GesturePinchBegin event if none has been sent yet.
if (!gesture_begin_pinch_sent_) {
- if (wheel_scroll_latching_enabled()) {
- // Before starting a pinch sequence, send the pending wheel end event to
- // finish scrolling.
- mouse_wheel_phase_handler_.DispatchPendingWheelEndEvent();
- }
+ // Before starting a pinch sequence, send the pending wheel end event to
+ // finish scrolling.
+ mouse_wheel_phase_handler_.DispatchPendingWheelEndEvent();
WebGestureEvent begin_event(*gesture_begin_event_);
begin_event.SetType(WebInputEvent::kGesturePinchBegin);
begin_event.SetSourceDevice(
blink::WebGestureDevice::kWebGestureDeviceTouchpad);
+ begin_event.SetNeedsWheelEvent(true);
SendGesturePinchEvent(&begin_event);
gesture_begin_pinch_sent_ = YES;
}
@@ -1538,8 +1572,7 @@ void RenderWidgetHostViewMac::OnNSViewGestureUpdate(
SendGesturePinchEvent(&update_event);
}
-void RenderWidgetHostViewMac::OnNSViewGestureEnd(
- blink::WebGestureEvent end_event) {
+void RenderWidgetHostViewMac::GestureEnd(blink::WebGestureEvent end_event) {
gesture_begin_event_.reset();
if (gesture_begin_pinch_sent_) {
SendGesturePinchEvent(&end_event);
@@ -1547,12 +1580,12 @@ void RenderWidgetHostViewMac::OnNSViewGestureEnd(
}
}
-void RenderWidgetHostViewMac::OnNSViewSmartMagnify(
+void RenderWidgetHostViewMac::SmartMagnify(
const blink::WebGestureEvent& smart_magnify_event) {
host()->ForwardGestureEvent(smart_magnify_event);
}
-void RenderWidgetHostViewMac::OnNSViewImeSetComposition(
+void RenderWidgetHostViewMac::ImeSetComposition(
const base::string16& text,
const std::vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& replacement_range,
@@ -1564,7 +1597,7 @@ void RenderWidgetHostViewMac::OnNSViewImeSetComposition(
}
}
-void RenderWidgetHostViewMac::OnNSViewImeCommitText(
+void RenderWidgetHostViewMac::ImeCommitText(
const base::string16& text,
const gfx::Range& replacement_range) {
if (auto* widget_host = GetWidgetForIme()) {
@@ -1573,19 +1606,19 @@ void RenderWidgetHostViewMac::OnNSViewImeCommitText(
}
}
-void RenderWidgetHostViewMac::OnNSViewImeFinishComposingText() {
+void RenderWidgetHostViewMac::ImeFinishComposingText() {
if (auto* widget_host = GetWidgetForIme()) {
widget_host->ImeFinishComposingText(false);
}
}
-void RenderWidgetHostViewMac::OnNSViewImeCancelComposition() {
+void RenderWidgetHostViewMac::ImeCancelCompositionFromCocoa() {
if (auto* widget_host = GetWidgetForIme()) {
widget_host->ImeCancelComposition();
}
}
-void RenderWidgetHostViewMac::OnNSViewLookUpDictionaryOverlayFromRange(
+void RenderWidgetHostViewMac::LookUpDictionaryOverlayFromRange(
const gfx::Range& range) {
content::RenderWidgetHostViewBase* focused_view =
GetFocusedViewForTextSelection();
@@ -1606,7 +1639,7 @@ void RenderWidgetHostViewMac::OnNSViewLookUpDictionaryOverlayFromRange(
target_widget_routing_id));
}
-void RenderWidgetHostViewMac::OnNSViewLookUpDictionaryOverlayAtPoint(
+void RenderWidgetHostViewMac::LookUpDictionaryOverlayAtPoint(
const gfx::PointF& root_point) {
if (!host() || !host()->delegate() ||
!host()->delegate()->GetInputEventRouter())
@@ -1628,34 +1661,47 @@ void RenderWidgetHostViewMac::OnNSViewLookUpDictionaryOverlayAtPoint(
target_widget_routing_id));
}
-void RenderWidgetHostViewMac::OnNSViewSyncGetCharacterIndexAtPoint(
+bool RenderWidgetHostViewMac::SyncGetCharacterIndexAtPoint(
const gfx::PointF& root_point,
uint32_t* index) {
*index = UINT32_MAX;
if (!host() || !host()->delegate() ||
!host()->delegate()->GetInputEventRouter())
- return;
+ return true;
gfx::PointF transformed_point;
RenderWidgetHostImpl* widget_host =
host()->delegate()->GetInputEventRouter()->GetRenderWidgetHostAtPoint(
this, root_point, &transformed_point);
if (!widget_host)
- return;
+ return true;
*index = TextInputClientMac::GetInstance()->GetCharacterIndexAtPoint(
widget_host, gfx::ToFlooredPoint(transformed_point));
+ return true;
+}
+
+void RenderWidgetHostViewMac::SyncGetCharacterIndexAtPoint(
+ const gfx::PointF& root_point,
+ SyncGetCharacterIndexAtPointCallback callback) {
+ uint32_t index;
+ SyncGetCharacterIndexAtPoint(root_point, &index);
+ std::move(callback).Run(index);
}
-void RenderWidgetHostViewMac::OnNSViewSyncGetFirstRectForRange(
+bool RenderWidgetHostViewMac::SyncGetFirstRectForRange(
const gfx::Range& requested_range,
+ const gfx::Rect& in_rect,
+ const gfx::Range& in_actual_range,
gfx::Rect* rect,
gfx::Range* actual_range,
bool* success) {
+ *rect = in_rect;
+ *actual_range = in_actual_range;
if (!GetFocusedWidget()) {
*success = false;
- return;
+ return true;
}
*success = true;
if (!GetCachedFirstRectForCharacterRange(requested_range, rect,
@@ -1665,68 +1711,88 @@ void RenderWidgetHostViewMac::OnNSViewSyncGetFirstRectForRange(
// TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery.
*actual_range = requested_range;
}
+ return true;
}
-void RenderWidgetHostViewMac::OnNSViewExecuteEditCommand(
- const std::string& command) {
+void RenderWidgetHostViewMac::SyncGetFirstRectForRange(
+ const gfx::Range& requested_range,
+ const gfx::Rect& rect,
+ const gfx::Range& actual_range,
+ SyncGetFirstRectForRangeCallback callback) {
+ gfx::Rect out_rect;
+ gfx::Range out_actual_range;
+ bool success;
+ SyncGetFirstRectForRange(requested_range, rect, actual_range, &out_rect,
+ &out_actual_range, &success);
+ std::move(callback).Run(out_rect, out_actual_range, success);
+}
+
+void RenderWidgetHostViewMac::ExecuteEditCommand(const std::string& command) {
if (host()->delegate()) {
host()->delegate()->ExecuteEditCommand(command, base::nullopt);
}
}
-void RenderWidgetHostViewMac::OnNSViewUndo() {
+void RenderWidgetHostViewMac::Undo() {
WebContents* web_contents = GetWebContents();
if (web_contents)
web_contents->Undo();
}
-void RenderWidgetHostViewMac::OnNSViewRedo() {
+void RenderWidgetHostViewMac::Redo() {
WebContents* web_contents = GetWebContents();
if (web_contents)
web_contents->Redo();
}
-void RenderWidgetHostViewMac::OnNSViewCut() {
+void RenderWidgetHostViewMac::Cut() {
if (auto* delegate = GetFocusedRenderWidgetHostDelegate()) {
delegate->Cut();
}
}
-void RenderWidgetHostViewMac::OnNSViewCopy() {
+void RenderWidgetHostViewMac::Copy() {
if (auto* delegate = GetFocusedRenderWidgetHostDelegate()) {
delegate->Copy();
}
}
-void RenderWidgetHostViewMac::OnNSViewCopyToFindPboard() {
+void RenderWidgetHostViewMac::CopyToFindPboard() {
WebContents* web_contents = GetWebContents();
if (web_contents)
web_contents->CopyToFindPboard();
}
-void RenderWidgetHostViewMac::OnNSViewPaste() {
+void RenderWidgetHostViewMac::Paste() {
if (auto* delegate = GetFocusedRenderWidgetHostDelegate()) {
delegate->Paste();
}
}
-void RenderWidgetHostViewMac::OnNSViewPasteAndMatchStyle() {
+void RenderWidgetHostViewMac::PasteAndMatchStyle() {
WebContents* web_contents = GetWebContents();
if (web_contents)
web_contents->PasteAndMatchStyle();
}
-void RenderWidgetHostViewMac::OnNSViewSelectAll() {
+void RenderWidgetHostViewMac::SelectAll() {
if (auto* delegate = GetFocusedRenderWidgetHostDelegate()) {
delegate->SelectAll();
}
}
-void RenderWidgetHostViewMac::OnNSViewSyncIsSpeaking(bool* is_speaking) {
+bool RenderWidgetHostViewMac::SyncIsSpeaking(bool* is_speaking) {
*is_speaking = ui::TextServicesContextMenu::IsSpeaking();
+ return true;
}
-void RenderWidgetHostViewMac::OnNSViewSpeakSelection() {
+void RenderWidgetHostViewMac::SyncIsSpeaking(SyncIsSpeakingCallback callback) {
+ bool is_speaking;
+ SyncIsSpeaking(&is_speaking);
+ std::move(callback).Run(is_speaking);
+}
+
+void RenderWidgetHostViewMac::StartSpeaking() {
RenderWidgetHostView* target = this;
WebContents* web_contents = GetWebContents();
if (web_contents) {
@@ -1743,10 +1809,152 @@ void RenderWidgetHostViewMac::OnNSViewSpeakSelection() {
target->SpeakSelection();
}
-void RenderWidgetHostViewMac::OnNSViewStopSpeaking() {
+void RenderWidgetHostViewMac::StopSpeaking() {
ui::TextServicesContextMenu::StopSpeaking();
}
+///////////////////////////////////////////////////////////////////////////////
+// mojom::RenderWidgetHostNSViewClient functions that translate events and
+// forward them to the RenderWidgetHostNSViewLocalClient implementation:
+
+void RenderWidgetHostViewMac::ForwardKeyboardEvent(
+ std::unique_ptr<InputEvent> input_event,
+ bool skip_in_browser) {
+ if (!input_event || !input_event->web_event ||
+ !blink::WebInputEvent::IsKeyboardEventType(
+ input_event->web_event->GetType())) {
+ DLOG(ERROR) << "Absent or non-KeyboardEventType event.";
+ return;
+ }
+ const blink::WebKeyboardEvent& keyboard_event =
+ static_cast<const blink::WebKeyboardEvent&>(*input_event->web_event);
+ NativeWebKeyboardEvent native_event(keyboard_event, nil);
+ native_event.skip_in_browser = skip_in_browser;
+ ForwardKeyboardEvent(native_event, input_event->latency_info);
+}
+
+void RenderWidgetHostViewMac::ForwardKeyboardEventWithCommands(
+ std::unique_ptr<InputEvent> input_event,
+ bool skip_in_browser,
+ const std::vector<EditCommand>& commands) {
+ if (!input_event || !input_event->web_event ||
+ !blink::WebInputEvent::IsKeyboardEventType(
+ input_event->web_event->GetType())) {
+ DLOG(ERROR) << "Absent or non-KeyboardEventType event.";
+ return;
+ }
+ const blink::WebKeyboardEvent& keyboard_event =
+ static_cast<const blink::WebKeyboardEvent&>(*input_event->web_event);
+ NativeWebKeyboardEvent native_event(keyboard_event, nil);
+ native_event.skip_in_browser = skip_in_browser;
+ ForwardKeyboardEventWithCommands(native_event, input_event->latency_info,
+ commands);
+}
+void RenderWidgetHostViewMac::RouteOrProcessMouseEvent(
+ std::unique_ptr<InputEvent> input_event) {
+ if (!input_event || !input_event->web_event ||
+ !blink::WebInputEvent::IsMouseEventType(
+ input_event->web_event->GetType())) {
+ DLOG(ERROR) << "Absent or non-MouseEventType event.";
+ return;
+ }
+ const blink::WebMouseEvent& mouse_event =
+ static_cast<const blink::WebMouseEvent&>(*input_event->web_event);
+ RouteOrProcessMouseEvent(mouse_event);
+}
+
+void RenderWidgetHostViewMac::RouteOrProcessWheelEvent(
+ std::unique_ptr<InputEvent> input_event) {
+ if (!input_event || !input_event->web_event ||
+ input_event->web_event->GetType() != blink::WebInputEvent::kMouseWheel) {
+ DLOG(ERROR) << "Absent or non-MouseWheel event.";
+ return;
+ }
+ const blink::WebMouseWheelEvent& wheel_event =
+ static_cast<const blink::WebMouseWheelEvent&>(*input_event->web_event);
+ RouteOrProcessWheelEvent(wheel_event);
+}
+
+void RenderWidgetHostViewMac::ForwardMouseEvent(
+ std::unique_ptr<InputEvent> input_event) {
+ if (!input_event || !input_event->web_event ||
+ !blink::WebInputEvent::IsMouseEventType(
+ input_event->web_event->GetType())) {
+ DLOG(ERROR) << "Absent or non-MouseEventType event.";
+ return;
+ }
+ const blink::WebMouseEvent& mouse_event =
+ static_cast<const blink::WebMouseEvent&>(*input_event->web_event);
+ ForwardMouseEvent(mouse_event);
+}
+
+void RenderWidgetHostViewMac::ForwardWheelEvent(
+ std::unique_ptr<InputEvent> input_event) {
+ if (!input_event || !input_event->web_event ||
+ input_event->web_event->GetType() != blink::WebInputEvent::kMouseWheel) {
+ DLOG(ERROR) << "Absent or non-MouseWheel event.";
+ return;
+ }
+ const blink::WebMouseWheelEvent& wheel_event =
+ static_cast<const blink::WebMouseWheelEvent&>(*input_event->web_event);
+ ForwardWheelEvent(wheel_event);
+}
+
+void RenderWidgetHostViewMac::GestureBegin(
+ std::unique_ptr<InputEvent> input_event,
+ bool is_synthetically_injected) {
+ if (!input_event || !input_event->web_event ||
+ !blink::WebInputEvent::IsGestureEventType(
+ input_event->web_event->GetType())) {
+ DLOG(ERROR) << "Absent or non-GestureEventType event.";
+ return;
+ }
+ blink::WebGestureEvent gesture_event =
+ *static_cast<const blink::WebGestureEvent*>(input_event->web_event.get());
+ // Strip the gesture type, because it is not known.
+ gesture_event.SetType(blink::WebInputEvent::kUndefined);
+ GestureBegin(gesture_event, is_synthetically_injected);
+}
+
+void RenderWidgetHostViewMac::GestureUpdate(
+ std::unique_ptr<InputEvent> input_event) {
+ if (!input_event || !input_event->web_event ||
+ !blink::WebInputEvent::IsGestureEventType(
+ input_event->web_event->GetType())) {
+ DLOG(ERROR) << "Absent or non-GestureEventType event.";
+ return;
+ }
+ const blink::WebGestureEvent& gesture_event =
+ static_cast<const blink::WebGestureEvent&>(*input_event->web_event);
+ GestureUpdate(gesture_event);
+}
+
+void RenderWidgetHostViewMac::GestureEnd(
+ std::unique_ptr<InputEvent> input_event) {
+ if (!input_event || !input_event->web_event ||
+ !blink::WebInputEvent::IsGestureEventType(
+ input_event->web_event->GetType())) {
+ DLOG(ERROR) << "Absent or non-GestureEventType event.";
+ return;
+ }
+ blink::WebGestureEvent gesture_event =
+ *static_cast<const blink::WebGestureEvent*>(input_event->web_event.get());
+ GestureEnd(gesture_event);
+}
+
+void RenderWidgetHostViewMac::SmartMagnify(
+ std::unique_ptr<InputEvent> input_event) {
+ if (!input_event || !input_event->web_event ||
+ !blink::WebInputEvent::IsGestureEventType(
+ input_event->web_event->GetType())) {
+ DLOG(ERROR) << "Absent or non-GestureEventType event.";
+ return;
+ }
+ const blink::WebGestureEvent& gesture_event =
+ static_cast<const blink::WebGestureEvent&>(*input_event->web_event);
+ SmartMagnify(gesture_event);
+}
+
void RenderWidgetHostViewMac::OnGotStringForDictionaryOverlay(
int32_t target_widget_process_id,
int32_t target_widget_routing_id,
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.mm
index f4e2439c495..3f089d75a05 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.mm
@@ -138,10 +138,10 @@ void EditCommandImp(id self, SEL _cmd, id sender) {
std::string command([command_name_ns UTF8String]);
// Forward the edit command string down the pipeline.
- RenderWidgetHostNSViewClient* client = [(
+ mojom::RenderWidgetHostNSViewClient* client = [(
id<RenderWidgetHostNSViewClientOwner>)self renderWidgetHostNSViewClient];
DCHECK(client);
- client->OnNSViewExecuteEditCommand(command);
+ client->ExecuteEditCommand(command);
}
} // namespace
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
index 701da35330e..26c6b9e09d3 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -53,7 +53,7 @@ using content::RenderWidgetHostViewMac;
return self;
}
-- (content::RenderWidgetHostNSViewClient*)renderWidgetHostNSViewClient {
+- (content::mojom::RenderWidgetHostNSViewClient*)renderWidgetHostNSViewClient {
return rwhvm_;
}
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 fbca43e1919..4fceb1ab71c 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
@@ -17,7 +17,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -165,10 +165,13 @@ NSEvent* MockTabletEventWithParams(CGEventType type,
NSEvent* MockMouseEventWithParams(CGEventType mouse_type,
CGPoint location,
CGMouseButton button,
- CGEventMouseSubtype subtype) {
+ CGEventMouseSubtype subtype,
+ bool is_entering_proximity = false) {
CGEventRef cg_event =
CGEventCreateMouseEvent(NULL, mouse_type, location, button);
CGEventSetIntegerValueField(cg_event, kCGMouseEventSubtype, subtype);
+ CGEventSetIntegerValueField(cg_event, kCGTabletProximityEventEnterProximity,
+ is_entering_proximity);
NSEvent* event = [NSEvent eventWithCGEvent:cg_event];
CFRelease(cg_event);
return event;
@@ -341,24 +344,13 @@ NSEvent* MockScrollWheelEventWithoutPhase(int32_t delta) {
return MockScrollWheelEventWithMomentumPhase(@selector(phaseNone), delta);
}
-enum WheelScrollingMode {
- kWheelScrollingModeNone,
- kWheelScrollLatching,
- kAsyncWheelEvents,
-};
-
} // namespace
class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
public:
- RenderWidgetHostViewMacTest(
- WheelScrollingMode wheel_scrolling_mode = kWheelScrollingModeNone)
- : rwhv_mac_(nullptr),
- wheel_scrolling_mode_(wheel_scrolling_mode),
- scroll_latching_(wheel_scrolling_mode_ != kWheelScrollingModeNone) {
+ RenderWidgetHostViewMacTest() : rwhv_mac_(nullptr) {
mock_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
ui::SetEventTickClockForTesting(&mock_clock_);
- SetFeatureList();
vsync_feature_list_.InitAndEnableFeature(
features::kVsyncAlignedInputEvents);
@@ -413,29 +405,6 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
return base::UTF16ToUTF8(rwhv_mac_->GetTextSelection()->selected_text());
}
- void SetFeatureList() {
- if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
- feature_list_.InitWithFeatures({features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents},
- {});
- } else if (wheel_scrolling_mode_ == kWheelScrollLatching) {
- feature_list_.InitWithFeatures(
- {features::kTouchpadAndWheelScrollLatching},
- {features::kAsyncWheelEvents});
- } else if (wheel_scrolling_mode_ == kWheelScrollingModeNone) {
- feature_list_.InitWithFeatures({},
- {features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents});
- }
- }
-
- void IgnoreEmptyUnhandledWheelEventWithWheelGestures();
- void ScrollWheelEndEventDelivery();
- void TimerBasedPhaseInfo();
- void WheelWithPhaseEndedIsNotForwardedImmediately();
- void WheelWithMomentumPhaseBeganStopsTheWheelEndDispatchTimer();
- void WheelWithPhaseBeganDispatchesThePendingWheelEnd();
-
MockRenderWidgetHostDelegate delegate_;
std::unique_ptr<TestBrowserContext> browser_context_;
@@ -444,15 +413,11 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
RenderWidgetHostViewMac* rwhv_mac_ = nullptr;
base::scoped_nsobject<RenderWidgetHostViewCocoa> rwhv_cocoa_;
- WheelScrollingMode wheel_scrolling_mode_;
- bool scroll_latching_;
-
private:
// This class isn't derived from PlatformTest.
base::mac::ScopedNSAutoreleasePool pool_;
base::test::ScopedFeatureList vsync_feature_list_;
- base::test::ScopedFeatureList feature_list_;
base::SimpleTestTickClock mock_clock_;
@@ -845,9 +810,8 @@ TEST_F(RenderWidgetHostViewMacTest, LastWheelEventLatencyInfoExists) {
// properly in scrollWheel function.
NSEvent* wheelEvent1 = MockScrollWheelEventWithPhase(@selector(phaseBegan),3);
[rwhv_mac_->cocoa_view() scrollWheel:wheelEvent1];
- ui::LatencyInfo::LatencyComponent ui_component1;
ASSERT_TRUE(host_->lastWheelEventLatencyInfo.FindLatency(
- ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, &ui_component1));
+ ui::INPUT_EVENT_LATENCY_UI_COMPONENT, nullptr));
// Send a wheel event with phaseEnded.
// Verifies that ui::INPUT_EVENT_LATENCY_UI_COMPONENT is added
@@ -855,9 +819,8 @@ TEST_F(RenderWidgetHostViewMacTest, LastWheelEventLatencyInfoExists) {
// in scrollWheel.
NSEvent* wheelEvent2 = MockScrollWheelEventWithPhase(@selector(phaseEnded),0);
[rwhv_mac_->cocoa_view() scrollWheel:wheelEvent2];
- ui::LatencyInfo::LatencyComponent ui_component2;
ASSERT_TRUE(host_->lastWheelEventLatencyInfo.FindLatency(
- ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, &ui_component2));
+ ui::INPUT_EVENT_LATENCY_UI_COMPONENT, nullptr));
}
TEST_F(RenderWidgetHostViewMacTest, SourceEventTypeExistsInLatencyInfo) {
@@ -871,7 +834,7 @@ TEST_F(RenderWidgetHostViewMacTest, SourceEventTypeExistsInLatencyInfo) {
ui::SourceEventType::WHEEL);
}
-void RenderWidgetHostViewMacTest::ScrollWheelEndEventDelivery() {
+TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
// Send an initial wheel event with NSEventPhaseBegan to the view.
NSEvent* event1 = MockScrollWheelEventWithPhase(@selector(phaseBegan), 0);
[rwhv_mac_->cocoa_view() scrollWheel:event1];
@@ -891,17 +854,10 @@ void RenderWidgetHostViewMacTest::ScrollWheelEndEventDelivery() {
[NSApp postEvent:event2 atStart:NO];
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
- if (scroll_latching_) {
- // The wheel event with phaseEnded won't be sent to the render view
- // immediately, instead the mouse_wheel_phase_handler will wait for 100ms
- // to see if a wheel event with momentumPhase began arrives or not.
- ASSERT_EQ(0U, events.size());
- } else {
- ASSERT_EQ(1U, events.size());
- }
-}
-TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
- ScrollWheelEndEventDelivery();
+ // The wheel event with phaseEnded won't be sent to the render view
+ // immediately, instead the mouse_wheel_phase_handler will wait for 100ms
+ // to see if a wheel event with momentumPhase began arrives or not.
+ ASSERT_EQ(0U, events.size());
}
TEST_F(RenderWidgetHostViewMacTest, PointerEventWithEraserType) {
@@ -944,6 +900,36 @@ TEST_F(RenderWidgetHostViewMacTest, PointerEventWithPenType) {
GetPointerType(events));
}
+TEST_F(RenderWidgetHostViewMacTest, PointerEventWithPenTypeNoTabletEvent) {
+ // Send a NSEvent of a mouse type with a subtype of
+ // NSTabletProximityEventSubtype, which indicates the input device is a pen.
+ NSEvent* event =
+ MockMouseEventWithParams(kCGEventMouseMoved, {6, 9}, kCGMouseButtonLeft,
+ kCGEventMouseSubtypeTabletProximity, true);
+ [rwhv_mac_->cocoa_view() mouseEvent:event];
+ base::RunLoop().RunUntilIdle();
+ MockWidgetInputHandler::MessageVector events =
+ host_->GetAndResetDispatchedMessages();
+ ASSERT_EQ("MouseLeave", GetMessageNames(events));
+ EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
+ GetPointerType(events));
+ events.clear();
+
+ event = cocoa_test_event_utils::EnterEvent();
+ [rwhv_mac_->cocoa_view() mouseEntered:event];
+ base::RunLoop().RunUntilIdle();
+ events = host_->GetAndResetDispatchedMessages();
+ ASSERT_EQ("MouseMove MouseMove", GetMessageNames(events));
+ EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
+ static_cast<const blink::WebMouseEvent*>(
+ events[0]->ToEvent()->Event()->web_event.get())
+ ->pointer_type);
+ EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
+ static_cast<const blink::WebMouseEvent*>(
+ events[1]->ToEvent()->Event()->web_event.get())
+ ->pointer_type);
+}
+
TEST_F(RenderWidgetHostViewMacTest, PointerEventWithMouseType) {
// Send a NSEvent of a mouse type.
NSEvent* event =
@@ -973,8 +959,8 @@ TEST_F(RenderWidgetHostViewMacTest, SendMouseMoveOnShowingContextMenu) {
ASSERT_EQ("MouseMove", GetMessageNames(events));
}
-void RenderWidgetHostViewMacTest::
- IgnoreEmptyUnhandledWheelEventWithWheelGestures() {
+TEST_F(RenderWidgetHostViewMacTest,
+ IgnoreEmptyUnhandledWheelEventWithWheelGestures) {
// Add a delegate to the view.
base::scoped_nsobject<MockRenderWidgetHostViewMacDelegate> view_delegate(
[[MockRenderWidgetHostViewMacDelegate alloc] init]);
@@ -996,16 +982,10 @@ void RenderWidgetHostViewMacTest::
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
- if (scroll_latching_) {
- // GestureEventQueue allows multiple in-flight events.
- ASSERT_EQ("GestureScrollBegin GestureScrollUpdate",
- GetMessageNames(events));
- events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
- } else {
- // GestureEventQueue allows multiple in-flight events.
- ASSERT_EQ("GestureScrollBegin GestureScrollUpdate GestureScrollEnd",
- GetMessageNames(events));
- }
+ // GestureEventQueue allows multiple in-flight events.
+ ASSERT_EQ("GestureScrollBegin GestureScrollUpdate", GetMessageNames(events));
+ events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
+
events.clear();
// Check that the view delegate got an unhandled wheel event.
@@ -1027,10 +1007,6 @@ void RenderWidgetHostViewMacTest::
// Delete the view while |view_delegate| is still in scope.
rwhv_cocoa_.reset();
}
-TEST_F(RenderWidgetHostViewMacTest,
- IgnoreEmptyUnhandledWheelEventWithWheelGestures) {
- IgnoreEmptyUnhandledWheelEventWithWheelGestures();
-}
// Tests that when view initiated shutdown happens (i.e. RWHView is deleted
// before RWH), we clean up properly and don't leak the RWHVGuest.
@@ -1122,46 +1098,10 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
EXPECT_TRUE(std::get<0>(sent_background));
}
-class RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest
- : public RenderWidgetHostViewMacTest {
- public:
- RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest()
- : RenderWidgetHostViewMacTest(kWheelScrollLatching) {}
-};
-
-class RenderWidgetHostViewMacWithAsyncWheelEventsEnabledTest
- : public RenderWidgetHostViewMacTest {
- public:
- RenderWidgetHostViewMacWithAsyncWheelEventsEnabledTest()
- : RenderWidgetHostViewMacTest(kAsyncWheelEvents) {}
-};
-
-TEST_F(RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest,
- IgnoreEmptyUnhandledWheelEventWithWheelGestures) {
- IgnoreEmptyUnhandledWheelEventWithWheelGestures();
-}
-TEST_F(RenderWidgetHostViewMacWithAsyncWheelEventsEnabledTest,
- IgnoreEmptyUnhandledWheelEventWithWheelGestures) {
- IgnoreEmptyUnhandledWheelEventWithWheelGestures();
-}
-
-TEST_F(RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest,
- ScrollWheelEndEventDelivery) {
- ScrollWheelEndEventDelivery();
-}
-TEST_F(RenderWidgetHostViewMacWithAsyncWheelEventsEnabledTest,
- ScrollWheelEndEventDelivery) {
- ScrollWheelEndEventDelivery();
-}
-
// Scrolling with a mouse wheel device on Mac won't give phase information.
// MouseWheelPhaseHandler adds timer based phase information to wheel events
// generated from this type of devices.
-void RenderWidgetHostViewMacTest::TimerBasedPhaseInfo() {
- // The test is valid only when wheel scroll latching is enabled.
- if (!scroll_latching_)
- return;
-
+TEST_F(RenderWidgetHostViewMacTest, TimerBasedPhaseInfo) {
rwhv_mac_->set_mouse_wheel_wheel_phase_handler_timeout(
base::TimeDelta::FromMilliseconds(100));
@@ -1197,24 +1137,11 @@ void RenderWidgetHostViewMacTest::TimerBasedPhaseInfo() {
events[1]->ToEvent()->Event()->web_event.get())
->data.scroll_end.synthetic);
}
-TEST_F(RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest,
- TimerBasedPhaseInfo) {
- TimerBasedPhaseInfo();
-}
-TEST_F(RenderWidgetHostViewMacWithAsyncWheelEventsEnabledTest,
- TimerBasedPhaseInfo) {
- TimerBasedPhaseInfo();
-}
-
-// When wheel scroll latching is enabled, wheel end events are not sent
-// immediately, instead we start a timer to see if momentum phase of the scroll
-// starts or not.
-void RenderWidgetHostViewMacTest::
- WheelWithPhaseEndedIsNotForwardedImmediately() {
- // The test is valid only when wheel scroll latching is enabled.
- if (!scroll_latching_)
- return;
+// With wheel scroll latching wheel end events are not sent immediately, instead
+// we start a timer to see if momentum phase of the scroll starts or not.
+TEST_F(RenderWidgetHostViewMacTest,
+ WheelWithPhaseEndedIsNotForwardedImmediately) {
// Initialize the view associated with a MockRenderWidgetHostImpl, rather than
// the MockRenderProcessHost that is set up by the test harness which mocks
// out |OnMessageReceived()|.
@@ -1244,9 +1171,8 @@ void RenderWidgetHostViewMacTest::
// in-flight events.
ASSERT_EQ("GestureScrollBegin GestureScrollUpdate", GetMessageNames(events));
- // Send a wheel event with phaseEnded. When wheel scroll latching is enabled
- // the event will be dropped and the mouse_wheel_end_dispatch_timer_ will
- // start.
+ // Send a wheel event with phaseEnded. The event will be dropped and the
+ // mouse_wheel_end_dispatch_timer_ will start.
NSEvent* wheelEvent2 =
MockScrollWheelEventWithPhase(@selector(phaseEnded), 0);
[view->cocoa_view() scrollWheel:wheelEvent2];
@@ -1268,21 +1194,9 @@ void RenderWidgetHostViewMacTest::
kMaximumTimeBetweenPhaseEndedAndMomentumPhaseBegan);
run_loop.Run();
}
-TEST_F(RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest,
- WheelWithPhaseEndedIsNotForwardedImmediately) {
- WheelWithPhaseEndedIsNotForwardedImmediately();
-}
-TEST_F(RenderWidgetHostViewMacWithAsyncWheelEventsEnabledTest,
- WheelWithPhaseEndedIsNotForwardedImmediately) {
- WheelWithPhaseEndedIsNotForwardedImmediately();
-}
-
-void RenderWidgetHostViewMacTest::
- WheelWithMomentumPhaseBeganStopsTheWheelEndDispatchTimer() {
- // The test is valid only when wheel scroll latching is enabled.
- if (!scroll_latching_)
- return;
+TEST_F(RenderWidgetHostViewMacTest,
+ WheelWithMomentumPhaseBeganStopsTheWheelEndDispatchTimer) {
// Initialize the view associated with a MockRenderWidgetHostImpl, rather than
// the MockRenderProcessHost that is set up by the test harness which mocks
// out |OnMessageReceived()|.
@@ -1313,9 +1227,8 @@ void RenderWidgetHostViewMacTest::
// in-flight events.
ASSERT_EQ("GestureScrollBegin GestureScrollUpdate", GetMessageNames(events));
- // Send a wheel event with phaseEnded. When wheel scroll latching is enabled
- // the event will be dropped and the mouse_wheel_end_dispatch_timer_ will
- // start.
+ // Send a wheel event with phaseEnded. The event will be dropped and the
+ // mouse_wheel_end_dispatch_timer_ will start.
NSEvent* wheelEvent2 =
MockScrollWheelEventWithPhase(@selector(phaseEnded), 0);
[view->cocoa_view() scrollWheel:wheelEvent2];
@@ -1332,29 +1245,14 @@ void RenderWidgetHostViewMacTest::
[view->cocoa_view() scrollWheel:wheelEvent3];
base::RunLoop().RunUntilIdle();
events = host->GetAndResetDispatchedMessages();
- if (wheel_scrolling_mode_ == kAsyncWheelEvents)
- ASSERT_EQ("MouseWheel GestureScrollUpdate", GetMessageNames(events));
- else
- ASSERT_EQ("MouseWheel", GetMessageNames(events));
+ ASSERT_EQ("MouseWheel GestureScrollUpdate", GetMessageNames(events));
DCHECK(!view->HasPendingWheelEndEventForTesting());
host->ShutdownAndDestroyWidget(true);
}
-TEST_F(RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest,
- WheelWithMomentumPhaseBeganStopsTheWheelEndDispatchTimer) {
- WheelWithMomentumPhaseBeganStopsTheWheelEndDispatchTimer();
-}
-TEST_F(RenderWidgetHostViewMacWithAsyncWheelEventsEnabledTest,
- WheelWithMomentumPhaseBeganStopsTheWheelEndDispatchTimer) {
- WheelWithMomentumPhaseBeganStopsTheWheelEndDispatchTimer();
-}
-
-void RenderWidgetHostViewMacTest::
- WheelWithPhaseBeganDispatchesThePendingWheelEnd() {
- // The test is valid only when wheel scroll latching is enabled.
- if (!scroll_latching_)
- return;
+TEST_F(RenderWidgetHostViewMacTest,
+ WheelWithPhaseBeganDispatchesThePendingWheelEnd) {
// Initialize the view associated with a MockRenderWidgetHostImpl, rather than
// the MockRenderProcessHost that is set up by the test harness which mocks
// out |OnMessageReceived()|.
@@ -1385,9 +1283,8 @@ void RenderWidgetHostViewMacTest::
events = host->GetAndResetDispatchedMessages();
ASSERT_EQ("GestureScrollBegin GestureScrollUpdate", GetMessageNames(events));
- // Send a wheel event with phaseEnded. When wheel scroll latching is enabled
- // the event will be dropped and the mouse_wheel_end_dispatch_timer_ will
- // start.
+ // Send a wheel event with phaseEnded. The event will be dropped and the
+ // mouse_wheel_end_dispatch_timer_ will start.
NSEvent* wheelEvent2 =
MockScrollWheelEventWithPhase(@selector(phaseEnded), 0);
[view->cocoa_view() scrollWheel:wheelEvent2];
@@ -1410,30 +1307,11 @@ void RenderWidgetHostViewMacTest::
host->ShutdownAndDestroyWidget(true);
}
-TEST_F(RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest,
- WheelWithPhaseBeganDispatchesThePendingWheelEnd) {
- WheelWithPhaseBeganDispatchesThePendingWheelEnd();
-}
-TEST_F(RenderWidgetHostViewMacWithAsyncWheelEventsEnabledTest,
- WheelWithPhaseBeganDispatchesThePendingWheelEnd) {
- WheelWithPhaseBeganDispatchesThePendingWheelEnd();
-}
class RenderWidgetHostViewMacPinchTest : public RenderWidgetHostViewMacTest {
public:
RenderWidgetHostViewMacPinchTest() = default;
- bool ZoomDisabledForPinchUpdateMessage(
- const MockWidgetInputHandler::MessageVector& events) {
- MockWidgetInputHandler::DispatchedEventMessage* event =
- events[events.size() - 1]->ToEvent();
- EXPECT_TRUE(event);
-
- return static_cast<const blink::WebGestureEvent*>(
- event->Event()->web_event.get())
- ->data.pinch_update.zoom_disabled;
- }
-
bool ShouldSendGestureEvents() {
#if defined(MAC_OS_X_VERSION_10_11) && \
MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11
@@ -1480,23 +1358,37 @@ TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
[rwhv_cocoa_ magnifyWithEvent:pinchUpdateEvents[0]];
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
- EXPECT_EQ("GesturePinchBegin GesturePinchUpdate", GetMessageNames(events));
- EXPECT_TRUE(ZoomDisabledForPinchUpdateMessage(events));
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
+
+ // After acking the synthetic mouse wheel, no GesturePinch events are
+ // produced.
+ events[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ events = host_->GetAndResetDispatchedMessages();
+ EXPECT_EQ(0U, events.size());
// The second update event crosses the threshold of 0.4, and so zoom is no
// longer disabled.
[rwhv_cocoa_ magnifyWithEvent:pinchUpdateEvents[1]];
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
- EXPECT_EQ("GesturePinchUpdate", GetMessageNames(events));
- EXPECT_FALSE(ZoomDisabledForPinchUpdateMessage(events));
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
+
+ // Now acking the synthetic mouse wheel does produce GesturePinch events.
+ events[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ events = host_->GetAndResetDispatchedMessages();
+ EXPECT_EQ("GesturePinchBegin GesturePinchUpdate", GetMessageNames(events));
// The third update still has zoom enabled.
[rwhv_cocoa_ magnifyWithEvent:pinchUpdateEvents[2]];
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
+ events[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ events = host_->GetAndResetDispatchedMessages();
EXPECT_EQ("GesturePinchUpdate", GetMessageNames(events));
- EXPECT_FALSE(ZoomDisabledForPinchUpdateMessage(events));
SendEndPinchEvent();
base::RunLoop().RunUntilIdle();
@@ -1521,8 +1413,11 @@ TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
[rwhv_cocoa_ magnifyWithEvent:pinchUpdateEvent];
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
+ events[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ events = host_->GetAndResetDispatchedMessages();
EXPECT_EQ("GesturePinchBegin GesturePinchUpdate", GetMessageNames(events));
- EXPECT_FALSE(ZoomDisabledForPinchUpdateMessage(events));
SendEndPinchEvent();
base::RunLoop().RunUntilIdle();
@@ -1551,13 +1446,19 @@ TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
[rwhv_cocoa_ magnifyWithEvent:pinchUpdateEvent];
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
- EXPECT_EQ("GesturePinchBegin GesturePinchUpdate", GetMessageNames(events));
- EXPECT_TRUE(ZoomDisabledForPinchUpdateMessage(events));
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
+
+ events[0]->ToEvent()->CallCallback(
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ events = host_->GetAndResetDispatchedMessages();
+ EXPECT_EQ(0U, events.size());
+ // Since no GesturePinchBegin was sent by the time we reach the pinch end,
+ // the GesturePinchBegin and GesturePinchEnd are elided.
SendEndPinchEvent();
base::RunLoop().RunUntilIdle();
events = host_->GetAndResetDispatchedMessages();
- EXPECT_EQ("GesturePinchEnd", GetMessageNames(events));
+ EXPECT_EQ(0U, events.size());
}
}
diff --git a/chromium/content/browser/renderer_host/render_widget_targeter.cc b/chromium/content/browser/renderer_host/render_widget_targeter.cc
index f25502b308e..4a5acc5f53b 100644
--- a/chromium/content/browser/renderer_host/render_widget_targeter.cc
+++ b/chromium/content/browser/renderer_host/render_widget_targeter.cc
@@ -54,8 +54,8 @@ class TracingUmaTracker {
metric_name_(metric_name),
tracing_category_(tracing_category) {
TRACE_EVENT_ASYNC_BEGIN0(
- tracing_category_.c_str(), metric_name_.c_str(),
- TRACE_ID_WITH_SCOPE(metric_name_.c_str(), TRACE_ID_LOCAL(id_)));
+ tracing_category_, metric_name_,
+ TRACE_ID_WITH_SCOPE(metric_name_, TRACE_ID_LOCAL(id_)));
}
~TracingUmaTracker() = default;
TracingUmaTracker(TracingUmaTracker&& tracker) = default;
@@ -63,17 +63,19 @@ class TracingUmaTracker {
void Stop() {
TRACE_EVENT_ASYNC_END0(
- tracing_category_.c_str(), metric_name_.c_str(),
- TRACE_ID_WITH_SCOPE(metric_name_.c_str(), TRACE_ID_LOCAL(id_)));
- UmaHistogramTimes(metric_name_.c_str(),
- base::TimeTicks::Now() - start_time_);
+ tracing_category_, metric_name_,
+ TRACE_ID_WITH_SCOPE(metric_name_, TRACE_ID_LOCAL(id_)));
+ UmaHistogramTimes(metric_name_, base::TimeTicks::Now() - start_time_);
}
private:
const int id_;
const base::TimeTicks start_time_;
- std::string metric_name_;
- std::string tracing_category_;
+
+ // These variables must be string literals and live for the duration
+ // of the program since tracing stores pointers.
+ const char* metric_name_;
+ const char* tracing_category_;
static int next_id_;
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.cc b/chromium/content/browser/renderer_host/ui_events_helper.cc
index 8b3330f22c9..6ea4ed53dbe 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.cc
+++ b/chromium/content/browser/renderer_host/ui_events_helper.cc
@@ -65,7 +65,8 @@ bool MakeUITouchEventsFromWebTouchEvents(
int flags = ui::WebEventModifiersToEventFlags(touch.GetModifiers());
base::TimeTicks timestamp = touch.TimeStamp();
- for (unsigned i = 0; i < touch.touches_length; ++i) {
+ unsigned count = 0;
+ for (unsigned i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; ++i) {
const blink::WebTouchPoint& point = touch.touches[i];
if (WebTouchPointStateToEventType(point.state) != type)
continue;
@@ -84,6 +85,8 @@ bool MakeUITouchEventsFromWebTouchEvents(
uievent->set_root_location_f(location);
uievent->set_latency(touch_with_latency.latency);
list->push_back(std::move(uievent));
+ if (++count >= touch.touches_length)
+ break;
}
return true;
}
diff --git a/chromium/content/browser/renderer_host/web_database_host_impl.cc b/chromium/content/browser/renderer_host/web_database_host_impl.cc
index a27dfea1f3e..99612d10417 100644
--- a/chromium/content/browser/renderer_host/web_database_host_impl.cc
+++ b/chromium/content/browser/renderer_host/web_database_host_impl.cc
@@ -91,8 +91,8 @@ void WebDatabaseHostImpl::OpenFile(const base::string16& vfs_file_name,
// open handles to them in the database tracker to make sure they're
// around for as long as needed.
if (vfs_file_name.empty()) {
- file = VfsBackend::OpenTempFileInDirectory(db_tracker_->DatabaseDirectory(),
- desired_flags);
+ file = VfsBackend::OpenTempFileInDirectory(
+ db_tracker_->database_directory(), desired_flags);
} else if (DatabaseUtil::CrackVfsFileName(vfs_file_name, &origin_identifier,
&database_name, nullptr) &&
!db_tracker_->IsDatabaseScheduledForDeletion(origin_identifier,
diff --git a/chromium/content/browser/renderer_interface_binders.cc b/chromium/content/browser/renderer_interface_binders.cc
index e306536aa57..896f1b27ded 100644
--- a/chromium/content/browser/renderer_interface_binders.cc
+++ b/chromium/content/browser/renderer_interface_binders.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "content/browser/background_fetch/background_fetch_service_impl.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/cookie_store/cookie_store_context.h"
#include "content/browser/locks/lock_manager.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
@@ -28,7 +29,7 @@
#include "services/network/restricted_cookie_manager.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/connector.h"
-#include "services/shape_detection/public/mojom/barcodedetection.mojom.h"
+#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom.h"
#include "services/shape_detection/public/mojom/constants.mojom.h"
#include "services/shape_detection/public/mojom/facedetection_provider.mojom.h"
#include "services/shape_detection/public/mojom/textdetection.mojom.h"
@@ -94,22 +95,15 @@ void ForwardServiceRequest(const char* service_name,
connector->BindInterface(service_name, std::move(request));
}
-void GetRestrictedCookieManagerForWorker(
+void GetRestrictedCookieManager(
network::mojom::RestrictedCookieManagerRequest request,
RenderProcessHost* render_process_host,
const url::Origin& origin) {
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableExperimentalWebPlatformFeatures)) {
- return;
- }
-
StoragePartition* storage_partition =
render_process_host->GetStoragePartition();
network::mojom::NetworkContext* network_context =
storage_partition->GetNetworkContext();
- uint32_t render_process_id = render_process_host->GetID();
- network_context->GetRestrictedCookieManager(
- std::move(request), render_process_id, MSG_ROUTING_NONE);
+ network_context->GetRestrictedCookieManager(std::move(request), origin);
}
// Register renderer-exposed interfaces. Each registered interface binder is
@@ -120,7 +114,7 @@ void GetRestrictedCookieManagerForWorker(
// override binders registered here.
void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
parameterized_binder_registry_.AddInterface(base::Bind(
- &ForwardServiceRequest<shape_detection::mojom::BarcodeDetection>,
+ &ForwardServiceRequest<shape_detection::mojom::BarcodeDetectionProvider>,
shape_detection::mojom::kServiceName));
parameterized_binder_registry_.AddInterface(base::Bind(
&ForwardServiceRequest<shape_detection::mojom::FaceDetectionProvider>,
@@ -174,12 +168,12 @@ void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
RenderProcessHost* host, const url::Origin& origin) {
static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
->GetPlatformNotificationContext()
- ->CreateService(host->GetID(), origin, std::move(request));
+ ->CreateService(origin, std::move(request));
}));
parameterized_binder_registry_.AddInterface(
base::BindRepeating(&BackgroundFetchServiceImpl::Create));
parameterized_binder_registry_.AddInterface(
- base::BindRepeating(GetRestrictedCookieManagerForWorker));
+ base::BindRepeating(GetRestrictedCookieManager));
parameterized_binder_registry_.AddInterface(
base::BindRepeating(&QuotaDispatcherHost::CreateForWorker));
parameterized_binder_registry_.AddInterface(base::BindRepeating(
@@ -201,7 +195,7 @@ void RendererInterfaceBinders::CreateWebSocket(
RenderProcessHost* host,
const url::Origin& origin) {
WebSocketManager::CreateWebSocket(host->GetID(), MSG_ROUTING_NONE, origin,
- std::move(request));
+ nullptr, std::move(request));
}
} // namespace
diff --git a/chromium/content/browser/resources/gpu/OWNERS b/chromium/content/browser/resources/gpu/OWNERS
index 2aa356651f1..ea5131efe74 100644
--- a/chromium/content/browser/resources/gpu/OWNERS
+++ b/chromium/content/browser/resources/gpu/OWNERS
@@ -1,3 +1,4 @@
nduca@chromium.org
kbr@chromium.org
-zmo@chromium.org \ No newline at end of file
+zmo@chromium.org
+backer@chromium.org
diff --git a/chromium/content/browser/resources/gpu/info_view.js b/chromium/content/browser/resources/gpu/info_view.js
index 41a64405b78..122f2e874be 100644
--- a/chromium/content/browser/resources/gpu/info_view.js
+++ b/chromium/content/browser/resources/gpu/info_view.js
@@ -230,6 +230,7 @@ cr.define('gpu', function() {
'texture_sharing': 'Texture Sharing',
'video_decode': 'Video Decode',
'rasterization': 'Rasterization',
+ 'oop_rasterization': 'Out-of-process Rasterization',
'multiple_raster_threads': 'Multiple Raster Threads',
'native_gpu_memory_buffers': 'Native GpuMemoryBuffers',
'protected_video_decode': 'Hardware Protected Video Decode',
diff --git a/chromium/content/browser/resources/histograms/histograms_internals.html b/chromium/content/browser/resources/histograms/histograms_internals.html
index 5fd6ebfb75b..16a224365a4 100644
--- a/chromium/content/browser/resources/histograms/histograms_internals.html
+++ b/chromium/content/browser/resources/histograms/histograms_internals.html
@@ -9,7 +9,7 @@
<script src="chrome://resources/js/promise_resolver.js"></script>
<script src="chrome://resources/js/util.js"></script>
<script src="histograms_internals.js"></script>
- <title>📊 About Histograms</title>
+ <title>Histograms</title>
</head>
<p>Stats accumulated from browser startup to previous page load; reload to get stats as of this page load.
</p>
diff --git a/chromium/content/browser/resources/media/peer_connection_update_table.js b/chromium/content/browser/resources/media/peer_connection_update_table.js
index 09998a6bf7d..83416e5109b 100644
--- a/chromium/content/browser/resources/media/peer_connection_update_table.js
+++ b/chromium/content/browser/resources/media/peer_connection_update_table.js
@@ -122,14 +122,6 @@ var PeerConnectionUpdateTable = (function() {
update.type === 'addIceCandidateFailed') {
valueContainer.parentElement.classList.add('update-log-failure');
}
- // Highlight legacy streams API usage.
- if (update.type === 'addStream' || update.type === 'removeStream') {
- valueContainer.parentElement.classList.add(
- 'update-log-legacy-api-usage');
- valueContainer.parentElement.title = update.type + ' is no longer ' +
- 'part of the WebRTC API and may be removed in future versions. ' +
- 'Use the addTrack/removeTrack APIs instead.';
- }
var value = update.value;
// map internal names and values to names and events from the
diff --git a/chromium/content/browser/resources/process/process_internals.html b/chromium/content/browser/resources/process/process_internals.html
index 9e5acb2d80a..9b63631e817 100644
--- a/chromium/content/browser/resources/process/process_internals.html
+++ b/chromium/content/browser/resources/process/process_internals.html
@@ -12,5 +12,5 @@
<title>Process Model Internals</title>
</head>
<div id="site-isolation-mode">Site Isolation mode: <span id='isolation-mode'>unknown</span></div>
-<div id="isolated-origins-container">Isolated origins: <span id='isolated-origins'></span></div>
+<div id="isolated-origins-container">Number of isolated origins: <span id='isolated-origins'></span></div>
</html>
diff --git a/chromium/content/browser/resources/process/process_internals.js b/chromium/content/browser/resources/process/process_internals.js
index a745e29b6ec..155847443a7 100644
--- a/chromium/content/browser/resources/process/process_internals.js
+++ b/chromium/content/browser/resources/process/process_internals.js
@@ -24,9 +24,8 @@ document.addEventListener('DOMContentLoaded', function() {
uiHandler.getIsolationMode().then((response) => {
document.getElementById('isolation-mode').innerText = response.mode;
});
- uiHandler.getIsolatedOrigins().then((response) => {
- document.getElementById('isolated-origins').innerText =
- response.isolatedOrigins.join(', ');
+ uiHandler.getIsolatedOriginsSize().then((response) => {
+ document.getElementById('isolated-origins').innerText = response.size;
});
});
diff --git a/chromium/content/browser/resources/service_worker/serviceworker_internals.js b/chromium/content/browser/resources/service_worker/serviceworker_internals.js
index 810676ab9d1..a1a697b8584 100644
--- a/chromium/content/browser/resources/service_worker/serviceworker_internals.js
+++ b/chromium/content/browser/resources/service_worker/serviceworker_internals.js
@@ -198,8 +198,6 @@ cr.define('serviceworker', function() {
function onErrorReported(partition_id,
version_id,
- process_id,
- thread_id,
error_info) {
outputLogMessage(partition_id,
version_id,
@@ -208,8 +206,6 @@ cr.define('serviceworker', function() {
function onConsoleMessageReported(partition_id,
version_id,
- process_id,
- thread_id,
message) {
outputLogMessage(partition_id,
version_id,
diff --git a/chromium/content/browser/sandbox_ipc_linux.cc b/chromium/content/browser/sandbox_ipc_linux.cc
index 3206764895c..a893d1b8f09 100644
--- a/chromium/content/browser/sandbox_ipc_linux.cc
+++ b/chromium/content/browser/sandbox_ipc_linux.cc
@@ -21,69 +21,15 @@
#include "base/posix/unix_domain_socket.h"
#include "base/process/launch.h"
#include "base/strings/string_number_conversions.h"
-#include "content/browser/renderer_host/font_utils_linux.h"
-#include "content/common/font_config_ipc_linux.h"
#include "content/public/common/content_switches.h"
#include "sandbox/linux/services/libc_interceptor.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-#include "skia/ext/skia_utils_base.h"
-#include "third_party/skia/include/ports/SkFontConfigInterface.h"
-#include "ui/gfx/font.h"
-#include "ui/gfx/font_fallback_linux.h"
-#include "ui/gfx/font_render_params.h"
namespace content {
-namespace {
-
-SandboxIPCHandler::TestObserver* g_test_observer = nullptr;
-
-// Converts gfx::FontRenderParams::Hinting to WebFontRenderStyle::hintStyle.
-// Returns an int for serialization, but the underlying Blink type is a char.
-int ConvertHinting(gfx::FontRenderParams::Hinting hinting) {
- switch (hinting) {
- case gfx::FontRenderParams::HINTING_NONE:
- return 0;
- case gfx::FontRenderParams::HINTING_SLIGHT:
- return 1;
- case gfx::FontRenderParams::HINTING_MEDIUM:
- return 2;
- case gfx::FontRenderParams::HINTING_FULL:
- return 3;
- }
- NOTREACHED() << "Unexpected hinting value " << hinting;
- return 0;
-}
-
-// Converts gfx::FontRenderParams::SubpixelRendering to
-// WebFontRenderStyle::useSubpixelRendering. Returns an int for serialization,
-// but the underlying Blink type is a char.
-int ConvertSubpixelRendering(
- gfx::FontRenderParams::SubpixelRendering rendering) {
- switch (rendering) {
- case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE:
- return 0;
- case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB:
- return 1;
- case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR:
- return 1;
- case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB:
- return 1;
- case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR:
- return 1;
- }
- NOTREACHED() << "Unexpected subpixel rendering value " << rendering;
- return 0;
-}
-
-} // namespace
+const size_t kMaxSandboxIPCMessagePayloadSize = 64;
// static
-void SandboxIPCHandler::SetObserverForTests(
- SandboxIPCHandler::TestObserver* observer) {
- g_test_observer = observer;
-}
-
SandboxIPCHandler::SandboxIPCHandler(int lifeline_fd, int browser_socket)
: lifeline_fd_(lifeline_fd), browser_socket_(browser_socket) {}
@@ -136,17 +82,22 @@ void SandboxIPCHandler::HandleRequestFromChild(int fd) {
// A FontConfigIPC::METHOD_MATCH message could be kMaxFontFamilyLength
// bytes long (this is the largest message type).
+ // The size limit used to be FontConfigIPC::kMaxFontFamilyLength which was
+ // 2048, but we do not receive FontConfig IPC here anymore. The only payloads
+ // here are service_manager::SandboxLinux::METHOD_MAKE_SHARED_MEMORY_SEGMENT
+ // and HandleLocalTime from libc_interceptor for which
+ // kMaxSandboxIPCMessagePayloadSize set to 64 should be plenty.
// 128 bytes padding are necessary so recvmsg() does not return MSG_TRUNC
// error for a maximum length message.
- char buf[FontConfigIPC::kMaxFontFamilyLength + 128];
+ char buf[kMaxSandboxIPCMessagePayloadSize + 128];
const ssize_t len =
base::UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds);
if (len == -1) {
// TODO: should send an error reply, or the sender might block forever.
if (errno == EMSGSIZE) {
- NOTREACHED()
- << "Sandbox host message is larger than kMaxFontFamilyLength";
+ NOTREACHED() << "Sandbox host message is larger than "
+ "kMaxSandboxIPCMessagePayloadSize";
} else {
PLOG(ERROR) << "Recvmsg failed";
NOTREACHED();
@@ -168,164 +119,12 @@ void SandboxIPCHandler::HandleRequestFromChild(int fd) {
if (sandbox::HandleInterceptedCall(kind, fd, iter, fds))
return;
- if (kind == FontConfigIPC::METHOD_MATCH) {
- HandleFontMatchRequest(fd, iter, fds);
- } else if (kind == FontConfigIPC::METHOD_OPEN) {
- HandleFontOpenRequest(fd, iter, fds);
- } else if (kind ==
- service_manager::SandboxLinux::METHOD_GET_FALLBACK_FONT_FOR_CHAR) {
- HandleGetFallbackFontForChar(fd, iter, fds);
- } else if (kind ==
- service_manager::SandboxLinux::METHOD_GET_STYLE_FOR_STRIKE) {
- HandleGetStyleForStrike(fd, iter, fds);
- } else if (kind ==
- service_manager::SandboxLinux::METHOD_MAKE_SHARED_MEMORY_SEGMENT) {
+ if (kind ==
+ service_manager::SandboxLinux::METHOD_MAKE_SHARED_MEMORY_SEGMENT) {
HandleMakeSharedMemorySegment(fd, iter, fds);
- } else if (kind ==
- service_manager::SandboxLinux::METHOD_MATCH_WITH_FALLBACK) {
- HandleMatchWithFallback(fd, iter, fds);
- }
-}
-
-int SandboxIPCHandler::FindOrAddPath(const SkString& path) {
- int count = paths_.size();
- for (int i = 0; i < count; ++i) {
- if (path == paths_[i])
- return i;
- }
- paths_.emplace_back(path);
- return count;
-}
-
-void SandboxIPCHandler::HandleFontMatchRequest(
- int fd,
- base::PickleIterator iter,
- const std::vector<base::ScopedFD>& fds) {
- SkFontStyle requested_style;
- std::string family;
- if (!iter.ReadString(&family) ||
- !skia::ReadSkFontStyle(&iter, &requested_style))
- return;
-
- SkFontConfigInterface::FontIdentity result_identity;
- SkString result_family;
- SkFontStyle result_style;
- SkFontConfigInterface* fc =
- SkFontConfigInterface::GetSingletonDirectInterface();
- const bool r =
- fc->matchFamilyName(family.c_str(), requested_style, &result_identity,
- &result_family, &result_style);
-
- base::Pickle reply;
- if (!r) {
- reply.WriteBool(false);
- } else {
- // Stash away the returned path, so we can give it an ID (index)
- // which will later be given to us in a request to open the file.
- int index = FindOrAddPath(result_identity.fString);
- result_identity.fID = static_cast<uint32_t>(index);
-
- reply.WriteBool(true);
- skia::WriteSkString(&reply, result_family);
- skia::WriteSkFontIdentity(&reply, result_identity);
- skia::WriteSkFontStyle(&reply, result_style);
- }
- SendRendererReply(fds, reply, -1);
-}
-
-void SandboxIPCHandler::HandleFontOpenRequest(
- int fd,
- base::PickleIterator iter,
- const std::vector<base::ScopedFD>& fds) {
- uint32_t index;
- if (!iter.ReadUInt32(&index))
- return;
- if (index >= static_cast<uint32_t>(paths_.size()))
- return;
- if (g_test_observer) {
- g_test_observer->OnFontOpen(index);
- }
- const int result_fd = open(paths_[index].c_str(), O_RDONLY);
-
- base::Pickle reply;
- reply.WriteBool(result_fd != -1);
-
- // The receiver will have its own access to the file, so we will close it
- // after this send.
- SendRendererReply(fds, reply, result_fd);
-
- if (result_fd >= 0) {
- int err = IGNORE_EINTR(close(result_fd));
- DCHECK(!err);
- }
-}
-
-void SandboxIPCHandler::HandleGetFallbackFontForChar(
- int fd,
- base::PickleIterator iter,
- const std::vector<base::ScopedFD>& fds) {
- // The other side of this call is
- // content/common/child_process_sandbox_support_impl_linux.cc
-
- UChar32 c;
- if (!iter.ReadInt(&c))
return;
-
- std::string preferred_locale;
- if (!iter.ReadString(&preferred_locale))
- return;
-
- auto fallback_font = gfx::GetFallbackFontForChar(c, preferred_locale);
- int fontconfig_interface_id =
- FindOrAddPath(SkString(fallback_font.filename.data()));
-
- if (g_test_observer) {
- g_test_observer->OnGetFallbackFontForChar(c, fallback_font.name,
- fontconfig_interface_id);
}
- base::Pickle reply;
- 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);
-}
-
-void SandboxIPCHandler::HandleGetStyleForStrike(
- int fd,
- base::PickleIterator iter,
- const std::vector<base::ScopedFD>& fds) {
- std::string family;
- bool bold;
- bool italic;
- uint16_t pixel_size;
-
- if (!iter.ReadString(&family) || !iter.ReadBool(&bold) ||
- !iter.ReadBool(&italic) || !iter.ReadUInt16(&pixel_size)) {
- return;
- }
-
- gfx::FontRenderParamsQuery query;
- query.families.push_back(family);
- query.pixel_size = pixel_size;
- query.style = italic ? gfx::Font::ITALIC : 0;
- query.weight = bold ? gfx::Font::Weight::BOLD : gfx::Font::Weight::NORMAL;
- const gfx::FontRenderParams params = gfx::GetFontRenderParams(query, nullptr);
-
- // These are passed as ints since they're interpreted as tri-state chars in
- // Blink.
- base::Pickle reply;
- reply.WriteInt(params.use_bitmaps);
- reply.WriteInt(params.autohinter);
- reply.WriteInt(params.hinting != gfx::FontRenderParams::HINTING_NONE);
- reply.WriteInt(ConvertHinting(params.hinting));
- reply.WriteInt(params.antialiasing);
- reply.WriteInt(ConvertSubpixelRendering(params.subpixel_rendering));
- reply.WriteInt(params.subpixel_positioning);
-
- SendRendererReply(fds, reply, -1);
+ NOTREACHED();
}
void SandboxIPCHandler::HandleMakeSharedMemorySegment(
@@ -347,34 +146,6 @@ void SandboxIPCHandler::HandleMakeSharedMemorySegment(
SendRendererReply(fds, reply, shm_fd);
}
-void SandboxIPCHandler::HandleMatchWithFallback(
- int fd,
- base::PickleIterator iter,
- const std::vector<base::ScopedFD>& fds) {
- std::string face;
- bool is_bold;
- bool is_italic;
- uint32_t charset;
- uint32_t fallback_family;
-
- if (!iter.ReadString(&face) || face.empty() || !iter.ReadBool(&is_bold) ||
- !iter.ReadBool(&is_italic) || !iter.ReadUInt32(&charset) ||
- !iter.ReadUInt32(&fallback_family)) {
- return;
- }
-
- int font_fd = MatchFontFaceWithFallback(face, is_bold, is_italic, charset,
- fallback_family);
-
- base::Pickle reply;
- SendRendererReply(fds, reply, font_fd);
-
- if (font_fd >= 0) {
- if (IGNORE_EINTR(close(font_fd)) < 0)
- PLOG(ERROR) << "close";
- }
-}
-
void SandboxIPCHandler::SendRendererReply(
const std::vector<base::ScopedFD>& fds,
const base::Pickle& reply,
diff --git a/chromium/content/browser/sandbox_ipc_linux.h b/chromium/content/browser/sandbox_ipc_linux.h
index 06c2c604397..684a6aa0825 100644
--- a/chromium/content/browser/sandbox_ipc_linux.h
+++ b/chromium/content/browser/sandbox_ipc_linux.h
@@ -18,8 +18,6 @@
#include "content/common/content_export.h"
#include "third_party/icu/source/common/unicode/uchar.h"
-class SkString;
-
namespace content {
class SandboxIPCHandler : public base::DelegateSimpleThread::Delegate {
@@ -32,55 +30,19 @@ class SandboxIPCHandler : public base::DelegateSimpleThread::Delegate {
void Run() override;
- class TestObserver {
- public:
- virtual void OnGetFallbackFontForChar(UChar32 c,
- std::string name,
- int id) = 0;
- virtual void OnFontOpen(int id) = 0;
- };
- CONTENT_EXPORT static void SetObserverForTests(TestObserver* observer);
-
private:
- int FindOrAddPath(const SkString& path);
-
void HandleRequestFromChild(int fd);
- void HandleFontMatchRequest(int fd,
- base::PickleIterator iter,
- const std::vector<base::ScopedFD>& fds);
-
- void HandleFontOpenRequest(int fd,
- base::PickleIterator iter,
- const std::vector<base::ScopedFD>& fds);
-
- void HandleGetFallbackFontForChar(int fd,
- base::PickleIterator iter,
- const std::vector<base::ScopedFD>& fds);
-
- void HandleGetStyleForStrike(int fd,
- base::PickleIterator iter,
- const std::vector<base::ScopedFD>& fds);
-
- void HandleLocaltime(int fd,
- base::PickleIterator iter,
- const std::vector<base::ScopedFD>& fds);
-
void HandleMakeSharedMemorySegment(int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds);
- void HandleMatchWithFallback(int fd,
- base::PickleIterator iter,
- const std::vector<base::ScopedFD>& fds);
-
void SendRendererReply(const std::vector<base::ScopedFD>& fds,
const base::Pickle& reply,
int reply_fd);
const int lifeline_fd_;
const int browser_socket_;
- std::vector<SkString> paths_;
DISALLOW_COPY_AND_ASSIGN(SandboxIPCHandler);
};
diff --git a/chromium/content/browser/sandbox_parameters_mac.mm b/chromium/content/browser/sandbox_parameters_mac.mm
index e9415b0de5f..a9227b8e010 100644
--- a/chromium/content/browser/sandbox_parameters_mac.mm
+++ b/chromium/content/browser/sandbox_parameters_mac.mm
@@ -10,6 +10,7 @@
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/mac/bundle_locations.h"
+#include "base/mac/foundation_util.h"
#include "base/mac/mac_util.h"
#include "base/numerics/checked_math.h"
#include "base/strings/stringprintf.h"
@@ -63,8 +64,8 @@ void SetupCommonSandboxParameters(sandbox::SeatbeltExecClient* client) {
CHECK(client->SetParameter(service_manager::SandboxMac::kSandboxBundlePath,
bundle_path));
- NSBundle* bundle = base::mac::OuterBundle();
- std::string bundle_id = base::SysNSStringToUTF8([bundle bundleIdentifier]);
+ std::string bundle_id = base::mac::BaseBundleID();
+ DCHECK(!bundle_id.empty()) << "base::mac::OuterBundle is unset";
CHECK(client->SetParameter(
service_manager::SandboxMac::kSandboxChromeBundleId, bundle_id));
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc b/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc
index 4e828cd1a16..7f88ed37799 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc
+++ b/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc
@@ -4,9 +4,8 @@
#include "content/browser/screen_orientation/screen_orientation_delegate_android.h"
-#include "content/browser/android/content_view_core.h"
#include "content/browser/screen_orientation/screen_orientation_provider.h"
-#include "jni/ScreenOrientationProvider_jni.h"
+#include "jni/ScreenOrientationProviderImpl_jni.h"
#include "ui/android/window_android.h"
#include "ui/gfx/native_widget_types.h"
@@ -29,7 +28,7 @@ void ScreenOrientationDelegateAndroid::Lock(
WebContents* web_contents,
blink::WebScreenOrientationLockType lock_orientation) {
gfx::NativeWindow window = web_contents->GetTopLevelNativeWindow();
- Java_ScreenOrientationProvider_lockOrientation(
+ Java_ScreenOrientationProviderImpl_lockOrientation(
base::android::AttachCurrentThread(),
window ? window->GetJavaObject() : nullptr,
lock_orientation);
@@ -39,13 +38,13 @@ bool ScreenOrientationDelegateAndroid::ScreenOrientationProviderSupported() {
// TODO(MLamouri): Consider moving isOrientationLockEnabled to a separate
// function, so reported error messages can differentiate between the device
// never supporting orientation or currently not support orientation.
- return Java_ScreenOrientationProvider_isOrientationLockEnabled(
+ return Java_ScreenOrientationProviderImpl_isOrientationLockEnabled(
base::android::AttachCurrentThread());
}
void ScreenOrientationDelegateAndroid::Unlock(WebContents* web_contents) {
gfx::NativeWindow window = web_contents->GetTopLevelNativeWindow();
- Java_ScreenOrientationProvider_unlockOrientation(
+ Java_ScreenOrientationProviderImpl_unlockOrientation(
base::android::AttachCurrentThread(),
window ? window->GetJavaObject() : nullptr);
}
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index 9c298b18244..e3b04edb5a3 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -129,7 +129,6 @@ network::ResourceRequest CreateXHRRequest(const char* url) {
request.plugin_child_id = -1;
request.resource_type = RESOURCE_TYPE_XHR;
request.appcache_host_id = kAppCacheNoHostId;
- request.download_to_file = false;
request.should_reset_appcache = false;
request.is_main_frame = true;
request.transition_type = ui::PAGE_TRANSITION_LINK;
@@ -185,28 +184,44 @@ class SecurityExploitBrowserTest : public ContentBrowserTest {
static void CreateLoaderAndStartOnIOThread(
scoped_refptr<ResourceMessageFilter> filter,
+ network::mojom::URLLoaderRequest request,
int route_id,
int request_id,
- const network::ResourceRequest& request) {
- network::mojom::URLLoaderPtr loader;
- network::TestURLLoaderClient client;
+ const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderClientPtrInfo client) {
filter->CreateLoaderAndStart(
- mojo::MakeRequest(&loader), route_id, request_id,
- network::mojom::kURLLoadOptionNone, request,
- client.CreateInterfacePtr(),
+ std::move(request), route_id, request_id,
+ network::mojom::kURLLoadOptionNone, resource_request,
+ network::mojom::URLLoaderClientPtr(std::move(client)),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
}
- static void CreateLoaderAndStart(RenderProcessHost* process,
- int route_id,
- int request_id,
- const network::ResourceRequest& request) {
+ static void CreateLoaderAndStart(
+ RenderProcessHost* process,
+ int route_id,
+ int request_id,
+ const network::ResourceRequest& resource_request) {
+ network::mojom::URLLoaderPtr loader;
+ network::TestURLLoaderClient client;
+ CreateLoaderAndStart(process, mojo::MakeRequest(&loader), route_id,
+ request_id, resource_request,
+ client.CreateInterfacePtr().PassInterface());
+ }
+
+ static void CreateLoaderAndStart(
+ RenderProcessHost* process,
+ network::mojom::URLLoaderRequest request,
+ int route_id,
+ int request_id,
+ const network::ResourceRequest& resource_request,
+ network::mojom::URLLoaderClientPtrInfo client) {
RenderProcessHostImpl* impl = static_cast<RenderProcessHostImpl*>(process);
auto filter = impl->resource_message_filter_;
process->GetChannel()->ipc_task_runner()->PostTask(
FROM_HERE, base::BindOnce(CreateLoaderAndStartOnIOThread, filter,
- route_id, request_id, request));
+ std::move(request), route_id, request_id,
+ resource_request, std::move(client)));
}
void TryCreateDuplicateRequestIds(Shell* shell, bool block_loaders) {
@@ -228,11 +243,16 @@ class SecurityExploitBrowserTest : public ContentBrowserTest {
// Use the same request id twice.
RenderProcessHostKillWaiter kill_waiter(rfh->GetProcess());
-
- CreateLoaderAndStart(rfh->GetProcess(), rfh->GetRoutingID(),
- kRequestIdNotPreviouslyUsed, request);
- CreateLoaderAndStart(rfh->GetProcess(), rfh->GetRoutingID(),
- kRequestIdNotPreviouslyUsed, request);
+ // We need to keep loader and client to keep the requests alive.
+ network::mojom::URLLoaderPtr loader1, loader2;
+ network::TestURLLoaderClient client1, client2;
+
+ CreateLoaderAndStart(rfh->GetProcess(), mojo::MakeRequest(&loader1),
+ rfh->GetRoutingID(), kRequestIdNotPreviouslyUsed,
+ request, client1.CreateInterfacePtr().PassInterface());
+ CreateLoaderAndStart(rfh->GetProcess(), mojo::MakeRequest(&loader2),
+ rfh->GetRoutingID(), kRequestIdNotPreviouslyUsed,
+ request, client2.CreateInterfacePtr().PassInterface());
EXPECT_EQ(bad_message::RDH_INVALID_REQUEST_ID, kill_waiter.Wait());
}
@@ -508,10 +528,12 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
// Renderer process should not be able to create multiple requests with the same
// id.
-// Disabled due to flakiness on all operating systems: crbug.com/799516
-IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, DISABLED_InvalidRequestId) {
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidRequestId) {
// Existing loader in pending_loaders_.
TryCreateDuplicateRequestIds(shell(), false);
+}
+
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidBlockedRequestId) {
// Existing loader in blocked_loaders_map_.
TryCreateDuplicateRequestIds(shell(), true);
}
@@ -526,9 +548,11 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, MismatchedOriginOnCommit) {
->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("/hung"));
+ // Navigate to a new URL, with an interceptor that replaces the origin with
+ // one that does not match params.url.
+ GURL url(embedded_test_server()->GetURL("/title2.html"));
+ PwnCommitIPC(shell()->web_contents(), url, url,
+ url::Origin::Create(GURL("http://bar.com/")));
// Use LoadURL, as the test shouldn't wait for navigation commit.
NavigationController& controller = shell()->web_contents()->GetController();
@@ -539,30 +563,12 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, MismatchedOriginOnCommit) {
RenderProcessHostKillWaiter kill_waiter(
root->current_frame_host()->GetProcess());
- // Create commit params with different origins in params.url and
- // params.origin.
- std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params =
- std::make_unique<FrameHostMsg_DidCommitProvisionalLoad_Params>();
- 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->method = "GET";
- params->page_state = PageState::CreateFromURL(url);
- params->origin = url::Origin::Create(GURL("http://bar.com/"));
-
- service_manager::mojom::InterfaceProviderPtr interface_provider;
- static_cast<mojom::FrameHost*>(root->current_frame_host())
- ->DidCommitProvisionalLoad(std::move(params),
- mojo::MakeRequest(&interface_provider));
-
// 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());
+ EXPECT_TRUE(
+ root->current_frame_host()->GetProcess()->IsInitializedAndNotDead());
EXPECT_EQ(bad_message::RFH_INVALID_ORIGIN_ON_COMMIT, kill_waiter.Wait());
}
@@ -585,14 +591,15 @@ class ScopedInterfaceProviderRequestReplacer
~ScopedInterfaceProviderRequestReplacer() override = default;
protected:
- void WillDispatchDidCommitProvisionalLoad(
+ bool WillDispatchDidCommitProvisionalLoad(
RenderFrameHost* render_frame_host,
::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
service_manager::mojom::InterfaceProviderRequest*
interface_provider_request) override {
- ASSERT_TRUE(interface_provider_request_override_.has_value());
+ CHECK(interface_provider_request_override_.has_value());
*interface_provider_request =
std::move(interface_provider_request_override_).value();
+ return true;
}
private:
diff --git a/chromium/content/browser/service_manager/common_browser_interfaces.cc b/chromium/content/browser/service_manager/common_browser_interfaces.cc
index af1a24e735b..ea58b9e3599 100644
--- a/chromium/content/browser/service_manager/common_browser_interfaces.cc
+++ b/chromium/content/browser/service_manager/common_browser_interfaces.cc
@@ -4,6 +4,7 @@
#include "content/browser/service_manager/common_browser_interfaces.h"
+#include <map>
#include <memory>
#include <utility>
@@ -15,10 +16,15 @@
#include "build/build_config.h"
#include "components/discardable_memory/service/discardable_shared_memory_manager.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/gpu/gpu_client_impl.h"
+#include "content/common/child_process_host_impl.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/common/connection_filter.h"
#include "content/public/common/service_manager_connection.h"
+#include "content/public/common/service_names.mojom.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "services/service_manager/public/cpp/binder_registry.h"
+#include "services/ui/public/interfaces/gpu.mojom.h"
#include "ui/base/ui_base_features.h"
#if defined(OS_WIN)
@@ -44,7 +50,7 @@ class ConnectionFilterImpl : public ConnectionFilter {
#elif defined(OS_MACOSX)
registry_.AddInterface(base::BindRepeating(&FontLoaderDispatcher::Create));
#endif
- if (!features::IsMashEnabled()) {
+ if (features::IsAshInBrowserProcess()) {
// For mus, the mojom::discardable_memory::DiscardableSharedMemoryManager
// is exposed from ui::Service. So we don't need bind the interface here.
auto* browser_main_loop = BrowserMainLoop::GetInstance();
@@ -57,9 +63,13 @@ class ConnectionFilterImpl : public ConnectionFilter {
}
}
}
+ if (features::IsAshInBrowserProcess()) {
+ registry_.AddInterface(base::BindRepeating(
+ &ConnectionFilterImpl::BindGpuRequest, base::Unretained(this)));
+ }
}
- ~ConnectionFilterImpl() override {}
+ ~ConnectionFilterImpl() override { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
private:
template <typename Interface>
@@ -72,9 +82,44 @@ class ConnectionFilterImpl : public ConnectionFilter {
const std::string& interface_name,
mojo::ScopedMessagePipeHandle* interface_pipe,
service_manager::Connector* connector) override {
+ // Ignore ui::mojom::Gpu interface request from Renderer process.
+ // The request will be handled in RenderProcessHostImpl.
+ if (source_info.identity.name() == mojom::kRendererServiceName &&
+ interface_name == ui::mojom::Gpu::Name_)
+ return;
+
registry_.TryBindInterface(interface_name, interface_pipe, source_info);
}
+ void BindGpuRequest(ui::mojom::GpuRequest request,
+ const service_manager::BindSourceInfo& source_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // Only allow one connection per service to avoid possible race condition.
+ // So Reset the current connection if there is one.
+ gpu_clients_.erase(source_info.identity);
+
+ const int gpu_client_id =
+ ChildProcessHostImpl::GenerateChildProcessUniqueId();
+ const uint64_t gpu_client_tracing_id =
+ ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(
+ gpu_client_id);
+ auto gpu_client = std::make_unique<GpuClientImpl>(
+ gpu_client_id, gpu_client_tracing_id,
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ gpu_client->SetConnectionErrorHandler(
+ base::BindOnce(&ConnectionFilterImpl::OnGpuConnectionClosed,
+ base::Unretained(this), source_info.identity));
+ gpu_client->Add(std::move(request));
+ gpu_clients_.emplace(source_info.identity, std::move(gpu_client));
+ }
+
+ void OnGpuConnectionClosed(const service_manager::Identity& service_identity,
+ GpuClient* client) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ gpu_clients_.erase(service_identity);
+ }
+
template <typename Interface>
static void BindOnTaskRunner(
const scoped_refptr<base::TaskRunner>& task_runner,
@@ -88,6 +133,8 @@ class ConnectionFilterImpl : public ConnectionFilter {
service_manager::BinderRegistryWithArgs<
const service_manager::BindSourceInfo&>
registry_;
+ std::map<service_manager::Identity, std::unique_ptr<GpuClientImpl>>
+ gpu_clients_;
DISALLOW_COPY_AND_ASSIGN(ConnectionFilterImpl);
};
diff --git a/chromium/content/browser/service_manager/service_manager_context.cc b/chromium/content/browser/service_manager/service_manager_context.cc
index 6df4527d9a4..2daaf7231c0 100644
--- a/chromium/content/browser/service_manager/service_manager_context.cc
+++ b/chromium/content/browser/service_manager/service_manager_context.cc
@@ -11,17 +11,21 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/deferred_sequenced_task_runner.h"
#include "base/feature_list.h"
#include "base/json/json_reader.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "base/no_destructor.h"
#include "base/process/process_handle.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "build/build_config.h"
+#include "content/app/strings/grit/content_strings.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/gpu/gpu_process_host.h"
@@ -45,8 +49,8 @@
#include "media/media_buildflags.h"
#include "media/mojo/buildflags.h"
#include "media/mojo/interfaces/constants.mojom.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/incoming_broker_client_invitation.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+#include "mojo/public/cpp/system/invitation.h"
#include "services/audio/public/mojom/constants.mojom.h"
#include "services/audio/service_factory.h"
#include "services/catalog/manifest_provider.h"
@@ -91,6 +95,11 @@
#include "ui/aura/env.h"
#endif
+#if defined(OS_LINUX)
+#include "components/services/font/font_service_app.h"
+#include "components/services/font/public/interfaces/constants.mojom.h"
+#endif
+
namespace content {
namespace {
@@ -106,13 +115,12 @@ void DestroyConnectorOnIOThread() { g_io_thread_connector.Get().reset(); }
// Launch a process for a service once its sandbox type is known.
void StartServiceInUtilityProcess(
const std::string& service_name,
- const base::string16& process_name,
+ const ContentBrowserClient::ProcessNameCallback& process_name_callback,
base::Optional<std::string> process_group,
service_manager::mojom::ServiceRequest request,
service_manager::mojom::PIDReceiverPtr pid_receiver,
service_manager::mojom::ConnectResult query_result,
const std::string& sandbox_string) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_manager::SandboxType sandbox_type =
service_manager::UtilitySandboxTypeFromString(sandbox_string);
@@ -128,7 +136,10 @@ void StartServiceInUtilityProcess(
} else {
// Start a new process for this service.
UtilityProcessHost* impl = new UtilityProcessHost(nullptr, nullptr);
+ base::string16 process_name = process_name_callback.Run();
+ DCHECK(!process_name.empty());
impl->SetName(process_name);
+ impl->SetMetricsName(service_name);
impl->SetServiceIdentity(service_manager::Identity(service_name));
impl->SetSandboxType(sandbox_type);
impl->Start();
@@ -155,16 +166,15 @@ void StartServiceInUtilityProcess(
// Determine a sandbox type for a service and launch a process for it.
void QueryAndStartServiceInUtilityProcess(
const std::string& service_name,
- const base::string16& process_name,
+ const ContentBrowserClient::ProcessNameCallback& process_name_callback,
base::Optional<std::string> process_group,
service_manager::mojom::ServiceRequest request,
service_manager::mojom::PIDReceiverPtr pid_receiver) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
ServiceManagerContext::GetConnectorForIOThread()->QueryService(
service_manager::Identity(service_name),
- base::BindOnce(&StartServiceInUtilityProcess, service_name, process_name,
- std::move(process_group), std::move(request),
- std::move(pid_receiver)));
+ base::BindOnce(&StartServiceInUtilityProcess, service_name,
+ process_name_callback, std::move(process_group),
+ std::move(request), std::move(pid_receiver)));
}
// Request service_manager::mojom::ServiceFactory from GPU process host. Must be
@@ -173,7 +183,6 @@ void StartServiceInGpuProcess(
const std::string& service_name,
service_manager::mojom::ServiceRequest request,
service_manager::mojom::PIDReceiverPtr pid_receiver) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
GpuProcessHost* process_host = GpuProcessHost::Get();
if (!process_host) {
DLOG(ERROR) << "GPU process host not available.";
@@ -247,8 +256,20 @@ class NullServiceProcessLauncherFactory
private:
std::unique_ptr<service_manager::ServiceProcessLauncher> Create(
const base::FilePath& service_path) override {
- LOG(ERROR) << "Attempting to run unsupported native service: "
- << service_path.value();
+ // There are innocuous races where browser code may attempt to connect
+ // to a specific renderer instance through the Service Manager after that
+ // renderer has been terminated. These result in this code path being hit
+ // fairly regularly and the resulting log spam causes confusion. We suppress
+ // this message only for "content_renderer".
+ const base::FilePath::StringType kRendererServiceFilename =
+ base::FilePath().AppendASCII(mojom::kRendererServiceName).value();
+ const base::FilePath::StringType service_executable =
+ service_path.BaseName().value();
+ if (service_executable.find(kRendererServiceFilename) ==
+ base::FilePath::StringType::npos) {
+ LOG(ERROR) << "Attempting to run unsupported native service: "
+ << service_path.value();
+ }
return nullptr;
}
@@ -274,15 +295,6 @@ class ServiceBinaryLauncherFactory
DISALLOW_COPY_AND_ASSIGN(ServiceBinaryLauncherFactory);
};
-// Helper to invoke GetGeolocationRequestContext on the currently-set
-// ContentBrowserClient.
-void GetGeolocationRequestContextFromContentClient(
- base::OnceCallback<void(scoped_refptr<net::URLRequestContextGetter>)>
- callback) {
- GetContentClient()->browser()->GetGeolocationRequestContext(
- std::move(callback));
-}
-
bool ShouldEnableVizService() {
#if defined(USE_AURA)
// aura::Env can be null in tests.
@@ -301,31 +313,49 @@ std::unique_ptr<service_manager::Service> CreateNetworkService() {
return std::make_unique<network::NetworkService>(std::move(registry));
}
+bool AudioServiceOutOfProcess() {
+ // Returns true iff kAudioServiceOutOfProcess feature is enabled and if the
+ // embedder does not provide its own in-process AudioManager.
+ return base::FeatureList::IsEnabled(features::kAudioServiceOutOfProcess) &&
+ !GetContentClient()->browser()->OverridesAudioManager();
+}
+
} // namespace
// State which lives on the IO thread and drives the ServiceManager.
class ServiceManagerContext::InProcessServiceManagerContext
: public base::RefCountedThreadSafe<InProcessServiceManagerContext> {
public:
- InProcessServiceManagerContext() {}
+ InProcessServiceManagerContext(scoped_refptr<base::SingleThreadTaskRunner>
+ service_manager_thread_task_runner)
+ : service_manager_thread_task_runner_(
+ service_manager_thread_task_runner) {}
void Start(
service_manager::mojom::ServicePtrInfo packaged_services_service_info,
std::unique_ptr<BuiltinManifestProvider> manifest_provider) {
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)
- ->PostTask(
- FROM_HERE,
- base::BindOnce(&InProcessServiceManagerContext::StartOnIOThread,
- this, std::move(manifest_provider),
- std::move(packaged_services_service_info)));
+ service_manager_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &InProcessServiceManagerContext::StartOnServiceManagerThread, this,
+ std::move(manifest_provider),
+ std::move(packaged_services_service_info),
+ base::ThreadTaskRunnerHandle::Get()));
}
void ShutDown() {
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)
- ->PostTask(
- FROM_HERE,
- base::BindOnce(&InProcessServiceManagerContext::ShutDownOnIOThread,
- this));
+ service_manager_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &InProcessServiceManagerContext::ShutDownOnServiceManagerThread,
+ this));
+ }
+
+ void StartServices(std::vector<service_manager::Identity> identities) {
+ service_manager_thread_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&InProcessServiceManagerContext ::
+ StartServicesOnServiceManagerThread,
+ this, std::move(identities)));
}
private:
@@ -333,9 +363,10 @@ class ServiceManagerContext::InProcessServiceManagerContext
~InProcessServiceManagerContext() {}
- void StartOnIOThread(
+ void StartOnServiceManagerThread(
std::unique_ptr<BuiltinManifestProvider> manifest_provider,
- service_manager::mojom::ServicePtrInfo packaged_services_service_info) {
+ service_manager::mojom::ServicePtrInfo packaged_services_service_info,
+ scoped_refptr<base::SequencedTaskRunner> ui_thread_task_runner) {
manifest_provider_ = std::move(manifest_provider);
std::unique_ptr<service_manager::ServiceProcessLauncherFactory>
service_process_launcher_factory;
@@ -358,12 +389,15 @@ class ServiceManagerContext::InProcessServiceManagerContext
service_manager::mojom::kRootUserID),
std::move(packaged_services_service), nullptr);
service_manager_->SetInstanceQuitCallback(
- base::Bind(&OnInstanceQuitOnIOThread));
+ base::Bind(&OnInstanceQuitOnServiceManagerThread,
+ std::move(ui_thread_task_runner)));
}
- static void OnInstanceQuitOnIOThread(const service_manager::Identity& id) {
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)
- ->PostTask(FROM_HERE, base::BindOnce(&OnInstanceQuit, id));
+ static void OnInstanceQuitOnServiceManagerThread(
+ scoped_refptr<base::SequencedTaskRunner> ui_thread_task_runner,
+ const service_manager::Identity& id) {
+ ui_thread_task_runner->PostTask(FROM_HERE,
+ base::BindOnce(&OnInstanceQuit, id));
}
static void OnInstanceQuit(const service_manager::Identity& id) {
@@ -377,25 +411,43 @@ class ServiceManagerContext::InProcessServiceManagerContext
}
}
- void ShutDownOnIOThread() {
+ void ShutDownOnServiceManagerThread() {
service_manager_.reset();
manifest_provider_.reset();
}
+ void StartServicesOnServiceManagerThread(
+ std::vector<service_manager::Identity> identities) {
+ if (!service_manager_)
+ return;
+
+ for (const auto& identity : identities)
+ service_manager_->StartService(identity);
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner>
+ service_manager_thread_task_runner_;
std::unique_ptr<BuiltinManifestProvider> manifest_provider_;
std::unique_ptr<service_manager::ServiceManager> service_manager_;
DISALLOW_COPY_AND_ASSIGN(InProcessServiceManagerContext);
};
-ServiceManagerContext::ServiceManagerContext() {
+ServiceManagerContext::ServiceManagerContext(
+ scoped_refptr<base::SingleThreadTaskRunner>
+ service_manager_thread_task_runner)
+ : service_manager_thread_task_runner_(
+ std::move(service_manager_thread_task_runner)) {
+ // The |service_manager_thread_task_runner_| must have been created before
+ // starting the ServiceManager.
+ DCHECK(service_manager_thread_task_runner_);
service_manager::mojom::ServiceRequest packaged_services_request;
if (service_manager::ServiceManagerIsRemote()) {
- auto invitation =
- mojo::edk::IncomingBrokerClientInvitation::AcceptFromCommandLine(
- mojo::edk::TransportProtocol::kLegacy);
+ auto endpoint = mojo::PlatformChannel::RecoverPassedEndpointFromCommandLine(
+ *base::CommandLine::ForCurrentProcess());
+ auto invitation = mojo::IncomingInvitation::Accept(std::move(endpoint));
packaged_services_request =
- service_manager::GetServiceRequestFromCommandLine(invitation.get());
+ service_manager::GetServiceRequestFromCommandLine(&invitation);
} else {
std::unique_ptr<BuiltinManifestProvider> manifest_provider =
std::make_unique<BuiltinManifestProvider>();
@@ -423,7 +475,8 @@ ServiceManagerContext::ServiceManagerContext() {
manifest_provider->AddServiceManifest(manifest.name,
manifest.resource_id);
}
- in_process_context_ = new InProcessServiceManagerContext;
+ in_process_context_ =
+ new InProcessServiceManagerContext(service_manager_thread_task_runner_);
service_manager::mojom::ServicePtr packaged_services_service;
packaged_services_request = mojo::MakeRequest(&packaged_services_service);
@@ -431,14 +484,14 @@ ServiceManagerContext::ServiceManagerContext() {
std::move(manifest_provider));
}
- packaged_services_connection_ = ServiceManagerConnection::Create(
- std::move(packaged_services_request),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ packaged_services_connection_ =
+ ServiceManagerConnection::Create(std::move(packaged_services_request),
+ service_manager_thread_task_runner_);
service_manager::mojom::ServicePtr root_browser_service;
- ServiceManagerConnection::SetForProcess(ServiceManagerConnection::Create(
- mojo::MakeRequest(&root_browser_service),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
+ ServiceManagerConnection::SetForProcess(
+ ServiceManagerConnection::Create(mojo::MakeRequest(&root_browser_service),
+ service_manager_thread_task_runner_));
auto* browser_connection = ServiceManagerConnection::GetForProcess();
service_manager::mojom::PIDReceiverPtr pid_receiver;
@@ -467,9 +520,10 @@ ServiceManagerContext::ServiceManagerContext() {
// ContentNfcDelegate.java respectively for comments on those parameters.
device_info.factory = base::Bind(
&device::CreateDeviceService, device_blocking_task_runner,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- base::BindRepeating(&GetGeolocationRequestContextFromContentClient),
+ service_manager_thread_task_runner_,
+ GetContentClient()->browser()->GetSystemSharedURLLoaderFactory(),
GetContentClient()->browser()->GetGeolocationApiKey(),
+ GetContentClient()->browser()->ShouldUseGmsCoreGeolocationProvider(),
base::Bind(&WakeLockContextHost::GetNativeViewForContext),
base::Bind(&ContentBrowserClient::OverrideSystemLocationProvider,
base::Unretained(GetContentClient()->browser())),
@@ -477,8 +531,8 @@ ServiceManagerContext::ServiceManagerContext() {
#else
device_info.factory = base::Bind(
&device::CreateDeviceService, device_blocking_task_runner,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- base::BindRepeating(&GetGeolocationRequestContextFromContentClient),
+ service_manager_thread_task_runner_,
+ GetContentClient()->browser()->GetSystemSharedURLLoaderFactory(),
GetContentClient()->browser()->GetGeolocationApiKey(),
base::Bind(&ContentBrowserClient::OverrideSystemLocationProvider,
base::Unretained(GetContentClient()->browser())));
@@ -512,7 +566,9 @@ ServiceManagerContext::ServiceManagerContext() {
#else
base::CreateSingleThreadTaskRunnerWithTraits(
#endif
- base::TaskTraits(base::MayBlock(), base::TaskPriority::BACKGROUND));
+ base::TaskTraits({base::MayBlock(), base::WithBaseSyncPrimitives(),
+ base::TaskPriority::BACKGROUND}),
+ base::SingleThreadTaskRunnerThreadMode::DEDICATED);
packaged_services_connection_->AddEmbeddedService(
video_capture::mojom::kServiceName, video_capture_info);
}
@@ -542,7 +598,20 @@ ServiceManagerContext::ServiceManagerContext() {
&out_of_process_services);
out_of_process_services[data_decoder::mojom::kServiceName] =
- base::ASCIIToUTF16("Data Decoder Service");
+ base::BindRepeating(&base::ASCIIToUTF16, "Data Decoder Service");
+
+#if defined(OS_LINUX)
+ {
+ service_manager::EmbeddedServiceInfo font_service_info;
+ font_service_info.factory =
+ base::BindRepeating(font_service::FontServiceApp::CreateService);
+ font_service_info.task_runner = base::CreateSequencedTaskRunnerWithTraits(
+ base::TaskTraits({base::MayBlock(), base::WithBaseSyncPrimitives(),
+ base::TaskPriority::USER_BLOCKING}));
+ packaged_services_connection_->AddEmbeddedService(
+ font_service::mojom::kServiceName, font_service_info);
+ }
+#endif
bool network_service_enabled =
base::FeatureList::IsEnabled(network::features::kNetworkService);
@@ -554,65 +623,59 @@ ServiceManagerContext::ServiceManagerContext() {
if (network_service_in_process) {
service_manager::EmbeddedServiceInfo network_service_info;
network_service_info.factory = base::BindRepeating(CreateNetworkService);
- network_service_info.task_runner =
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
+ network_service_info.task_runner = service_manager_thread_task_runner_;
packaged_services_connection_->AddEmbeddedService(
mojom::kNetworkServiceName, network_service_info);
} else {
out_of_process_services[mojom::kNetworkServiceName] =
- base::ASCIIToUTF16("Network Service");
+ base::BindRepeating(&base::ASCIIToUTF16, "Network Service");
}
- } else {
- // Create the in-process NetworkService object so that its getter is
- // available on the IO thread.
- GetNetworkService();
}
- if (BrowserMainLoop* bml = BrowserMainLoop::GetInstance()) {
- if (bml->AudioServiceOutOfProcess()) {
- DCHECK(base::FeatureList::IsEnabled(features::kAudioServiceAudioStreams));
- out_of_process_services[audio::mojom::kServiceName] =
- base::ASCIIToUTF16("Audio Service");
- } else {
- service_manager::EmbeddedServiceInfo info;
- info.factory = base::BindRepeating(
- [](BrowserMainLoop* bml)
- -> std::unique_ptr<service_manager::Service> {
- return audio::CreateEmbeddedService(bml->audio_manager());
- },
- bml);
- info.task_runner = bml->audio_service_runner();
- DCHECK(info.task_runner);
- packaged_services_connection_->AddEmbeddedService(
- audio::mojom::kServiceName, info);
- }
+ if (AudioServiceOutOfProcess()) {
+ DCHECK(base::FeatureList::IsEnabled(features::kAudioServiceAudioStreams));
+ out_of_process_services[audio::mojom::kServiceName] =
+ base::BindRepeating(&base::ASCIIToUTF16, "Audio Service");
+ } else {
+ service_manager::EmbeddedServiceInfo info;
+ // TODO(hanxi): Removes BrowserMainLoop::GetAudioManager().
+ // https://crbug.com/853254.
+ info.factory =
+ base::BindRepeating([]() -> std::unique_ptr<service_manager::Service> {
+ return audio::CreateEmbeddedService(
+ BrowserMainLoop::GetAudioManager());
+ });
+ info.task_runner = GetAudioServiceRunner();
+ DCHECK(info.task_runner);
+ packaged_services_connection_->AddEmbeddedService(
+ audio::mojom::kServiceName, info);
}
if (features::IsVideoCaptureServiceEnabledForOutOfProcess()) {
out_of_process_services[video_capture::mojom::kServiceName] =
- base::ASCIIToUTF16("Video Capture Service");
+ base::BindRepeating(&base::ASCIIToUTF16, "Video Capture Service");
}
#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_UTILITY_PROCESS)
out_of_process_services[media::mojom::kMediaServiceName] =
- base::ASCIIToUTF16("Media Service");
+ base::BindRepeating(&base::ASCIIToUTF16, "Media Service");
#endif
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
- out_of_process_services[media::mojom::kCdmServiceName] =
- base::ASCIIToUTF16("Content Decryption Module Service");
+ out_of_process_services[media::mojom::kCdmServiceName] = base::BindRepeating(
+ &base::ASCIIToUTF16, "Content Decryption Module Service");
#endif
if (ShouldEnableVizService()) {
out_of_process_services[viz::mojom::kVizServiceName] =
- base::ASCIIToUTF16("Visuals Service");
+ base::BindRepeating(&base::ASCIIToUTF16, "Visuals Service");
}
for (const auto& service : out_of_process_services) {
packaged_services_connection_->AddServiceRequestHandlerWithPID(
service.first,
base::BindRepeating(&QueryAndStartServiceInUtilityProcess,
- service.first, service.second.process_name,
+ service.first, service.second.process_name_callback,
service.second.process_group));
}
@@ -629,15 +692,8 @@ ServiceManagerContext::ServiceManagerContext() {
packaged_services_connection_->Start();
- RegisterCommonBrowserInterfaces(browser_connection);
- browser_connection->Start();
-
- if (network_service_enabled && !network_service_in_process) {
- // Start the network service process as soon as possible, since it is
- // critical to start up performance.
- browser_connection->GetConnector()->StartService(
- mojom::kNetworkServiceName);
- }
+ in_process_context_->StartServices(
+ GetContentClient()->browser()->GetStartupServices());
}
ServiceManagerContext::~ServiceManagerContext() {
@@ -649,8 +705,8 @@ ServiceManagerContext::~ServiceManagerContext() {
in_process_context_->ShutDown();
if (ServiceManagerConnection::GetForProcess())
ServiceManagerConnection::DestroyForProcess();
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&DestroyConnectorOnIOThread));
+ service_manager_thread_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&DestroyConnectorOnIOThread));
}
// static
@@ -668,4 +724,36 @@ bool ServiceManagerContext::HasValidProcessForProcessGroup(
return iter->second->GetData().handle != base::kNullProcessHandle;
}
+// static
+void ServiceManagerContext::StartBrowserConnection() {
+ auto* browser_connection = ServiceManagerConnection::GetForProcess();
+ RegisterCommonBrowserInterfaces(browser_connection);
+ browser_connection->Start();
+
+ bool network_service_enabled =
+ base::FeatureList::IsEnabled(network::features::kNetworkService);
+ bool network_service_in_process =
+ base::FeatureList::IsEnabled(features::kNetworkServiceInProcess) ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess);
+ if (!network_service_enabled) {
+ // Create the in-process NetworkService object so that its getter is
+ // available on the IO thread.
+ GetNetworkService();
+ } else if (!network_service_in_process) {
+ // Start the network service process as soon as possible, since it is
+ // critical to start up performance.
+ browser_connection->GetConnector()->StartService(
+ mojom::kNetworkServiceName);
+ }
+}
+
+// static
+base::DeferredSequencedTaskRunner*
+ServiceManagerContext::GetAudioServiceRunner() {
+ static base::NoDestructor<scoped_refptr<base::DeferredSequencedTaskRunner>>
+ instance(new base::DeferredSequencedTaskRunner);
+ return (*instance).get();
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_manager/service_manager_context.h b/chromium/content/browser/service_manager/service_manager_context.h
index b31926acae7..eebd74a0c5e 100644
--- a/chromium/content/browser/service_manager/service_manager_context.h
+++ b/chromium/content/browser/service_manager/service_manager_context.h
@@ -11,8 +11,13 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
+namespace base {
+class DeferredSequencedTaskRunner;
+}
+
namespace service_manager {
class Connector;
}
@@ -26,7 +31,9 @@ class ServiceManagerConnection;
// launched from an external one.
class CONTENT_EXPORT ServiceManagerContext {
public:
- ServiceManagerContext();
+ explicit ServiceManagerContext(scoped_refptr<base::SingleThreadTaskRunner>
+ service_manager_thread_task_runner);
+
~ServiceManagerContext();
// Returns a service_manager::Connector that can be used on the IO thread.
@@ -37,9 +44,17 @@ class CONTENT_EXPORT ServiceManagerContext {
static bool HasValidProcessForProcessGroup(
const std::string& process_group_name);
+ // Starts the browser connction to the ServiceManager. It must be called after
+ // the BrowserMainLoop starts.
+ static void StartBrowserConnection();
+
+ static base::DeferredSequencedTaskRunner* GetAudioServiceRunner();
+
private:
class InProcessServiceManagerContext;
+ scoped_refptr<base::SingleThreadTaskRunner>
+ service_manager_thread_task_runner_;
scoped_refptr<InProcessServiceManagerContext> in_process_context_;
std::unique_ptr<ServiceManagerConnection> packaged_services_connection_;
diff --git a/chromium/content/browser/service_worker/OWNERS b/chromium/content/browser/service_worker/OWNERS
index a0d918100a0..f7f81753511 100644
--- a/chromium/content/browser/service_worker/OWNERS
+++ b/chromium/content/browser/service_worker/OWNERS
@@ -5,11 +5,13 @@
# //content/browser/resources/service_worker/
# //content/common/service_worker/
# //content/renderer/service_worker/
+# //third_party/blink/common/service_worker/
+# //third_party/blink/public/common/service_worker/
# //third_party/blink/public/mojom/service_worker/
-# //third_party/blink/public/web/modules/serviceworker/
-# //third_party/blink/public/platform/modules/serviceworker/
+# //third_party/blink/public/platform/modules/service_worker/
+# //third_party/blink/public/web/modules/service_worker/
# //third_party/WebKit/LayoutTests/external/wpt/service-workers/
-# //third_party/blink/renderer/modules/serviceworkers/
+# //third_party/blink/renderer/modules/service_worker/
falken@chromium.org
horo@chromium.org
diff --git a/chromium/content/browser/service_worker/README.md b/chromium/content/browser/service_worker/README.md
new file mode 100644
index 00000000000..55d7fb79b43
--- /dev/null
+++ b/chromium/content/browser/service_worker/README.md
@@ -0,0 +1,44 @@
+# Service workers
+[content/browser/service_worker]: /content/browser/service_worker
+[content/renderer/service_worker]: /content/renderer/service_worker
+[content/renderer/service_worker]: /content/renderer/service_worker
+[content/common/service_worker]: /content/common/service_worker
+[third_party/blink/common/service_worker]: /third_party/blink/common/service_worker
+[third_party/blink/public/common/service_worker]: /third_party/blink/public/common/service_worker
+[third_party/blink/public/mojom/service_worker]: /third_party/blink/public/mojom/service_worker
+[third_party/blink/public/platform/modules/service_worker]: /third_party/blink/public/platform/modules/service_worker
+[third_party/blink/public/web/modules/service_worker]: /third_party/blink/public/web/modules/service_worker
+[third_party/blink/renderer/modules/service_worker]: /third_party/blink/renderer/modules/service_worker
+[Blink Public API]: /third_party/blink/public
+[Onion Soup]: https://docs.google.com/document/d/1K1nO8G9dO9kNSmtVz2gJ2GG9gQOTgm65sJlV3Fga4jE/edit?usp=sharing
+
+This is Chromium's implementation of [service
+workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). See the
+[Service Worker specification](https://w3c.github.io/ServiceWorker/).
+
+## Directory structure
+
+- [content/browser/service_worker]: Browser process code, including stored
+ registration data, the inception of starting a service worker, and controlling
+ navigations. The browser process has host objects of most live renderer
+ entities that deal with service workers, and the bulk of work is performed by
+ these host objects.
+- [content/renderer/service_worker]: Renderer process code. This should move to
+ third_party/blink per [Onion Soup].
+- [content/common/service_worker]: Common process code.
+- [third_party/blink/common/service_worker]: Common process code. Contains the
+ implementation of third_party/blink/public/common/service_worker.
+- [third_party/blink/public/common/service_worker]: Header files for common
+ process code that can be used by both inside Blink and outside Blink.
+- [third_party/blink/public/mojom/service_worker]: Mojom files for common
+ process code that can be used by both Blink and content.
+- [third_party/blink/public/platform/modules/service_worker]: [Blink Public API]
+ header files. This should be removed per [Onion Soup].
+- [third_party/blink/public/web/modules/service_worker]: More [Blink Public API]
+ header files. This should be removed per [Onion Soup].
+- [third_party/blink/renderer/modules/service_worker]: Renderer process code in
+ Blink. This is the closest code to the web-exposed Service Worker API.
+
+## Other documentation
+
+- [Service Worker Security FAQ](/docs/security/service-worker-security-faq.md)
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
index eef43481a14..7e3365820e3 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -13,6 +13,7 @@
#include "base/trace_event/trace_event.h"
#include "content/browser/bad_message.h"
#include "content/browser/devtools/service_worker_devtools_manager.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_content_settings_proxy_impl.h"
@@ -21,18 +22,17 @@
#include "content/common/content_switches_internal.h"
#include "content/common/renderer.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/common/service_worker/service_worker_utils.h"
#include "content/common/url_loader_factory_bundle.mojom.h"
#include "content/common/url_schemes.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 "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_message.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/web/web_console_message.h"
#include "url/gurl.h"
@@ -79,7 +79,7 @@ void NotifyWorkerVersionDoomedOnUI(int worker_process_id, int worker_route_id) {
}
using SetupProcessCallback = base::OnceCallback<void(
- ServiceWorkerStatusCode,
+ blink::ServiceWorkerStatusCode,
mojom::EmbeddedWorkerStartParamsPtr,
std::unique_ptr<ServiceWorkerProcessManager::AllocatedProcessInfo>,
std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy>,
@@ -106,7 +106,8 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
if (!process_manager) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT,
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort,
std::move(params), std::move(process_info),
std::move(devtools_proxy), std::move(factory_bundle),
nullptr /* cache_storage */));
@@ -114,10 +115,11 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
}
// Get a process.
- ServiceWorkerStatusCode status = process_manager->AllocateWorkerProcess(
- params->embedded_worker_id, params->scope, params->script_url,
- can_use_existing_process, process_info.get());
- if (status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode status =
+ process_manager->AllocateWorkerProcess(
+ params->embedded_worker_id, params->scope, params->script_url,
+ can_use_existing_process, process_info.get());
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(std::move(callback), status, std::move(params),
@@ -128,7 +130,8 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
const int process_id = process_info->process_id;
RenderProcessHost* rph = RenderProcessHost::FromID(process_id);
// TODO(falken): This CHECK should no longer fail, so turn to a DCHECK it if
- // crash reports agree. Consider also checking for rph->HasConnection().
+ // crash reports agree. Consider also checking for
+ // rph->IsInitializedAndNotDead().
CHECK(rph);
// Create cache storage now as an optimization, so the service worker can use
@@ -153,11 +156,24 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
}
// S13nServiceWorker:
+ // Create a default loader for network fallback.
+ // The factory from RPH::CreateURLLoaderFactory() doesn't support
+ // reconnection to the network service after a crash, but it's probably OK
+ // since it's used for a single service worker startup until installation
+ // finishes (with the exception of https://crbug.com/719052).
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
+ rph->CreateURLLoaderFactory(mojo::MakeRequest(&default_factory_info));
+ factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
+ factory_bundle->default_factory_info() = std::move(default_factory_info);
+ }
+
+ // S13nServiceWorker:
// Create the loader factories for non-http(s) URLs, for example
// chrome-extension:// URLs. For performance, only do this step when the main
// script URL is non-http(s). We assume an http(s) service worker cannot
// importScripts a non-http(s) URL.
- if (ServiceWorkerUtils::IsServicificationEnabled() &&
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
!params->script_url.SchemeIsHTTPOrHTTPS()) {
ContentBrowserClient::NonNetworkURLLoaderFactoryMap factories;
GetContentClient()
@@ -165,7 +181,6 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
->RegisterNonNetworkSubresourceURLLoaderFactories(
rph->GetID(), MSG_ROUTING_NONE, &factories);
- factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
for (auto& pair : factories) {
const std::string& scheme = pair.first;
std::unique_ptr<network::mojom::URLLoaderFactory> factory =
@@ -198,13 +213,10 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
devtools_proxy = std::make_unique<EmbeddedWorkerInstance::DevToolsProxy>(
process_id, routing_id);
- // Set EmbeddedWorkerSettings for content settings only readable from the UI
- // thread.
- // TODO(bengr): Support changes to the data saver setting while the worker is
- // running.
- params->data_saver_enabled =
- GetContentClient()->browser()->IsDataSaverEnabled(
- process_manager->browser_context());
+ // TODO(crbug.com/862854): Support changes to RendererPreferences while the
+ // worker is running.
+ GetContentClient()->browser()->UpdateRendererPreferencesForWorker(
+ process_manager->browser_context(), &params->renderer_preferences);
// Continue to OnSetupCompleted on the IO thread.
BrowserThread::PostTask(
@@ -225,8 +237,7 @@ bool HasSentStartWorker(EmbeddedWorkerInstance::StartingPhase phase) {
case EmbeddedWorkerInstance::SCRIPT_READ_FINISHED:
case EmbeddedWorkerInstance::SCRIPT_STREAMING:
case EmbeddedWorkerInstance::SCRIPT_LOADED:
- case EmbeddedWorkerInstance::SCRIPT_EVALUATED:
- case EmbeddedWorkerInstance::THREAD_STARTED:
+ case EmbeddedWorkerInstance::SCRIPT_EVALUATION:
return true;
case EmbeddedWorkerInstance::STARTING_PHASE_MAX_VALUE:
NOTREACHED();
@@ -337,12 +348,15 @@ class EmbeddedWorkerInstance::StartTask {
StartTask(EmbeddedWorkerInstance* instance,
const GURL& script_url,
- mojom::EmbeddedWorkerInstanceClientRequest request)
+ mojom::EmbeddedWorkerInstanceClientRequest request,
+ base::TimeTicks start_time)
: instance_(instance),
request_(std::move(request)),
state_(ProcessAllocationState::NOT_ALLOCATED),
is_installed_(false),
started_during_browser_startup_(false),
+ skip_recording_startup_time_(instance_->devtools_attached()),
+ start_time_(start_time),
weak_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("ServiceWorker",
@@ -352,6 +366,11 @@ class EmbeddedWorkerInstance::StartTask {
~StartTask() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (did_send_start_) {
+ TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker",
+ "INITIALIZING_ON_RENDERER", this);
+ }
+
TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker",
"EmbeddedWorkerInstance::Start", this);
@@ -375,7 +394,7 @@ class EmbeddedWorkerInstance::StartTask {
break;
}
- // Don't have to abort |start_callback_| here. The caller of
+ // Don't have to abort |sent_start_callback_| here. The caller of
// EmbeddedWorkerInstance::Start(), that is, ServiceWorkerVersion does not
// expect it when the start worker sequence is canceled by Stop() because
// the callback, ServiceWorkerVersion::OnStartSentAndScriptEvaluated(),
@@ -383,9 +402,11 @@ class EmbeddedWorkerInstance::StartTask {
// is stopped, the version attempts to restart the worker if there are
// requests in the queue. See ServiceWorkerVersion::OnStoppedInternal() for
// details.
- // TODO(nhiroki): Reconsider this bizarre layering.
+ // TODO(crbug.com/859912): Reconsider this bizarre layering.
}
+ base::TimeTicks start_time() const { return start_time_; }
+
void set_start_worker_sent_time(base::TimeTicks time) {
start_worker_sent_time_ = time;
}
@@ -393,24 +414,31 @@ class EmbeddedWorkerInstance::StartTask {
return start_worker_sent_time_;
}
+ void set_skip_recording_startup_time() {
+ skip_recording_startup_time_ = true;
+ }
+ bool skip_recording_startup_time() const {
+ return skip_recording_startup_time_;
+ }
+
void Start(mojom::EmbeddedWorkerStartParamsPtr params,
- StatusCallback callback) {
+ StatusCallback sent_start_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(instance_->context_);
+ base::WeakPtr<ServiceWorkerContextCore> context = instance_->context_;
state_ = ProcessAllocationState::ALLOCATING;
- start_callback_ = std::move(callback);
+ sent_start_callback_ = std::move(sent_start_callback);
is_installed_ = params->is_installed;
if (!GetContentClient()->browser()->IsBrowserStartupComplete())
started_during_browser_startup_ = true;
bool can_use_existing_process =
- instance_->context_->GetVersionFailureCount(
- params->service_worker_version_id) < kMaxSameProcessFailureCount;
+ context->GetVersionFailureCount(params->service_worker_version_id) <
+ kMaxSameProcessFailureCount;
DCHECK_EQ(params->embedded_worker_id, instance_->embedded_worker_id_);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "ALLOCATING_PROCESS",
this);
- base::WeakPtr<ServiceWorkerContextCore> context = instance_->context_;
base::WeakPtr<ServiceWorkerProcessManager> process_manager =
context->process_manager()->AsWeakPtr();
@@ -425,24 +453,12 @@ class EmbeddedWorkerInstance::StartTask {
weak_factory_.GetWeakPtr(), process_manager)));
}
- static void RunStartCallback(StartTask* task,
- ServiceWorkerStatusCode status) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "INITIALIZING_ON_RENDERER",
- task, "Status",
- ServiceWorkerStatusToString(status));
- StatusCallback callback = std::move(task->start_callback_);
- task->start_callback_.Reset();
- std::move(callback).Run(status);
- // |task| may be destroyed.
- }
-
bool is_installed() const { return is_installed_; }
private:
void OnSetupCompleted(
base::WeakPtr<ServiceWorkerProcessManager> process_manager,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
mojom::EmbeddedWorkerStartParamsPtr params,
std::unique_ptr<ServiceWorkerProcessManager::AllocatedProcessInfo>
process_info,
@@ -452,7 +468,7 @@ class EmbeddedWorkerInstance::StartTask {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::unique_ptr<WorkerProcessHandle> process_handle;
- if (status == SERVICE_WORKER_OK) {
+ if (status == blink::ServiceWorkerStatusCode::kOk) {
// If we allocated a process, WorkerProcessHandle has to be created before
// returning to ensure the process is eventually released.
process_handle = std::make_unique<WorkerProcessHandle>(
@@ -460,16 +476,14 @@ class EmbeddedWorkerInstance::StartTask {
process_info->process_id);
if (!instance_->context_)
- status = SERVICE_WORKER_ERROR_ABORT;
+ status = blink::ServiceWorkerStatusCode::kErrorAbort;
}
- if (status != SERVICE_WORKER_OK) {
- TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "ALLOCATING_PROCESS",
- this, "Error",
- ServiceWorkerStatusToString(status));
- StatusCallback callback = std::move(start_callback_);
- start_callback_.Reset();
- instance_->OnStartFailed(std::move(callback), status);
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
+ TRACE_EVENT_NESTABLE_ASYNC_END1(
+ "ServiceWorker", "ALLOCATING_PROCESS", this, "Error",
+ blink::ServiceWorkerStatusToString(status));
+ instance_->OnSetupFailed(std::move(sent_start_callback_), status);
// |this| may be destroyed.
return;
}
@@ -497,32 +511,20 @@ class EmbeddedWorkerInstance::StartTask {
// S13nServiceWorker: Build the URLLoaderFactory for loading new scripts.
scoped_refptr<network::SharedURLLoaderFactory> factory_for_new_scripts;
- if (ServiceWorkerUtils::IsServicificationEnabled()) {
- if (factory_bundle) {
- network::mojom::URLLoaderFactoryPtr network_factory_ptr;
- // The factory from CloneNetworkFactory() doesn't support reconnection
- // to the network service after a crash, but it's probably OK since it's
- // used for a single service worker startup until installation finishes
- // (with the exception of https://crbug.com/719052).
- instance_->context_->loader_factory_getter()->CloneNetworkFactory(
- mojo::MakeRequest(&network_factory_ptr));
- scoped_refptr<URLLoaderFactoryBundle> factory =
- base::MakeRefCounted<URLLoaderFactoryBundle>(
- std::move(factory_bundle));
- factory->SetDefaultFactory(std::move(network_factory_ptr));
- factory_for_new_scripts = std::move(factory);
- } else {
- factory_for_new_scripts =
- instance_->context_->loader_factory_getter()->GetNetworkFactory();
- }
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ DCHECK(factory_bundle);
+ factory_for_new_scripts = base::MakeRefCounted<URLLoaderFactoryBundle>(
+ std::move(factory_bundle));
}
instance_->SendStartWorker(std::move(params),
std::move(factory_for_new_scripts),
std::move(cache_storage));
+ std::move(sent_start_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker",
"INITIALIZING_ON_RENDERER", this);
+ did_send_start_ = true;
// |this|'s work is done here, but |instance_| still uses its state until
// startup is complete.
}
@@ -533,12 +535,15 @@ class EmbeddedWorkerInstance::StartTask {
// Ownership is transferred by a PostTask() call after process allocation.
mojom::EmbeddedWorkerInstanceClientRequest request_;
- StatusCallback start_callback_;
+ StatusCallback sent_start_callback_;
+ bool did_send_start_ = false;
ProcessAllocationState state_;
// Used for UMA.
bool is_installed_;
bool started_during_browser_startup_;
+ bool skip_recording_startup_time_;
+ base::TimeTicks start_time_;
base::TimeTicks start_worker_sent_time_;
base::WeakPtrFactory<StartTask> weak_factory_;
@@ -551,8 +556,6 @@ EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
DCHECK(status_ == EmbeddedWorkerStatus::STOPPING ||
status_ == EmbeddedWorkerStatus::STOPPED)
<< static_cast<int>(status_);
- for (auto& observer : listener_list_)
- observer.OnDestroyed();
devtools_proxy_.reset();
if (registry_->GetWorker(embedded_worker_id_))
registry_->RemoveWorker(process_id(), embedded_worker_id_);
@@ -560,25 +563,19 @@ EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
}
void EmbeddedWorkerInstance::Start(mojom::EmbeddedWorkerStartParamsPtr params,
- ProviderInfoGetter provider_info_getter,
StatusCallback callback) {
+ DCHECK(context_);
restart_count_++;
- if (!context_) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT);
- // |this| may be destroyed by the callback.
- return;
- }
DCHECK_EQ(EmbeddedWorkerStatus::STOPPED, status_);
DCHECK(!params->pause_after_download || !params->is_installed);
DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId,
params->service_worker_version_id);
- step_time_ = base::TimeTicks::Now();
+ auto start_time = base::TimeTicks::Now();
status_ = EmbeddedWorkerStatus::STARTING;
starting_phase_ = ALLOCATING_PROCESS;
network_accessed_for_script_ = false;
- provider_info_getter_ = std::move(provider_info_getter);
for (auto& observer : listener_list_)
observer.OnStarting();
@@ -593,7 +590,7 @@ void EmbeddedWorkerInstance::Start(mojom::EmbeddedWorkerStartParamsPtr params,
client_.set_connection_error_handler(
base::BindOnce(&EmbeddedWorkerInstance::Detach, base::Unretained(this)));
inflight_start_task_.reset(
- new StartTask(this, params->script_url, std::move(request)));
+ new StartTask(this, params->script_url, std::move(request), start_time));
inflight_start_task_->Start(std::move(params), std::move(callback));
}
@@ -684,11 +681,8 @@ void EmbeddedWorkerInstance::OnRegisteredToDevToolsManager(
DCHECK(!devtools_proxy_);
devtools_proxy_ = std::move(devtools_proxy);
}
- 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.
- step_time_ = base::TimeTicks();
- }
+ if (wait_for_debugger)
+ inflight_start_task_->set_skip_recording_startup_time();
for (auto& observer : listener_list_)
observer.OnRegisteredToDevToolsManager();
}
@@ -698,7 +692,7 @@ void EmbeddedWorkerInstance::SendStartWorker(
scoped_refptr<network::SharedURLLoaderFactory> factory,
blink::mojom::CacheStoragePtrInfo cache_storage) {
DCHECK(context_);
- DCHECK(params->dispatcher_request.is_pending());
+ DCHECK(params->service_worker_request.is_pending());
DCHECK(params->controller_request.is_pending());
DCHECK(!instance_host_binding_.is_bound());
instance_host_binding_.Bind(mojo::MakeRequest(&params->instance_host));
@@ -710,27 +704,24 @@ void EmbeddedWorkerInstance::SendStartWorker(
const bool is_script_streaming = !params->installed_scripts_info.is_null();
inflight_start_task_->set_start_worker_sent_time(base::TimeTicks::Now());
+
+ // The host must be alive as long as |params->provider_info| is alive.
+ DCHECK(owner_version_->provider_host());
params->provider_info =
- std::move(provider_info_getter_).Run(process_id(), std::move(factory));
+ owner_version_->provider_host()->CompleteStartWorkerPreparation(
+ process_id(), std::move(factory), std::move(params->provider_info));
params->provider_info->cache_storage = std::move(cache_storage);
+
client_->StartWorker(std::move(params));
registry_->BindWorkerToProcess(process_id(), embedded_worker_id());
- if (!step_time_.is_null()) {
- base::TimeDelta duration = UpdateStepTime();
- if (inflight_start_task_->is_installed()) {
- ServiceWorkerMetrics::RecordTimeToSendStartWorker(duration,
- start_situation_);
- }
- }
-
starting_phase_ = is_script_streaming ? SCRIPT_STREAMING : SENT_START_WORKER;
for (auto& observer : listener_list_)
observer.OnStartWorkerMessageSent();
}
void EmbeddedWorkerInstance::RequestTermination() {
- if (!ServiceWorkerUtils::IsServicificationEnabled()) {
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
mojo::ReportBadMessage(
"Invalid termination request: RequestTermination() was called but "
"S13nServiceWorker is not enabled");
@@ -772,45 +763,15 @@ void EmbeddedWorkerInstance::OnScriptReadFinished() {
}
void EmbeddedWorkerInstance::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;
- }
-
- // Don't record the time when script streaming is enabled because
- // OnScriptLoaded is called at the different timing.
- if (starting_phase_ != SCRIPT_STREAMING && !step_time_.is_null()) {
- base::TimeDelta duration = UpdateStepTime();
- ServiceWorkerMetrics::RecordTimeToLoad(duration, source, start_situation_);
- }
// Renderer side has started to launch the worker thread.
starting_phase_ = SCRIPT_LOADED;
- for (auto& observer : listener_list_)
- observer.OnScriptLoaded();
+ owner_version_->OnMainScriptLoaded();
// |this| may be destroyed by the callback.
}
-void EmbeddedWorkerInstance::OnURLJobCreatedForMainScript() {
- if (!inflight_start_task_)
- return;
-
- if (!step_time_.is_null()) {
- base::TimeDelta duration = UpdateStepTime();
- if (inflight_start_task_->is_installed())
- ServiceWorkerMetrics::RecordTimeToURLJob(duration, start_situation_);
- }
-}
-
void EmbeddedWorkerInstance::OnWorkerVersionInstalled() {
if (devtools_proxy_)
devtools_proxy_->NotifyWorkerVersionInstalled();
@@ -821,72 +782,61 @@ void EmbeddedWorkerInstance::OnWorkerVersionDoomed() {
devtools_proxy_->NotifyWorkerVersionDoomed();
}
-void EmbeddedWorkerInstance::OnThreadStarted(int thread_id) {
- if (!context_ || !inflight_start_task_)
- return;
-
- starting_phase_ = THREAD_STARTED;
- if (!step_time_.is_null()) {
- base::TimeDelta duration = UpdateStepTime();
- if (inflight_start_task_->is_installed())
- ServiceWorkerMetrics::RecordTimeToStartThread(duration, start_situation_);
- }
-
- thread_id_ = thread_id;
- for (auto& observer : listener_list_)
- observer.OnThreadStarted();
-}
-
-void EmbeddedWorkerInstance::OnScriptLoadFailed() {
+void EmbeddedWorkerInstance::OnScriptEvaluationStart() {
if (!inflight_start_task_)
return;
- // starting_phase_ may be SCRIPT_READ_FINISHED in case of reading from cache.
+ starting_phase_ = SCRIPT_EVALUATION;
for (auto& observer : listener_list_)
- observer.OnScriptLoadFailed();
+ observer.OnScriptEvaluationStart();
}
-void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) {
- if (!inflight_start_task_)
+void EmbeddedWorkerInstance::OnStarted(
+ blink::mojom::ServiceWorkerStartStatus start_status,
+ int thread_id,
+ mojom::EmbeddedWorkerStartTimingPtr start_timing) {
+ if (!(start_timing->start_worker_received_time <=
+ start_timing->script_evaluation_start_time &&
+ start_timing->script_evaluation_start_time <=
+ start_timing->script_evaluation_end_time)) {
+ mojo::ReportBadMessage("EWI_BAD_START_TIMING");
return;
-
- DCHECK_EQ(EmbeddedWorkerStatus::STARTING, status_);
-
- // Renderer side has completed evaluating the loaded worker script.
- starting_phase_ = SCRIPT_EVALUATED;
- if (!step_time_.is_null()) {
- base::TimeDelta duration = UpdateStepTime();
- if (success && inflight_start_task_->is_installed())
- ServiceWorkerMetrics::RecordTimeToEvaluateScript(duration,
- start_situation_);
}
- base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr();
- StartTask::RunStartCallback(
- inflight_start_task_.get(),
- success ? SERVICE_WORKER_OK
- : SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED);
- // |this| may be destroyed by the callback.
-}
-
-void EmbeddedWorkerInstance::OnStarted(
- mojom::EmbeddedWorkerStartTimingPtr start_timing) {
if (!registry_->OnWorkerStarted(process_id(), embedded_worker_id_))
return;
- // Stop is requested before OnStarted is sent back from the worker.
+ // Stop was requested before OnStarted was sent back from the worker. Just
+ // pretend startup didn't happen, so observers don't try to use the running
+ // worker as it will stop soon.
if (status_ == EmbeddedWorkerStatus::STOPPING)
return;
- if (inflight_start_task_->is_installed()) {
- ServiceWorkerMetrics::RecordEmbeddedWorkerStartTiming(
- std::move(start_timing), inflight_start_task_->start_worker_sent_time(),
- start_situation_);
+ if (inflight_start_task_->is_installed() &&
+ !inflight_start_task_->skip_recording_startup_time()) {
+ ServiceWorkerMetrics::StartTimes times;
+ times.local_start = inflight_start_task_->start_time();
+ times.local_start_worker_sent =
+ inflight_start_task_->start_worker_sent_time();
+ times.remote_start_worker_received =
+ start_timing->start_worker_received_time;
+ times.remote_script_evaluation_start =
+ start_timing->script_evaluation_start_time;
+ times.remote_script_evaluation_end =
+ start_timing->script_evaluation_end_time;
+ times.local_end = base::TimeTicks::Now();
+
+ ServiceWorkerMetrics::RecordStartWorkerTiming(times, start_situation_);
}
+
DCHECK_EQ(EmbeddedWorkerStatus::STARTING, status_);
status_ = EmbeddedWorkerStatus::RUNNING;
+ thread_id_ = thread_id;
inflight_start_task_.reset();
- for (auto& observer : listener_list_)
- observer.OnStarted();
+ for (auto& observer : listener_list_) {
+ observer.OnStarted(start_status);
+ // |this| may be destroyed here. Fortunately we know there is only one
+ // observer in production code.
+ }
}
void EmbeddedWorkerInstance::OnStopped() {
@@ -959,8 +909,11 @@ void EmbeddedWorkerInstance::RemoveObserver(Listener* listener) {
void EmbeddedWorkerInstance::SetDevToolsAttached(bool attached) {
devtools_attached_ = attached;
- if (attached)
- registry_->OnDevToolsAttached(embedded_worker_id_);
+ if (!attached)
+ return;
+ if (inflight_start_task_)
+ inflight_start_task_->set_skip_recording_startup_time();
+ registry_->OnDevToolsAttached(embedded_worker_id_);
}
void EmbeddedWorkerInstance::OnNetworkAccessedForScriptLoad() {
@@ -980,8 +933,9 @@ void EmbeddedWorkerInstance::ReleaseProcess() {
thread_id_ = kInvalidEmbeddedWorkerThreadId;
}
-void EmbeddedWorkerInstance::OnStartFailed(StatusCallback callback,
- ServiceWorkerStatusCode status) {
+void EmbeddedWorkerInstance::OnSetupFailed(
+ StatusCallback callback,
+ blink::ServiceWorkerStatusCode status) {
EmbeddedWorkerStatus old_status = status_;
ReleaseProcess();
base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr();
@@ -992,15 +946,6 @@ void EmbeddedWorkerInstance::OnStartFailed(StatusCallback callback,
}
}
-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;
-}
-
void EmbeddedWorkerInstance::AddMessageToConsole(
blink::WebConsoleMessage::Level level,
const std::string& message) {
@@ -1040,16 +985,14 @@ std::string EmbeddedWorkerInstance::StartingPhaseToString(StartingPhase phase) {
return "Script downloading";
case SCRIPT_LOADED:
return "Script loaded";
- case SCRIPT_EVALUATED:
- return "Script evaluated";
- case THREAD_STARTED:
- return "Thread started";
case SCRIPT_READ_STARTED:
return "Script read started";
case SCRIPT_READ_FINISHED:
return "Script read finished";
case SCRIPT_STREAMING:
return "Script streaming";
+ case SCRIPT_EVALUATION:
+ return "Script evaluation";
case STARTING_PHASE_MAX_VALUE:
NOTREACHED();
}
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
index 2546eb0d4ae..4f034cdf345 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.h
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -26,9 +26,9 @@
#include "content/common/content_export.h"
#include "content/common/service_worker/controller_service_worker.mojom.h"
#include "content/common/service_worker/embedded_worker.mojom.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h"
#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
@@ -41,6 +41,11 @@ class ServiceWorkerContentSettingsProxyImpl;
class ServiceWorkerContextCore;
class ServiceWorkerVersion;
+namespace service_worker_new_script_loader_unittest {
+class ServiceWorkerNewScriptLoaderTest;
+FORWARD_DECLARE_TEST(ServiceWorkerNewScriptLoaderTest, AccessedNetwork);
+} // namespace service_worker_new_script_loader_unittest
+
// This gives an interface to control one EmbeddedWorker instance, which
// may be 'in-waiting' or running in one of the child processes added by
// AddProcessReference().
@@ -50,7 +55,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
: public mojom::EmbeddedWorkerInstanceHost {
public:
class DevToolsProxy;
- using StatusCallback = base::OnceCallback<void(ServiceWorkerStatusCode)>;
+ using StatusCallback =
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)>;
// This enum is used in UMA histograms. Append-only.
enum StartingPhase {
@@ -60,23 +66,20 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
SENT_START_WORKER = 3,
SCRIPT_DOWNLOADING = 4,
SCRIPT_LOADED = 5,
- SCRIPT_EVALUATED = 6,
- // THREAD_STARTED happens after SCRIPT_LOADED and before SCRIPT_EVALUATED
- THREAD_STARTED = 7,
+ // SCRIPT_EVALUATED = 6, // Obsolete
+ // THREAD_STARTED = 7, // Obsolete
// Script read happens after SENT_START_WORKER and before SCRIPT_LOADED
// (installed scripts only)
SCRIPT_READ_STARTED = 8,
SCRIPT_READ_FINISHED = 9,
SCRIPT_STREAMING = 10,
- // Add new values here.
+ SCRIPT_EVALUATION = 11,
+ // Add new values here and update enums.xml.
STARTING_PHASE_MAX_VALUE,
};
- using ProviderInfoGetter =
- base::OnceCallback<mojom::ServiceWorkerProviderInfoForStartWorkerPtr(
- int /* process_id */,
- scoped_refptr<network::SharedURLLoaderFactory>)>;
-
+ // DEPRECATED, only for use by ServiceWorkerVersion.
+ // TODO(crbug.com/855852): Remove this interface.
class Listener {
public:
virtual ~Listener() {}
@@ -85,8 +88,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
virtual void OnProcessAllocated() {}
virtual void OnRegisteredToDevToolsManager() {}
virtual void OnStartWorkerMessageSent() {}
- virtual void OnThreadStarted() {}
- virtual void OnStarted() {}
+ virtual void OnScriptEvaluationStart() {}
+ virtual void OnStarted(blink::mojom::ServiceWorkerStartStatus status) {}
// Called when status changed to STOPPING. The renderer has been sent a Stop
// IPC message and OnStopped() will be called upon successful completion.
@@ -104,8 +107,6 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
// worker died. When this is called, status is STOPPED.
virtual void OnDetached(EmbeddedWorkerStatus old_status) {}
- virtual void OnScriptLoaded() {}
- virtual void OnScriptLoadFailed() {}
virtual void OnReportException(const base::string16& error_message,
int line_number,
int column_number,
@@ -115,26 +116,21 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
const base::string16& message,
int line_number,
const GURL& source_url) {}
- // The instance is being deleted, so it's not safe to call any methods that
- // may result in a virtual method call.
- virtual void OnDestroyed() {}
};
~EmbeddedWorkerInstance() override;
// 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.
- // |params| should be populated with service worker version info needed
- // to start the worker. If the worker is already installed,
- // |installed_scripts_info| holds information about its scripts; otherwise,
- // it is null.
- // |provider_info_getter| is called when this instance
- // allocates a process and is ready to send a StartWorker message.
- void Start(
- mojom::EmbeddedWorkerStartParamsPtr params,
- ProviderInfoGetter provider_info_getter,
- StatusCallback callback);
+ // STOPPED status.
+ //
+ // |sent_start_callback| is invoked once the Start IPC is sent, or if an error
+ // prevented that from happening. The callback is not invoked in some cases,
+ // e.g., when Stop() is called and aborts the start procedure. Note that when
+ // the callback is invoked with kOk status, the service worker has not yet
+ // finished starting. Observe OnStarted()/OnStopped() for when start completed
+ // or failed.
+ void Start(mojom::EmbeddedWorkerStartParamsPtr params,
+ StatusCallback sent_start_callback);
// Stops the worker. It is invalid to call this when the worker is not in
// STARTING or RUNNING status.
@@ -165,6 +161,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
int thread_id() const { return thread_id_; }
int worker_devtools_agent_route_id() const;
+ // DEPRECATED, only for use by ServiceWorkerVersion.
+ // TODO(crbug.com/855852): Remove the Listener interface.
void AddObserver(Listener* listener);
void RemoveObserver(Listener* listener);
@@ -195,10 +193,6 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
// Called when the worker is doomed.
void OnWorkerVersionDoomed();
- // Called when the net::URLRequestJob to load the service worker script
- // created. Not called for import scripts.
- void OnURLJobCreatedForMainScript();
-
// Add message to the devtools console.
void AddMessageToConsole(blink::WebConsoleMessage::Level level,
const std::string& message);
@@ -224,6 +218,9 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, StartAndStop);
FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, DetachDuringStart);
FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, StopDuringStart);
+ FRIEND_TEST_ALL_PREFIXES(service_worker_new_script_loader_unittest::
+ ServiceWorkerNewScriptLoaderTest,
+ AccessedNetwork);
// Constructor is called via EmbeddedWorkerRegistry::CreateWorker().
// This instance holds a ref of |registry|.
@@ -260,15 +257,12 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
void CountFeature(blink::mojom::WebFeature feature) override;
void OnReadyForInspection() override;
void OnScriptLoaded() override;
- // Notifies the corresponding provider host that the thread has started and is
- // ready to receive messages.
- void OnThreadStarted(int thread_id) override;
- void OnScriptLoadFailed() override;
- // Fires the callback passed to Start().
- void OnScriptEvaluated(bool success) override;
+ void OnScriptEvaluationStart() override;
// Changes the internal worker status from STARTING to RUNNING.
- void OnStarted(mojom::EmbeddedWorkerStartTimingPtr start_timing) override;
- // Resets the embedded worker instance to the initial state. This will change
+ void OnStarted(blink::mojom::ServiceWorkerStartStatus status,
+ int thread_id,
+ mojom::EmbeddedWorkerStartTimingPtr start_timing) override;
+ // Resets the embedded worker instance to the initial state. Changes
// the internal status from STARTING or RUNNING to STOPPED.
void OnStopped() override;
void OnReportException(const base::string16& error_message,
@@ -287,11 +281,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
// Called back from StartTask when the startup sequence failed. Calls
// ReleaseProcess() and invokes |callback| with |status|. May destroy |this|.
- void OnStartFailed(StatusCallback callback, ServiceWorkerStatusCode status);
-
- // Returns the time elapsed since |step_time_| and updates |step_time_|
- // to the current time.
- base::TimeDelta UpdateStepTime();
+ void OnSetupFailed(StatusCallback callback,
+ blink::ServiceWorkerStatusCode status);
base::WeakPtr<ServiceWorkerContextCore> context_;
scoped_refptr<EmbeddedWorkerRegistry> registry_;
@@ -316,9 +307,6 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
// Binding for EmbeddedWorkerInstanceHost, runs on IO thread.
mojo::AssociatedBinding<EmbeddedWorkerInstanceHost> instance_host_binding_;
- // This is set at Start and used on SendStartWorker.
- ProviderInfoGetter provider_info_getter_;
-
// Whether devtools is attached or not.
bool devtools_attached_;
@@ -335,9 +323,6 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
ServiceWorkerMetrics::StartSituation start_situation_ =
ServiceWorkerMetrics::StartSituation::UNKNOWN;
- // Used for UMA. The start time of the current start sequence step.
- base::TimeTicks step_time_;
-
std::unique_ptr<ServiceWorkerContentSettingsProxyImpl> content_settings_;
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 9389f539804..5dac55e4405 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -22,7 +22,7 @@
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/embedded_worker.mojom.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -31,75 +31,28 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace content {
namespace {
-void SaveStatusAndCall(ServiceWorkerStatusCode* out,
- base::OnceClosure callback,
- ServiceWorkerStatusCode status) {
- *out = status;
- std::move(callback).Run();
+EmbeddedWorkerInstance::StatusCallback ReceiveStatus(
+ base::Optional<blink::ServiceWorkerStatusCode>* out_status,
+ base::OnceClosure quit) {
+ return base::BindOnce(
+ [](base::Optional<blink::ServiceWorkerStatusCode>* out_status,
+ base::OnceClosure quit, blink::ServiceWorkerStatusCode status) {
+ *out_status = status;
+ std::move(quit).Run();
+ },
+ out_status, std::move(quit));
}
} // namespace
-class ProviderHostEndpoints : public mojom::ServiceWorkerContainerHost {
- public:
- ProviderHostEndpoints() : binding_(this) {}
-
- ~ProviderHostEndpoints() override {}
-
- mojom::ServiceWorkerProviderInfoForStartWorkerPtr CreateProviderInfoPtr() {
- DCHECK(!binding_.is_bound());
- DCHECK(!client_.is_bound());
- // Just keep the endpoints.
- mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info =
- mojom::ServiceWorkerProviderInfoForStartWorker::New();
- binding_.Bind(mojo::MakeRequest(&provider_info->host_ptr_info));
- provider_info->client_request = mojo::MakeRequest(&client_);
- mojo::MakeRequest(&provider_info->interface_provider);
- return provider_info;
- }
-
- private:
- // Implements mojom::ServiceWorkerContainerHost.
- void Register(const GURL& script_url,
- blink::mojom::ServiceWorkerRegistrationOptionsPtr options,
- RegisterCallback callback) override {
- NOTIMPLEMENTED();
- }
- void GetRegistration(const GURL& client_url,
- GetRegistrationCallback callback) override {
- NOTIMPLEMENTED();
- }
- void GetRegistrations(GetRegistrationsCallback callback) override {
- NOTIMPLEMENTED();
- }
- void GetRegistrationForReady(
- GetRegistrationForReadyCallback callback) override {
- NOTIMPLEMENTED();
- }
- void EnsureControllerServiceWorker(
- mojom::ControllerServiceWorkerRequest request,
- mojom::ControllerServiceWorkerPurpose purpose) override {
- NOTIMPLEMENTED();
- }
- void CloneForWorker(
- mojom::ServiceWorkerContainerHostRequest request) override {
- NOTIMPLEMENTED();
- }
- void Ping(PingCallback callback) override { NOTIMPLEMENTED(); }
-
- mojom::ServiceWorkerContainerAssociatedPtr client_;
- mojo::AssociatedBinding<mojom::ServiceWorkerContainerHost> binding_;
-
- DISALLOW_COPY_AND_ASSIGN(ProviderHostEndpoints);
-};
-
-class EmbeddedWorkerInstanceTest : public testing::Test,
+class EmbeddedWorkerInstanceTest : public testing::TestWithParam<bool>,
public EmbeddedWorkerInstance::Listener {
protected:
EmbeddedWorkerInstanceTest()
@@ -115,13 +68,15 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
struct EventLog {
EventType type;
- EmbeddedWorkerStatus status;
+ base::Optional<EmbeddedWorkerStatus> status;
+ base::Optional<blink::mojom::ServiceWorkerStartStatus> start_status;
};
- void RecordEvent(
- EventType type,
- EmbeddedWorkerStatus status = EmbeddedWorkerStatus::STOPPED) {
- EventLog log = {type, status};
+ void RecordEvent(EventType type,
+ base::Optional<EmbeddedWorkerStatus> status = base::nullopt,
+ base::Optional<blink::mojom::ServiceWorkerStartStatus>
+ start_status = base::nullopt) {
+ EventLog log = {type, status, start_status};
events_.push_back(log);
}
@@ -129,7 +84,9 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
void OnStartWorkerMessageSent() override {
RecordEvent(START_WORKER_MESSAGE_SENT);
}
- void OnStarted() override { RecordEvent(STARTED); }
+ void OnStarted(blink::mojom::ServiceWorkerStartStatus status) override {
+ RecordEvent(STARTED, base::nullopt, status);
+ }
void OnStopped(EmbeddedWorkerStatus old_status) override {
RecordEvent(STOPPED, old_status);
}
@@ -138,6 +95,13 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
}
void SetUp() override {
+ if (GetParam()) {
+ scoped_feature_list_.InitAndEnableFeature(
+ blink::features::kServiceWorkerServicification);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ blink::features::kServiceWorkerServicification);
+ }
helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
}
@@ -166,51 +130,58 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
return pair;
}
- ServiceWorkerStatusCode StartWorker(EmbeddedWorkerInstance* worker,
- int id, const GURL& pattern,
- const GURL& url) {
- ServiceWorkerStatusCode status;
- base::RunLoop run_loop;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(id, pattern, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
- run_loop.Run();
- return status;
+ // Calls worker->Start() and runs until the start IPC is sent.
+ //
+ // Expects success. For failure cases, call Start() manually.
+ void StartWorkerUntilStartSent(EmbeddedWorkerInstance* worker,
+ mojom::EmbeddedWorkerStartParamsPtr params) {
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ base::RunLoop loop;
+ worker->Start(std::move(params),
+ ReceiveStatus(&status, loop.QuitClosure()));
+ loop.Run();
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
+ }
+
+ // Calls worker->Start() and runs until startup finishes.
+ //
+ // Expects success. For failure cases, call Start() manually.
+ void StartWorker(EmbeddedWorkerInstance* worker,
+ mojom::EmbeddedWorkerStartParamsPtr params) {
+ StartWorkerUntilStartSent(worker, std::move(params));
+ // TODO(falken): Listen for OnStarted() instead of this.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
}
- mojom::EmbeddedWorkerStartParamsPtr
- CreateStartParams(int version_id, const GURL& scope, const GURL& script_url) {
+ mojom::EmbeddedWorkerStartParamsPtr CreateStartParams(
+ scoped_refptr<ServiceWorkerVersion> version) {
auto params = mojom::EmbeddedWorkerStartParams::New();
- params->service_worker_version_id = version_id;
- params->scope = scope;
- params->script_url = script_url;
+ params->service_worker_version_id = version->version_id();
+ params->scope = version->scope();
+ params->script_url = version->script_url();
params->pause_after_download = false;
params->is_installed = false;
- params->dispatcher_request = CreateEventDispatcher();
+ params->service_worker_request = CreateServiceWorker();
params->controller_request = CreateController();
params->installed_scripts_info = GetInstalledScriptsInfoPtr();
+ params->provider_info = CreateProviderInfo(std::move(version));
return params;
}
mojom::ServiceWorkerProviderInfoForStartWorkerPtr CreateProviderInfo(
- int /* process_id */,
- scoped_refptr<network::SharedURLLoaderFactory>) {
- provider_host_endpoints_.emplace_back(
- std::make_unique<ProviderHostEndpoints>());
- return provider_host_endpoints_.back()->CreateProviderInfoPtr();
- }
-
- EmbeddedWorkerInstance::ProviderInfoGetter CreateProviderInfoGetter() {
- return base::BindOnce(&EmbeddedWorkerInstanceTest::CreateProviderInfo,
- base::Unretained(this));
+ scoped_refptr<ServiceWorkerVersion> version) {
+ auto provider_info = mojom::ServiceWorkerProviderInfoForStartWorker::New();
+ version->provider_host_ = ServiceWorkerProviderHost::PreCreateForController(
+ context()->AsWeakPtr(), version, &provider_info);
+ return provider_info;
}
- mojom::ServiceWorkerEventDispatcherRequest CreateEventDispatcher() {
- dispatchers_.emplace_back();
- return mojo::MakeRequest(&dispatchers_.back());
+ mojom::ServiceWorkerRequest CreateServiceWorker() {
+ service_workers_.emplace_back();
+ return mojo::MakeRequest(&service_workers_.back());
}
mojom::ControllerServiceWorkerRequest CreateController() {
@@ -241,8 +212,6 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
return context()->embedded_worker_registry();
}
- IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); }
-
std::vector<std::unique_ptr<
EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient>>*
mock_instance_clients() {
@@ -250,17 +219,17 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
}
// Mojo endpoints.
- std::vector<mojom::ServiceWorkerEventDispatcherPtr> dispatchers_;
+ std::vector<mojom::ServiceWorkerPtr> service_workers_;
std::vector<mojom::ControllerServiceWorkerPtr> controllers_;
std::vector<blink::mojom::ServiceWorkerInstalledScriptsManagerPtr>
installed_scripts_managers_;
std::vector<blink::mojom::ServiceWorkerInstalledScriptsManagerHostRequest>
installed_scripts_manager_host_requests_;
- std::vector<std::unique_ptr<ProviderHostEndpoints>> provider_host_endpoints_;
TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
std::vector<EventLog> events_;
+ base::test::ScopedFeatureList scoped_feature_list_;
private:
DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest);
@@ -279,7 +248,7 @@ class StalledInStartWorkerHelper : public EmbeddedWorkerTestHelper {
const GURL& scope,
const GURL& script_url,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -293,7 +262,7 @@ class StalledInStartWorkerHelper : public EmbeddedWorkerTestHelper {
}
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id, service_worker_version_id, scope, script_url,
- pause_after_download, std::move(dispatcher_request),
+ pause_after_download, std::move(service_worker_request),
std::move(controller_request), std::move(instance_host),
std::move(provider_info), std::move(installed_scripts_info));
}
@@ -320,28 +289,18 @@ class StalledInStartWorkerHelper : public EmbeddedWorkerTestHelper {
instance_host_ptr_map_;
};
-TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
+TEST_P(EmbeddedWorkerInstanceTest, StartAndStop) {
const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(pattern, url);
- const int64_t service_worker_version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
worker->AddObserver(this);
// Start should succeed.
- ServiceWorkerStatusCode status;
- base::RunLoop run_loop;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(service_worker_version_id, pattern, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
- run_loop.Run();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ StartWorker(worker.get(), CreateStartParams(pair.second));
// The 'WorkerStarted' message should have been sent by
// EmbeddedWorkerTestHelper.
@@ -362,12 +321,14 @@ TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
EXPECT_EQ(STARTED, events_[2].type);
+ EXPECT_EQ(blink::mojom::ServiceWorkerStartStatus::kNormalCompletion,
+ events_[2].start_status.value());
EXPECT_EQ(STOPPED, events_[3].type);
}
// Test that a worker that failed twice will use a new render process
// on the next attempt.
-TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
+TEST_P(EmbeddedWorkerInstanceTest, ForceNewProcess) {
const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
@@ -379,16 +340,7 @@ TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
{
// Start once normally.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- base::RunLoop run_loop;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(service_worker_version_id, pattern, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
- run_loop.Run();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
+ StartWorker(worker.get(), CreateStartParams(pair.second));
// The worker should be using the default render process.
EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
@@ -397,25 +349,16 @@ TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
}
// Fail twice.
- context()->UpdateVersionFailureCount(service_worker_version_id,
- SERVICE_WORKER_ERROR_FAILED);
- context()->UpdateVersionFailureCount(service_worker_version_id,
- SERVICE_WORKER_ERROR_FAILED);
+ context()->UpdateVersionFailureCount(
+ service_worker_version_id, blink::ServiceWorkerStatusCode::kErrorFailed);
+ context()->UpdateVersionFailureCount(
+ service_worker_version_id, blink::ServiceWorkerStatusCode::kErrorFailed);
{
// Start again.
- ServiceWorkerStatusCode status;
base::RunLoop run_loop;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(service_worker_version_id, pattern, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
- run_loop.Run();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ StartWorker(worker.get(), CreateStartParams(pair.second));
- EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
// The worker should be using the new render process.
EXPECT_EQ(helper_->new_render_process_id(), worker->process_id());
worker->Stop();
@@ -423,20 +366,17 @@ TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
}
}
-TEST_F(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
+TEST_P(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(pattern, url);
- const int64_t service_worker_version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
// Start the worker and then call StopIfNotAttachedToDevTools().
- EXPECT_EQ(SERVICE_WORKER_OK,
- StartWorker(worker.get(), service_worker_version_id, pattern, url));
- EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
+ StartWorker(worker.get(), CreateStartParams(pair.second));
EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
worker->StopIfNotAttachedToDevTools();
EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, worker->status());
@@ -448,9 +388,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
// Set devtools_attached to true, and do the same.
worker->SetDevToolsAttached(true);
- EXPECT_EQ(SERVICE_WORKER_OK,
- StartWorker(worker.get(), service_worker_version_id, pattern, url));
- EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
+ StartWorker(worker.get(), CreateStartParams(pair.second));
EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
worker->StopIfNotAttachedToDevTools();
base::RunLoop().RunUntilIdle();
@@ -467,7 +405,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
// Test that the removal of a worker from the registry doesn't remove
// other workers in the same process.
-TEST_F(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) {
+TEST_P(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) {
const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
@@ -480,35 +418,11 @@ TEST_F(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) {
std::unique_ptr<EmbeddedWorkerInstance> worker2 =
embedded_worker_registry()->CreateWorker(pair2.second.get());
- const int64_t version_id1 = pair1.second->version_id();
- const int64_t version_id2 = pair2.second->version_id();
int process_id = helper_->mock_render_process_id();
- {
- // Start worker1.
- ServiceWorkerStatusCode status;
- base::RunLoop run_loop;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id1, pattern, url);
- worker1->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
- run_loop.Run();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
- }
-
- {
- // Start worker2.
- ServiceWorkerStatusCode status;
- base::RunLoop run_loop;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id2, pattern, url);
- worker2->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
- run_loop.Run();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
- }
+ // Start workers.
+ StartWorker(worker1.get(), CreateStartParams(pair1.second));
+ StartWorker(worker2.get(), CreateStartParams(pair2.second));
// The two workers share the same process.
EXPECT_EQ(worker1->process_id(), worker2->process_id());
@@ -528,59 +442,45 @@ TEST_F(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) {
worker2->Stop();
}
-TEST_F(EmbeddedWorkerInstanceTest, DetachDuringProcessAllocation) {
+TEST_P(EmbeddedWorkerInstanceTest, DetachDuringProcessAllocation) {
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(scope, url);
- const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
worker->AddObserver(this);
// Run the start worker sequence and detach during process allocation.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, scope, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, base::DoNothing::Once<>()));
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ mojom::EmbeddedWorkerStartParamsPtr params = CreateStartParams(pair.second);
+ worker->Start(std::move(params), ReceiveStatus(&status, base::DoNothing()));
worker->Detach();
base::RunLoop().RunUntilIdle();
+ // The start callback should not be aborted by detach (see a comment on the
+ // dtor of EmbeddedWorkerInstance::StartTask).
+ EXPECT_FALSE(status);
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, worker->process_id());
- // The start callback should not be aborted by detach (see a comment on the
- // dtor of EmbeddedWorkerInstance::StartTask).
- EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status);
-
// "PROCESS_ALLOCATED" event should not be recorded.
ASSERT_EQ(1u, events_.size());
EXPECT_EQ(DETACHED, events_[0].type);
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status.value());
}
-TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
+TEST_P(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
helper_.reset(new StalledInStartWorkerHelper());
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(scope, url);
- const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
worker->AddObserver(this);
- // Run the start worker sequence until a start worker message is sent.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, scope, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, base::DoNothing::Once<>()));
- base::RunLoop().RunUntilIdle();
-
+ StartWorkerUntilStartSent(worker.get(), CreateStartParams(pair.second));
ASSERT_EQ(2u, events_.size());
EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
@@ -592,34 +492,26 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, worker->process_id());
- // The start callback should not be aborted by detach (see a comment on the
- // dtor of EmbeddedWorkerInstance::StartTask).
- EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status);
-
// "STARTED" event should not be recorded.
ASSERT_EQ(1u, events_.size());
EXPECT_EQ(DETACHED, events_[0].type);
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status.value());
}
-TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
+TEST_P(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(scope, url);
- const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
worker->AddObserver(this);
// Stop the start worker sequence before a process is allocated.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, scope, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, base::DoNothing::Once<>()));
+ worker->Start(CreateStartParams(pair.second),
+ ReceiveStatus(&status, base::DoNothing()));
worker->Stop();
base::RunLoop().RunUntilIdle();
@@ -628,24 +520,17 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
// The start callback should not be aborted by stop (see a comment on the dtor
// of EmbeddedWorkerInstance::StartTask).
- EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status);
+ EXPECT_FALSE(status);
// "PROCESS_ALLOCATED" event should not be recorded.
ASSERT_EQ(1u, events_.size());
EXPECT_EQ(STOPPED, events_[0].type);
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status.value());
events_.clear();
// Restart the worker.
- status = SERVICE_WORKER_ERROR_MAX_VALUE;
- std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop);
- params = CreateStartParams(version_id, scope, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, run_loop->QuitClosure()));
- run_loop->Run();
-
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ StartWorker(worker.get(), CreateStartParams(pair.second));
+
ASSERT_EQ(3u, events_.size());
EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
@@ -672,7 +557,7 @@ class DontReceiveResumeAfterDownloadInstanceClient
bool* const was_resume_after_download_called_;
};
-TEST_F(EmbeddedWorkerInstanceTest, StopDuringPausedAfterDownload) {
+TEST_P(EmbeddedWorkerInstanceTest, StopDuringPausedAfterDownload) {
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
@@ -682,21 +567,17 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringPausedAfterDownload) {
helper_->AsWeakPtr(), &was_resume_after_download_called));
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(scope, url);
- const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
worker->AddObserver(this);
// Run the start worker sequence until pause after download.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
-
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, scope, url);
+ mojom::EmbeddedWorkerStartParamsPtr params = CreateStartParams(pair.second);
params->pause_after_download = true;
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, base::DoNothing::Once<>()));
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ worker->Start(std::move(params), ReceiveStatus(&status, base::DoNothing()));
base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
// Make the worker stopping and attempt to send a resume after download
// message.
@@ -709,26 +590,17 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringPausedAfterDownload) {
EXPECT_FALSE(was_resume_after_download_called);
}
-TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
+TEST_P(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
helper_.reset(new StalledInStartWorkerHelper);
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(scope, url);
- const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
worker->AddObserver(this);
- // Run the start worker sequence until a start worker message is sent.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, scope, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, base::DoNothing::Once<>()));
- base::RunLoop().RunUntilIdle();
-
+ StartWorkerUntilStartSent(worker.get(), CreateStartParams(pair.second));
ASSERT_EQ(2u, events_.size());
EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
@@ -740,30 +612,18 @@ TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, worker->process_id());
- // The start callback should not be aborted by stop (see a comment on the dtor
- // of EmbeddedWorkerInstance::StartTask).
- EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status);
-
// "STARTED" event should not be recorded.
ASSERT_EQ(1u, events_.size());
EXPECT_EQ(STOPPED, events_[0].type);
- EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, events_[0].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, events_[0].status.value());
events_.clear();
// Restart the worker.
static_cast<StalledInStartWorkerHelper*>(helper_.get())
->set_force_stall_in_start(false);
- status = SERVICE_WORKER_ERROR_MAX_VALUE;
- std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop);
-
- params = CreateStartParams(version_id, scope, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, run_loop->QuitClosure()));
- run_loop->Run();
+ StartWorker(worker.get(), CreateStartParams(pair.second));
// The worker should be started.
- EXPECT_EQ(SERVICE_WORKER_OK, status);
ASSERT_EQ(3u, events_.size());
EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
@@ -773,25 +633,18 @@ TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
worker->Stop();
}
-TEST_F(EmbeddedWorkerInstanceTest, Detach) {
+TEST_P(EmbeddedWorkerInstanceTest, Detach) {
const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(pattern, url);
- const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
worker->AddObserver(this);
// Start the worker.
base::RunLoop run_loop;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, pattern, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
- run_loop.Run();
+ StartWorker(worker.get(), CreateStartParams(pair.second));
// Detach.
int process_id = worker->process_id();
@@ -806,7 +659,7 @@ TEST_F(EmbeddedWorkerInstanceTest, Detach) {
}
// Test for when sending the start IPC failed.
-TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) {
+TEST_P(EmbeddedWorkerInstanceTest, FailToSendStartIPC) {
const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
@@ -814,24 +667,28 @@ TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) {
helper_->RegisterMockInstanceClient(nullptr);
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(pattern, url);
- const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
worker->AddObserver(this);
- // Attempt to start the worker.
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, pattern, url);
- worker->Start(std::move(params), CreateProviderInfoGetter(),
- base::DoNothing());
- base::RunLoop().RunUntilIdle();
+ // Attempt to start the worker. From the browser process's point of view, the
+ // start IPC was sent.
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ base::RunLoop loop;
+ worker->Start(CreateStartParams(pair.second),
+ ReceiveStatus(&status, loop.QuitClosure()));
+ loop.Run();
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
+ // But the renderer should not receive the message and the binding is broken.
// Worker should handle the failure of binding on the remote side as detach.
+ base::RunLoop().RunUntilIdle();
+
ASSERT_EQ(3u, events_.size());
EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
EXPECT_EQ(DETACHED, events_[2].type);
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[2].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[2].status.value());
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
}
@@ -848,7 +705,7 @@ class FailEmbeddedWorkerInstanceClientImpl
}
};
-TEST_F(EmbeddedWorkerInstanceTest, RemoveRemoteInterface) {
+TEST_P(EmbeddedWorkerInstanceTest, RemoveRemoteInterface) {
const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
@@ -859,24 +716,25 @@ TEST_F(EmbeddedWorkerInstanceTest, RemoveRemoteInterface) {
ASSERT_EQ(mock_instance_clients()->size(), 1UL);
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(pattern, url);
- const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
worker->AddObserver(this);
// Attempt to start the worker.
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, pattern, url);
- worker->Start(std::move(params), CreateProviderInfoGetter(),
- base::DoNothing());
- base::RunLoop().RunUntilIdle();
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ base::RunLoop loop;
+ worker->Start(CreateStartParams(pair.second),
+ ReceiveStatus(&status, loop.QuitClosure()));
+ loop.Run();
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
// Worker should handle the sudden shutdown as detach.
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(3u, events_.size());
EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
EXPECT_EQ(DETACHED, events_[2].type);
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[2].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[2].status.value());
}
class StoreMessageInstanceClient
@@ -901,7 +759,7 @@ class StoreMessageInstanceClient
messages_;
};
-TEST_F(EmbeddedWorkerInstanceTest, AddMessageToConsole) {
+TEST_P(EmbeddedWorkerInstanceTest, AddMessageToConsole) {
const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
std::unique_ptr<StoreMessageInstanceClient> instance_client =
@@ -911,7 +769,6 @@ TEST_F(EmbeddedWorkerInstanceTest, AddMessageToConsole) {
ASSERT_EQ(mock_instance_clients()->size(), 1UL);
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(pattern, url);
- const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
worker->AddObserver(this);
@@ -920,12 +777,13 @@ TEST_F(EmbeddedWorkerInstanceTest, AddMessageToConsole) {
// cause a crash.
std::pair<blink::WebConsoleMessage::Level, std::string> test_message =
std::make_pair(blink::WebConsoleMessage::kLevelVerbose, "");
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, pattern, url);
- worker->Start(std::move(params), CreateProviderInfoGetter(),
- base::DoNothing());
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ worker->Start(CreateStartParams(pair.second),
+ ReceiveStatus(&status, base::DoNothing()));
worker->AddMessageToConsole(test_message.first, test_message.second);
base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
// Messages sent before sending StartWorker message won't be dispatched.
ASSERT_EQ(0UL, instance_client_rawptr->message().size());
@@ -933,7 +791,6 @@ TEST_F(EmbeddedWorkerInstanceTest, AddMessageToConsole) {
EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
EXPECT_EQ(STARTED, events_[2].type);
- EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
worker->AddMessageToConsole(test_message.first, test_message.second);
base::RunLoop().RunUntilIdle();
@@ -961,7 +818,7 @@ class RecordCacheStorageHelper : public EmbeddedWorkerTestHelper {
const GURL& scope,
const GURL& script_url,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -970,7 +827,7 @@ class RecordCacheStorageHelper : public EmbeddedWorkerTestHelper {
had_cache_storage_ = !!provider_info->cache_storage;
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id, service_worker_version_id, scope, script_url,
- pause_after_download, std::move(dispatcher_request),
+ pause_after_download, std::move(service_worker_request),
std::move(controller_request), std::move(instance_host),
std::move(provider_info), std::move(installed_scripts_info));
}
@@ -983,7 +840,7 @@ class RecordCacheStorageHelper : public EmbeddedWorkerTestHelper {
// Test that the worker is given a CacheStoragePtr during startup, when
// |pause_after_download| is false.
-TEST_F(EmbeddedWorkerInstanceTest, CacheStorageOptimization) {
+TEST_P(EmbeddedWorkerInstanceTest, CacheStorageOptimization) {
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
auto helper = std::make_unique<RecordCacheStorageHelper>();
@@ -991,22 +848,13 @@ TEST_F(EmbeddedWorkerInstanceTest, CacheStorageOptimization) {
helper_ = std::move(helper);
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(scope, url);
- const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
// First, test a worker without pause after download.
{
// Start the worker.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- base::RunLoop run_loop;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, scope, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
- run_loop.Run();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ StartWorker(worker.get(), CreateStartParams(pair.second));
// Cache storage should have been sent.
EXPECT_TRUE(helper_rawptr->had_cache_storage());
@@ -1019,19 +867,16 @@ TEST_F(EmbeddedWorkerInstanceTest, CacheStorageOptimization) {
// Second, test a worker with pause after download.
{
// Start the worker until paused.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, scope, url);
+ mojom::EmbeddedWorkerStartParamsPtr params = CreateStartParams(pair.second);
params->pause_after_download = true;
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, base::DoNothing::Once<>()));
+ worker->Start(std::move(params), base::DoNothing());
base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
// Finish starting.
worker->ResumeAfterDownload();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
// Cache storage should not have been sent.
EXPECT_FALSE(helper_rawptr->had_cache_storage());
@@ -1044,7 +889,7 @@ TEST_F(EmbeddedWorkerInstanceTest, CacheStorageOptimization) {
// Test that the worker is not given a CacheStoragePtr during startup when
// the feature is disabled.
-TEST_F(EmbeddedWorkerInstanceTest, CacheStorageOptimizationIsDisabled) {
+TEST_P(EmbeddedWorkerInstanceTest, CacheStorageOptimizationIsDisabled) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(
blink::features::kEagerCacheStorageSetupForServiceWorkers);
@@ -1056,22 +901,14 @@ TEST_F(EmbeddedWorkerInstanceTest, CacheStorageOptimizationIsDisabled) {
helper_ = std::move(helper);
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(scope, url);
- const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
// First, test a worker without pause after download.
{
// Start the worker.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- base::RunLoop run_loop;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, scope, url);
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
- run_loop.Run();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ mojom::EmbeddedWorkerStartParamsPtr params = CreateStartParams(pair.second);
+ StartWorker(worker.get(), std::move(params));
// Cache storage should not have been sent.
EXPECT_FALSE(helper_rawptr->had_cache_storage());
@@ -1084,19 +921,16 @@ TEST_F(EmbeddedWorkerInstanceTest, CacheStorageOptimizationIsDisabled) {
// Second, test a worker with pause after download.
{
// Start the worker until paused.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- mojom::EmbeddedWorkerStartParamsPtr params =
- CreateStartParams(version_id, scope, url);
+ mojom::EmbeddedWorkerStartParamsPtr params = CreateStartParams(pair.second);
params->pause_after_download = true;
- worker->Start(
- std::move(params), CreateProviderInfoGetter(),
- base::BindOnce(&SaveStatusAndCall, &status, base::DoNothing::Once<>()));
+ worker->Start(std::move(params), base::DoNothing());
base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
// Finish starting.
worker->ResumeAfterDownload();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
// Cache storage should not have been sent.
EXPECT_FALSE(helper_rawptr->had_cache_storage());
@@ -1107,4 +941,47 @@ TEST_F(EmbeddedWorkerInstanceTest, CacheStorageOptimizationIsDisabled) {
}
}
+// Starts the worker with kAbruptCompletion status.
+class AbruptCompletionHelper : public EmbeddedWorkerTestHelper {
+ public:
+ AbruptCompletionHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
+ ~AbruptCompletionHelper() override = default;
+
+ void OnResumeAfterDownload(int embedded_worker_id) override {
+ SimulateScriptEvaluationStart(embedded_worker_id);
+ SimulateWorkerStarted(
+ embedded_worker_id,
+ blink::mojom::ServiceWorkerStartStatus::kAbruptCompletion,
+ GetNextThreadId());
+ }
+};
+
+// Tests that kAbruptCompletion is the OnStarted() status when the
+// renderer reports abrupt completion.
+TEST_P(EmbeddedWorkerInstanceTest, AbruptCompletion) {
+ const GURL scope("http://example.com/");
+ const GURL url("http://example.com/worker.js");
+ helper_ = std::make_unique<AbruptCompletionHelper>();
+
+ RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(scope, url);
+ std::unique_ptr<EmbeddedWorkerInstance> worker =
+ embedded_worker_registry()->CreateWorker(pair.second.get());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
+ worker->AddObserver(this);
+
+ StartWorker(worker.get(), CreateStartParams(pair.second));
+
+ ASSERT_EQ(3u, events_.size());
+ EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
+ EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
+ EXPECT_EQ(STARTED, events_[2].type);
+ EXPECT_EQ(blink::mojom::ServiceWorkerStartStatus::kAbruptCompletion,
+ events_[2].start_status.value());
+ worker->Stop();
+}
+
+INSTANTIATE_TEST_CASE_P(IsServiceWorkerServicificationEnabled,
+ EmbeddedWorkerInstanceTest,
+ ::testing::Bool(););
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.h b/chromium/content/browser/service_worker/embedded_worker_registry.h
index c4e25c4b695..20825f66eef 100644
--- a/chromium/content/browser/service_worker/embedded_worker_registry.h
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.h
@@ -17,7 +17,7 @@
#include "base/strings/string16.h"
#include "content/browser/service_worker/service_worker_lifetime_tracker.h"
#include "content/common/content_export.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
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 4db8a45e0d1..4942766b0e6 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -20,48 +20,31 @@
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/common/background_fetch/background_fetch_types.h"
#include "content/common/renderer.mojom.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "content/common/service_worker/service_worker_messages.h"
-#include "content/common/service_worker/service_worker_utils.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/associated_binding_set.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/http/http_util.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "storage/common/blob_storage/blob_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
namespace content {
namespace {
-class MockServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
- public:
- MockServiceWorkerDispatcherHost(int process_id, IPC::Sender* sender)
- : ServiceWorkerDispatcherHost(process_id), sender_(sender) {}
-
- bool Send(IPC::Message* message) override { return sender_->Send(message); }
-
- protected:
- ~MockServiceWorkerDispatcherHost() override {}
-
- private:
- IPC::Sender* sender_;
-
- DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerDispatcherHost);
-};
-
void OnFetchEventCommon(
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback) {
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback) {
response_callback->OnResponse(
ServiceWorkerResponse(
std::make_unique<std::vector<GURL>>(), 200, "OK",
@@ -81,6 +64,51 @@ void OnFetchEventCommon(
} // namespace
+// A URLLoaderFactory that returns 200 OK with a simple body to any request.
+class EmbeddedWorkerTestHelper::MockNetworkURLLoaderFactory final
+ : public network::mojom::URLLoaderFactory {
+ public:
+ MockNetworkURLLoaderFactory() = default;
+
+ // network::mojom::URLLoaderFactory implementation.
+ void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& url_request,
+ network::mojom::URLLoaderClientPtr client,
+ const net::MutableNetworkTrafficAnnotationTag&
+ traffic_annotation) override {
+ std::string headers = "HTTP/1.1 200 OK\n\n";
+ net::HttpResponseInfo info;
+ info.headers = new net::HttpResponseHeaders(
+ net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
+ network::ResourceResponseHead response;
+ response.headers = info.headers;
+ response.headers->GetMimeType(&response.mime_type);
+ client->OnReceiveResponse(response);
+
+ std::string body = "this body came from the network";
+ uint32_t bytes_written = body.size();
+ mojo::DataPipe data_pipe;
+ data_pipe.producer_handle->WriteData(body.data(), &bytes_written,
+ MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
+ client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
+
+ network::URLLoaderCompletionStatus status;
+ status.error_code = net::OK;
+ client->OnComplete(status);
+ }
+
+ void Clone(network::mojom::URLLoaderFactoryRequest request) override {
+ bindings_.AddBinding(this, std::move(request));
+ }
+
+ private:
+ mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
+ DISALLOW_COPY_AND_ASSIGN(MockNetworkURLLoaderFactory);
+};
+
EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::
MockEmbeddedWorkerInstanceClient(
base::WeakPtr<EmbeddedWorkerTestHelper> helper)
@@ -99,7 +127,6 @@ void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StartWorker(
EmbeddedWorkerInstance* worker =
helper_->registry()->GetWorker(params->embedded_worker_id);
ASSERT_TRUE(worker);
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
helper_->OnStartWorkerStub(std::move(params));
}
@@ -151,23 +178,22 @@ void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::Bind(
client->binding_.Bind(std::move(request));
}
-class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
- : public mojom::ServiceWorkerEventDispatcher {
+class EmbeddedWorkerTestHelper::MockServiceWorker
+ : public mojom::ServiceWorker {
public:
static void Create(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
int embedded_worker_id,
- mojom::ServiceWorkerEventDispatcherRequest request) {
- mojo::MakeStrongBinding(std::make_unique<MockServiceWorkerEventDispatcher>(
- helper, embedded_worker_id),
- std::move(request));
+ mojom::ServiceWorkerRequest request) {
+ mojo::MakeStrongBinding(
+ std::make_unique<MockServiceWorker>(helper, embedded_worker_id),
+ std::move(request));
}
- MockServiceWorkerEventDispatcher(
- const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
- int embedded_worker_id)
+ MockServiceWorker(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
+ int embedded_worker_id)
: helper_(helper), embedded_worker_id_(embedded_worker_id) {}
- ~MockServiceWorkerEventDispatcher() override {}
+ ~MockServiceWorker() override {}
void InitializeGlobalScope(
blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
@@ -246,7 +272,7 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
}
void DispatchFetchEvent(
- mojom::DispatchFetchEventParamsPtr params,
+ blink::mojom::DispatchFetchEventParamsPtr params,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback) override {
if (!helper_)
@@ -294,7 +320,6 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
}
void DispatchAbortPaymentEvent(
- int payment_request_id,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
DispatchAbortPaymentEventCallback callback) override {
if (!helper_)
@@ -304,7 +329,6 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
}
void DispatchCanMakePaymentEvent(
- int payment_request_id,
payments::mojom::CanMakePaymentEventDataPtr event_data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
DispatchCanMakePaymentEventCallback callback) override {
@@ -316,7 +340,6 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
}
void DispatchPaymentRequestEvent(
- int payment_request_id,
payments::mojom::PaymentRequestEventDataPtr event_data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
DispatchPaymentRequestEventCallback callback) override {
@@ -400,6 +423,8 @@ class EmbeddedWorkerTestHelper::MockRendererInterface : public mojom::Renderer {
void SetProcessBackgrounded(bool backgrounded) override { NOTREACHED(); }
void SetSchedulerKeepActive(bool keep_active) override { NOTREACHED(); }
void ProcessPurgeAndSuspend() override { NOTREACHED(); }
+ void SetIsLockedToSite() override { NOTREACHED(); }
+ void EnableV8LowMemoryMode() override { NOTREACHED(); }
base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
mojo::AssociatedBindingSet<mojom::Renderer> bindings_;
@@ -407,11 +432,6 @@ class EmbeddedWorkerTestHelper::MockRendererInterface : public mojom::Renderer {
EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
const base::FilePath& user_data_directory)
- : EmbeddedWorkerTestHelper(user_data_directory, nullptr) {}
-
-EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
- const base::FilePath& user_data_directory,
- scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter)
: browser_context_(std::make_unique<TestBrowserContext>()),
render_process_host_(
std::make_unique<MockRenderProcessHost>(browser_context_.get())),
@@ -423,7 +443,8 @@ EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
next_thread_id_(0),
mock_render_process_id_(render_process_host_->GetID()),
new_mock_render_process_id_(new_render_process_host_->GetID()),
- url_loader_factory_getter_(std::move(url_loader_factory_getter)),
+ url_loader_factory_getter_(
+ base::MakeRefCounted<URLLoaderFactoryGetter>()),
weak_factory_(this) {
scoped_refptr<base::SequencedTaskRunner> database_task_runner =
base::ThreadTaskRunnerHandle::Get();
@@ -432,8 +453,6 @@ EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
url_loader_factory_getter_.get());
wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id());
wrapper_->process_manager()->SetNewProcessIdForTest(new_render_process_id());
- EnsureDispatcherHostForProcess(mock_render_process_id());
- EnsureDispatcherHostForProcess(new_render_process_id());
// Install a mocked mojom::Renderer interface to catch requests to
// establish Mojo connection for EWInstanceClient.
@@ -455,23 +474,27 @@ EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
new_renderer_interface_ptr.get()));
new_render_process_host_->OverrideRendererInterfaceForTesting(
std::move(new_renderer_interface_ptr));
-}
-EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() {
- if (wrapper_.get())
- wrapper_->Shutdown();
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ default_network_loader_factory_ =
+ std::make_unique<MockNetworkURLLoaderFactory>();
+ SetNetworkFactory(default_network_loader_factory_.get());
+ }
}
-bool EmbeddedWorkerTestHelper::Send(IPC::Message* message) {
- OnMessageReceived(*message);
- delete message;
- return true;
-}
+void EmbeddedWorkerTestHelper::SetNetworkFactory(
+ network::mojom::URLLoaderFactory* factory) {
+ if (!factory)
+ factory = default_network_loader_factory_.get();
-bool EmbeddedWorkerTestHelper::OnMessageReceived(const IPC::Message& message) {
- sink_.OnMessageReceived(message);
+ url_loader_factory_getter_->SetNetworkFactoryForTesting(factory);
+ render_process_host_->OverrideURLLoaderFactory(factory);
+ new_render_process_host_->OverrideURLLoaderFactory(factory);
+}
- return false;
+EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() {
+ if (wrapper_.get())
+ wrapper_->Shutdown();
}
void EmbeddedWorkerTestHelper::RegisterMockInstanceClient(
@@ -479,21 +502,6 @@ void EmbeddedWorkerTestHelper::RegisterMockInstanceClient(
mock_instance_clients_.push_back(std::move(client));
}
-void EmbeddedWorkerTestHelper::RegisterDispatcherHost(
- int process_id,
- scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host) {
- dispatcher_hosts_[process_id] = std::move(dispatcher_host);
-}
-
-void EmbeddedWorkerTestHelper::EnsureDispatcherHostForProcess(int process_id) {
- if (context()->GetDispatcherHost(process_id))
- return;
- auto dispatcher_host =
- base::MakeRefCounted<MockServiceWorkerDispatcherHost>(process_id, this);
- dispatcher_host->Init(wrapper_.get());
- RegisterDispatcherHost(process_id, std::move(dispatcher_host));
-}
-
ServiceWorkerContextCore* EmbeddedWorkerTestHelper::context() {
return wrapper_->context();
}
@@ -503,11 +511,6 @@ void EmbeddedWorkerTestHelper::ShutdownContext() {
wrapper_ = nullptr;
}
-ServiceWorkerDispatcherHost*
-EmbeddedWorkerTestHelper::GetDispatcherHostForProcess(int process_id) {
- return dispatcher_hosts_[process_id].get();
-}
-
// static
net::HttpResponseInfo EmbeddedWorkerTestHelper::CreateHttpResponseInfo() {
net::HttpResponseInfo info;
@@ -526,15 +529,15 @@ void EmbeddedWorkerTestHelper::OnStartWorker(
const GURL& scope,
const GURL& script_url,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker);
- MockServiceWorkerEventDispatcher::Create(AsWeakPtr(), embedded_worker_id,
- std::move(dispatcher_request));
+ MockServiceWorker::Create(AsWeakPtr(), embedded_worker_id,
+ std::move(service_worker_request));
embedded_worker_id_service_worker_version_id_map_[embedded_worker_id] =
service_worker_version_id;
embedded_worker_id_instance_host_ptr_map_[embedded_worker_id].Bind(
@@ -561,9 +564,11 @@ void EmbeddedWorkerTestHelper::DidSimulateWorkerScriptCached(
}
void EmbeddedWorkerTestHelper::OnResumeAfterDownload(int embedded_worker_id) {
- SimulateWorkerThreadStarted(GetNextThreadId(), embedded_worker_id);
- SimulateWorkerScriptEvaluated(embedded_worker_id, true /* success */);
- SimulateWorkerStarted(embedded_worker_id);
+ SimulateScriptEvaluationStart(embedded_worker_id);
+ SimulateWorkerStarted(
+ embedded_worker_id,
+ blink::mojom::ServiceWorkerStartStatus::kNormalCompletion,
+ GetNextThreadId());
}
void EmbeddedWorkerTestHelper::OnStopWorker(int embedded_worker_id) {
@@ -572,8 +577,7 @@ void EmbeddedWorkerTestHelper::OnStopWorker(int embedded_worker_id) {
}
void EmbeddedWorkerTestHelper::OnActivateEvent(
- mojom::ServiceWorkerEventDispatcher::DispatchActivateEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchActivateEventCallback callback) {
dispatched_events()->push_back(Event::Activate);
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -583,8 +587,7 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchAbortEventCallback callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
@@ -592,8 +595,7 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
void EmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent(
const std::string& developer_id,
mojom::BackgroundFetchState state,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchClickEventCallback callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
@@ -602,8 +604,7 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchFailEventCallback callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
@@ -612,8 +613,7 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchedEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::DispatchBackgroundFetchedEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
@@ -621,23 +621,20 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchedEvent(
void EmbeddedWorkerTestHelper::OnCookieChangeEvent(
const net::CanonicalCookie& cookie,
::network::mojom::CookieChangeCause cause,
- mojom::ServiceWorkerEventDispatcher::DispatchCookieChangeEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchCookieChangeEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
void EmbeddedWorkerTestHelper::OnExtendableMessageEvent(
mojom::ExtendableMessageEventPtr event,
- mojom::ServiceWorkerEventDispatcher::DispatchExtendableMessageEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchExtendableMessageEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
void EmbeddedWorkerTestHelper::OnInstallEvent(
- mojom::ServiceWorkerEventDispatcher::DispatchInstallEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchInstallEventCallback callback) {
dispatched_events()->push_back(Event::Install);
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
true /* has_fetch_handler */, base::Time::Now());
@@ -646,17 +643,16 @@ void EmbeddedWorkerTestHelper::OnInstallEvent(
void EmbeddedWorkerTestHelper::OnFetchEvent(
int /* embedded_worker_id */,
const network::ResourceRequest& /* request */,
- mojom::FetchEventPreloadHandlePtr /* preload_handle */,
+ blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback) {
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback) {
// TODO(falken): In-line common into here.
OnFetchEventCommon(std::move(response_callback), std::move(finish_callback));
}
void EmbeddedWorkerTestHelper::OnPushEvent(
const PushEventPayload& payload,
- mojom::ServiceWorkerEventDispatcher::DispatchPushEventCallback callback) {
+ mojom::ServiceWorker::DispatchPushEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
@@ -666,8 +662,7 @@ void EmbeddedWorkerTestHelper::OnNotificationClickEvent(
const PlatformNotificationData& notification_data,
int action_index,
const base::Optional<base::string16>& reply,
- mojom::ServiceWorkerEventDispatcher::DispatchNotificationClickEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchNotificationClickEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
@@ -675,16 +670,14 @@ void EmbeddedWorkerTestHelper::OnNotificationClickEvent(
void EmbeddedWorkerTestHelper::OnNotificationCloseEvent(
const std::string& notification_id,
const PlatformNotificationData& notification_data,
- mojom::ServiceWorkerEventDispatcher::DispatchNotificationCloseEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchNotificationCloseEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
}
void EmbeddedWorkerTestHelper::OnAbortPaymentEvent(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchAbortPaymentEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchAbortPaymentEventCallback callback) {
response_callback->OnResponseForAbortPayment(true, base::Time::Now());
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -693,15 +686,12 @@ void EmbeddedWorkerTestHelper::OnAbortPaymentEvent(
void EmbeddedWorkerTestHelper::OnCanMakePaymentEvent(
payments::mojom::CanMakePaymentEventDataPtr event_data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchCanMakePaymentEventCallback callback) {
bool can_make_payment = false;
for (const auto& method_data : event_data->method_data) {
- for (const auto& method : method_data->supported_methods) {
- if (method == "test-method") {
- can_make_payment = true;
- break;
- }
+ if (method_data->supported_method == "test-method") {
+ can_make_payment = true;
+ break;
}
}
response_callback->OnResponseForCanMakePayment(can_make_payment,
@@ -713,8 +703,7 @@ void EmbeddedWorkerTestHelper::OnCanMakePaymentEvent(
void EmbeddedWorkerTestHelper::OnPaymentRequestEvent(
payments::mojom::PaymentRequestEventDataPtr event_data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchPaymentRequestEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchPaymentRequestEventCallback callback) {
response_callback->OnResponseForPaymentRequest(
payments::mojom::PaymentHandlerResponse::New(), base::Time::Now());
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
@@ -768,34 +757,25 @@ void EmbeddedWorkerTestHelper::SimulateWorkerScriptLoaded(
base::RunLoop().RunUntilIdle();
}
-void EmbeddedWorkerTestHelper::SimulateWorkerThreadStarted(
- int thread_id,
+void EmbeddedWorkerTestHelper::SimulateScriptEvaluationStart(
int embedded_worker_id) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker);
ASSERT_TRUE(embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]);
embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]
- ->OnThreadStarted(thread_id);
+ ->OnScriptEvaluationStart();
base::RunLoop().RunUntilIdle();
}
-void EmbeddedWorkerTestHelper::SimulateWorkerScriptEvaluated(
+void EmbeddedWorkerTestHelper::SimulateWorkerStarted(
int embedded_worker_id,
- bool success) {
- EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
- ASSERT_TRUE(worker);
- ASSERT_TRUE(embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]);
- embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]
- ->OnScriptEvaluated(success);
- base::RunLoop().RunUntilIdle();
-}
-
-void EmbeddedWorkerTestHelper::SimulateWorkerStarted(int embedded_worker_id) {
+ blink::mojom::ServiceWorkerStartStatus status,
+ int thread_id) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker);
ASSERT_TRUE(embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]);
embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]->OnStarted(
- mojom::EmbeddedWorkerStartTiming::New());
+ status, thread_id, mojom::EmbeddedWorkerStartTiming::New());
base::RunLoop().RunUntilIdle();
}
@@ -840,14 +820,13 @@ void EmbeddedWorkerTestHelper::OnStartWorkerStub(
EmbeddedWorkerInstance* worker =
registry()->GetWorker(params->embedded_worker_id);
ASSERT_TRUE(worker);
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(
&EmbeddedWorkerTestHelper::OnStartWorker, AsWeakPtr(),
params->embedded_worker_id, params->service_worker_version_id,
params->scope, params->script_url, params->pause_after_download,
- std::move(params->dispatcher_request),
+ std::move(params->service_worker_request),
std::move(params->controller_request),
std::move(params->instance_host), std::move(params->provider_info),
std::move(params->installed_scripts_info)));
@@ -870,8 +849,7 @@ void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id) {
}
void EmbeddedWorkerTestHelper::OnActivateEventStub(
- mojom::ServiceWorkerEventDispatcher::DispatchActivateEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchActivateEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&EmbeddedWorkerTestHelper::OnActivateEvent,
AsWeakPtr(), std::move(callback)));
@@ -881,8 +859,7 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEventStub(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchAbortEventCallback callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent,
@@ -893,8 +870,7 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEventStub(
void EmbeddedWorkerTestHelper::OnBackgroundFetchClickEventStub(
const std::string& developer_id,
mojom::BackgroundFetchState state,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchClickEventCallback callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent,
@@ -905,8 +881,7 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchFailEventStub(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchFailEventCallback callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent,
@@ -918,8 +893,7 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchedEventStub(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::DispatchBackgroundFetchedEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchedEvent,
@@ -930,8 +904,7 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchedEventStub(
void EmbeddedWorkerTestHelper::OnCookieChangeEventStub(
const net::CanonicalCookie& cookie,
::network::mojom::CookieChangeCause cause,
- mojom::ServiceWorkerEventDispatcher::DispatchCookieChangeEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchCookieChangeEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnCookieChangeEvent,
@@ -940,8 +913,7 @@ void EmbeddedWorkerTestHelper::OnCookieChangeEventStub(
void EmbeddedWorkerTestHelper::OnExtendableMessageEventStub(
mojom::ExtendableMessageEventPtr event,
- mojom::ServiceWorkerEventDispatcher::DispatchExtendableMessageEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchExtendableMessageEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnExtendableMessageEvent,
@@ -949,8 +921,7 @@ void EmbeddedWorkerTestHelper::OnExtendableMessageEventStub(
}
void EmbeddedWorkerTestHelper::OnInstallEventStub(
- mojom::ServiceWorkerEventDispatcher::DispatchInstallEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchInstallEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&EmbeddedWorkerTestHelper::OnInstallEvent,
AsWeakPtr(), std::move(callback)));
@@ -959,10 +930,9 @@ void EmbeddedWorkerTestHelper::OnInstallEventStub(
void EmbeddedWorkerTestHelper::OnFetchEventStub(
int embedded_worker_id,
const network::ResourceRequest& request,
- mojom::FetchEventPreloadHandlePtr preload_handle,
+ blink::mojom::FetchEventPreloadHandlePtr preload_handle,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback) {
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnFetchEvent, AsWeakPtr(),
@@ -975,8 +945,7 @@ void EmbeddedWorkerTestHelper::OnNotificationClickEventStub(
const PlatformNotificationData& notification_data,
int action_index,
const base::Optional<base::string16>& reply,
- mojom::ServiceWorkerEventDispatcher::DispatchNotificationClickEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchNotificationClickEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnNotificationClickEvent,
@@ -987,8 +956,7 @@ void EmbeddedWorkerTestHelper::OnNotificationClickEventStub(
void EmbeddedWorkerTestHelper::OnNotificationCloseEventStub(
const std::string& notification_id,
const PlatformNotificationData& notification_data,
- mojom::ServiceWorkerEventDispatcher::DispatchNotificationCloseEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchNotificationCloseEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnNotificationCloseEvent,
@@ -998,7 +966,7 @@ void EmbeddedWorkerTestHelper::OnNotificationCloseEventStub(
void EmbeddedWorkerTestHelper::OnPushEventStub(
const PushEventPayload& payload,
- mojom::ServiceWorkerEventDispatcher::DispatchPushEventCallback callback) {
+ mojom::ServiceWorker::DispatchPushEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&EmbeddedWorkerTestHelper::OnPushEvent,
AsWeakPtr(), payload, std::move(callback)));
@@ -1006,8 +974,7 @@ void EmbeddedWorkerTestHelper::OnPushEventStub(
void EmbeddedWorkerTestHelper::OnAbortPaymentEventStub(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchAbortPaymentEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchAbortPaymentEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&EmbeddedWorkerTestHelper::OnAbortPaymentEvent,
AsWeakPtr(), std::move(response_callback),
@@ -1017,8 +984,7 @@ void EmbeddedWorkerTestHelper::OnAbortPaymentEventStub(
void EmbeddedWorkerTestHelper::OnCanMakePaymentEventStub(
payments::mojom::CanMakePaymentEventDataPtr event_data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchCanMakePaymentEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnCanMakePaymentEvent,
@@ -1029,8 +995,7 @@ void EmbeddedWorkerTestHelper::OnCanMakePaymentEventStub(
void EmbeddedWorkerTestHelper::OnPaymentRequestEventStub(
payments::mojom::PaymentRequestEventDataPtr event_data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchPaymentRequestEventCallback
- callback) {
+ mojom::ServiceWorker::DispatchPaymentRequestEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnPaymentRequestEvent,
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 609a99102b0..9204ee99207 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
@@ -20,15 +20,14 @@
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/embedded_worker.mojom.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
-#include "content/common/service_worker/service_worker_status_code.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_test_sink.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/cookies/cookie_change_dispatcher.h"
#include "net/http/http_response_info.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h"
#include "url/gurl.h"
@@ -42,7 +41,6 @@ class EmbeddedWorkerTestHelper;
class MockRenderProcessHost;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
-class ServiceWorkerDispatcherHost;
class TestBrowserContext;
struct PlatformNotificationData;
struct PushEventPayload;
@@ -61,8 +59,7 @@ struct PushEventPayload;
// methods to add their own logic/verification code.
//
// See embedded_worker_instance_unittest.cc for example usages.
-class EmbeddedWorkerTestHelper : public IPC::Sender,
- public IPC::Listener {
+class EmbeddedWorkerTestHelper {
public:
enum class Event { Install, Activate };
@@ -102,40 +99,16 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
EmbeddedWorkerTestHelper(
const base::FilePath& user_data_directory,
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter);
- ~EmbeddedWorkerTestHelper() override;
-
- // IPC::Sender implementation.
- bool Send(IPC::Message* message) override;
-
- // IPC::Listener implementation.
- bool OnMessageReceived(const IPC::Message& msg) override;
+ virtual ~EmbeddedWorkerTestHelper();
// Registers a Mojo endpoint object derived from
// MockEmbeddedWorkerInstanceClient.
void RegisterMockInstanceClient(
std::unique_ptr<MockEmbeddedWorkerInstanceClient> client);
- // Registers the dispatcher host for the process to a map managed by this test
- // helper. If there is a existing dispatcher host, it'll replace the existing
- // dispatcher host with the given one. When replacing, this should be called
- // before ServiceWorkerDispatcherHost::Init to allow the old dispatcher host
- // to destruct and remove itself from ServiceWorkerContextCore, since Init
- // adds to context core. If |dispatcher_host| is nullptr, this method just
- // removes the existing dispatcher host from the map.
- void RegisterDispatcherHost(
- int process_id,
- scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host);
-
- // Creates and registers a basic dispatcher host for the process if one
- // registered isn't already.
- void EnsureDispatcherHostForProcess(int process_id);
-
template <typename MockType, typename... Args>
MockType* CreateAndRegisterMockInstanceClient(Args&&... args);
- // IPC sink for EmbeddedWorker messages.
- IPC::TestSink* ipc_sink() { return &sink_; }
-
std::vector<Event>* dispatched_events() { return &events_; }
std::vector<std::unique_ptr<MockEmbeddedWorkerInstanceClient>>*
@@ -159,8 +132,6 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
TestBrowserContext* browser_context() { return browser_context_.get(); }
- ServiceWorkerDispatcherHost* GetDispatcherHostForProcess(int process_id);
-
base::WeakPtr<EmbeddedWorkerTestHelper> AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}
@@ -171,17 +142,21 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
return url_loader_factory_getter_.get();
}
+ // Overrides the network URLLoaderFactory for subsequent requests. Passing a
+ // null pointer will restore the default behavior.
+ void SetNetworkFactory(network::mojom::URLLoaderFactory* factory);
+
protected:
// StartWorker IPC handler routed through MockEmbeddedWorkerInstanceClient.
// This simulates behaviors in the renderer process. Binds
- // |dispatcher_request| to MockServiceWorkerEventDispatcher by default.
+ // |service_worker_request| to MockServiceWorker by default.
virtual void OnStartWorker(
int embedded_worker_id,
int64_t service_worker_version_id,
const GURL& scope,
const GURL& script_url,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -195,88 +170,75 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
// On*Event handlers. By default they just return success via
// SimulateSendReplyToBrowser.
virtual void OnActivateEvent(
- mojom::ServiceWorkerEventDispatcher::DispatchActivateEventCallback
- callback);
+ mojom::ServiceWorker::DispatchActivateEventCallback callback);
virtual void OnBackgroundFetchAbortEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchAbortEventCallback callback);
+ mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback);
virtual void OnBackgroundFetchClickEvent(
const std::string& developer_id,
mojom::BackgroundFetchState state,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchClickEventCallback callback);
+ mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback);
virtual void OnBackgroundFetchFailEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchFailEventCallback callback);
+ mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback);
virtual void OnBackgroundFetchedEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchedEventCallback callback);
+ mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback);
virtual void OnCookieChangeEvent(
const net::CanonicalCookie& cookie,
::network::mojom::CookieChangeCause cause,
- mojom::ServiceWorkerEventDispatcher::DispatchCookieChangeEventCallback
- callback);
+ mojom::ServiceWorker::DispatchCookieChangeEventCallback callback);
virtual void OnExtendableMessageEvent(
mojom::ExtendableMessageEventPtr event,
- mojom::ServiceWorkerEventDispatcher::
- DispatchExtendableMessageEventCallback callback);
+ mojom::ServiceWorker::DispatchExtendableMessageEventCallback callback);
virtual void OnInstallEvent(
- mojom::ServiceWorkerEventDispatcher::DispatchInstallEventCallback
- callback);
+ mojom::ServiceWorker::DispatchInstallEventCallback callback);
virtual void OnFetchEvent(
int embedded_worker_id,
const network::ResourceRequest& request,
- mojom::FetchEventPreloadHandlePtr preload_handle,
+ blink::mojom::FetchEventPreloadHandlePtr preload_handle,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback);
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback);
virtual void OnNotificationClickEvent(
const std::string& notification_id,
const PlatformNotificationData& notification_data,
int action_index,
const base::Optional<base::string16>& reply,
- mojom::ServiceWorkerEventDispatcher::
- DispatchNotificationClickEventCallback callback);
+ mojom::ServiceWorker::DispatchNotificationClickEventCallback callback);
virtual void OnNotificationCloseEvent(
const std::string& notification_id,
const PlatformNotificationData& notification_data,
- mojom::ServiceWorkerEventDispatcher::
- DispatchNotificationCloseEventCallback callback);
+ mojom::ServiceWorker::DispatchNotificationCloseEventCallback callback);
virtual void OnPushEvent(
const PushEventPayload& payload,
- mojom::ServiceWorkerEventDispatcher::DispatchPushEventCallback callback);
+ mojom::ServiceWorker::DispatchPushEventCallback callback);
virtual void OnAbortPaymentEvent(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchAbortPaymentEventCallback
- callback);
+ mojom::ServiceWorker::DispatchAbortPaymentEventCallback callback);
virtual void OnCanMakePaymentEvent(
payments::mojom::CanMakePaymentEventDataPtr data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
- callback);
+ mojom::ServiceWorker::DispatchCanMakePaymentEventCallback callback);
virtual void OnPaymentRequestEvent(
payments::mojom::PaymentRequestEventDataPtr data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchPaymentRequestEventCallback
- callback);
+ mojom::ServiceWorker::DispatchPaymentRequestEventCallback callback);
// These functions simulate making Mojo calls to the browser.
void SimulateWorkerReadyForInspection(int embedded_worker_id);
void SimulateWorkerScriptCached(int embedded_worker_id,
base::OnceClosure callback);
void SimulateWorkerScriptLoaded(int embedded_worker_id);
- void SimulateWorkerThreadStarted(int thread_id, int embedded_worker_id);
- void SimulateWorkerScriptEvaluated(int embedded_worker_id, bool success);
- void SimulateWorkerStarted(int embedded_worker_id);
+ void SimulateScriptEvaluationStart(int embedded_worker_id);
+ void SimulateWorkerStarted(int embedded_worker_id,
+ blink::mojom::ServiceWorkerStartStatus status,
+ int thread_id);
void SimulateWorkerStopped(int embedded_worker_id);
EmbeddedWorkerRegistry* registry();
@@ -287,7 +249,8 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
}
private:
- class MockServiceWorkerEventDispatcher;
+ class MockNetworkURLLoaderFactory;
+ class MockServiceWorker;
class MockRendererInterface;
void DidSimulateWorkerScriptCached(int embedded_worker_id,
@@ -301,79 +264,65 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
void OnResumeAfterDownloadStub(int embedded_worker_id);
void OnStopWorkerStub(int embedded_worker_id);
void OnActivateEventStub(
- mojom::ServiceWorkerEventDispatcher::DispatchActivateEventCallback
- callback);
+ mojom::ServiceWorker::DispatchActivateEventCallback callback);
void OnBackgroundFetchAbortEventStub(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchAbortEventCallback callback);
+ mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback);
void OnBackgroundFetchClickEventStub(
const std::string& developer_id,
mojom::BackgroundFetchState state,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchClickEventCallback callback);
+ mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback);
void OnBackgroundFetchFailEventStub(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchFailEventCallback callback);
+ mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback);
void OnBackgroundFetchedEventStub(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
- mojom::ServiceWorkerEventDispatcher::
- DispatchBackgroundFetchedEventCallback callback);
+ mojom::ServiceWorker::DispatchBackgroundFetchedEventCallback callback);
void OnCookieChangeEventStub(
const net::CanonicalCookie& cookie,
::network::mojom::CookieChangeCause cause,
- mojom::ServiceWorkerEventDispatcher::DispatchCookieChangeEventCallback
- callback);
+ mojom::ServiceWorker::DispatchCookieChangeEventCallback callback);
void OnExtendableMessageEventStub(
mojom::ExtendableMessageEventPtr event,
- mojom::ServiceWorkerEventDispatcher::
- DispatchExtendableMessageEventCallback callback);
+ mojom::ServiceWorker::DispatchExtendableMessageEventCallback callback);
void OnInstallEventStub(
- mojom::ServiceWorkerEventDispatcher::DispatchInstallEventCallback
- callback);
+ mojom::ServiceWorker::DispatchInstallEventCallback callback);
void OnFetchEventStub(
int embedded_worker_id,
const network::ResourceRequest& request,
- mojom::FetchEventPreloadHandlePtr preload_handle,
+ blink::mojom::FetchEventPreloadHandlePtr preload_handle,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback);
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback);
void OnNotificationClickEventStub(
const std::string& notification_id,
const PlatformNotificationData& notification_data,
int action_index,
const base::Optional<base::string16>& reply,
- mojom::ServiceWorkerEventDispatcher::
- DispatchNotificationClickEventCallback callback);
+ mojom::ServiceWorker::DispatchNotificationClickEventCallback callback);
void OnNotificationCloseEventStub(
const std::string& notification_id,
const PlatformNotificationData& notification_data,
- mojom::ServiceWorkerEventDispatcher::
- DispatchNotificationCloseEventCallback callback);
+ mojom::ServiceWorker::DispatchNotificationCloseEventCallback callback);
void OnPushEventStub(
const PushEventPayload& payload,
- mojom::ServiceWorkerEventDispatcher::DispatchPushEventCallback callback);
+ mojom::ServiceWorker::DispatchPushEventCallback callback);
void OnAbortPaymentEventStub(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchAbortPaymentEventCallback
- callback);
+ mojom::ServiceWorker::DispatchAbortPaymentEventCallback callback);
void OnCanMakePaymentEventStub(
payments::mojom::CanMakePaymentEventDataPtr data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
- callback);
+ mojom::ServiceWorker::DispatchCanMakePaymentEventCallback callback);
void OnPaymentRequestEventStub(
payments::mojom::PaymentRequestEventDataPtr data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchPaymentRequestEventCallback
- callback);
+ mojom::ServiceWorker::DispatchPaymentRequestEventCallback callback);
std::unique_ptr<TestBrowserContext> browser_context_;
std::unique_ptr<MockRenderProcessHost> render_process_host_;
@@ -381,8 +330,6 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
scoped_refptr<ServiceWorkerContextWrapper> wrapper_;
- IPC::TestSink sink_;
-
std::unique_ptr<MockRendererInterface> mock_renderer_interface_;
std::vector<std::unique_ptr<MockEmbeddedWorkerInstanceClient>>
mock_instance_clients_;
@@ -392,9 +339,6 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
int mock_render_process_id_;
int new_mock_render_process_id_;
- std::map<int /* process_id */, scoped_refptr<ServiceWorkerDispatcherHost>>
- dispatcher_hosts_;
-
std::map<int, int64_t> embedded_worker_id_service_worker_version_id_map_;
std::map<
@@ -417,6 +361,7 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
std::vector<Event> events_;
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_;
+ std::unique_ptr<MockNetworkURLLoaderFactory> default_network_loader_factory_;
base::WeakPtrFactory<EmbeddedWorkerTestHelper> weak_factory_;
diff --git a/chromium/content/browser/service_worker/service_worker_browsertest.cc b/chromium/content/browser/service_worker/service_worker_browsertest.cc
index c12bec86b88..d8275ba30f8 100644
--- a/chromium/content/browser/service_worker/service_worker_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_browsertest.cc
@@ -43,13 +43,10 @@
#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_type_converters.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/service_worker/service_worker_messages.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/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/content_browser_client.h"
@@ -82,12 +79,14 @@
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/url_request/url_request_filter.h"
-#include "net/url_request/url_request_interceptor.h"
#include "net/url_request/url_request_test_job.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_data_snapshot.h"
#include "storage/browser/blob/blob_reader.h"
#include "storage/browser/blob/blob_storage_context.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_type_converters.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -104,7 +103,7 @@ const int kV8CacheTimeStampDataSize =
sizeof(uint32_t) + sizeof(uint32_t) + sizeof(double);
struct FetchResult {
- ServiceWorkerStatusCode status;
+ blink::ServiceWorkerStatusCode status;
ServiceWorkerFetchDispatcher::FetchEventResult result;
ServiceWorkerResponse response;
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
@@ -156,8 +155,8 @@ base::OnceClosure CreatePrepareReceiver(bool* is_prepared) {
void ReceiveFindRegistrationStatus(
BrowserThread::ID run_quit_thread,
base::OnceClosure quit,
- ServiceWorkerStatusCode* out_status,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode* out_status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
*out_status = status;
if (!quit.is_null())
@@ -167,7 +166,7 @@ void ReceiveFindRegistrationStatus(
ServiceWorkerStorage::FindRegistrationCallback CreateFindRegistrationReceiver(
BrowserThread::ID run_quit_thread,
base::OnceClosure quit,
- ServiceWorkerStatusCode* status) {
+ blink::ServiceWorkerStatusCode* status) {
return base::BindOnce(&ReceiveFindRegistrationStatus, run_quit_thread,
std::move(quit), status);
}
@@ -206,6 +205,8 @@ class WorkerActivatedObserver
const ServiceWorkerVersion* version = context_->GetLiveVersion(version_id);
if (version->status() == ServiceWorkerVersion::ACTIVATED) {
context_->RemoveObserver(this);
+ version_id_ = version_id;
+ registration_id_ = version->registration_id();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WorkerActivatedObserver::Quit, this));
@@ -213,12 +214,18 @@ class WorkerActivatedObserver
}
void Wait() { run_loop_.Run(); }
+ int64_t registration_id() { return registration_id_; }
+ int64_t version_id() { return version_id_; }
+
private:
friend class base::RefCountedThreadSafe<WorkerActivatedObserver>;
~WorkerActivatedObserver() override {}
void InitOnIOThread() { context_->AddObserver(this); }
void Quit() { run_loop_.Quit(); }
+ int64_t registration_id_ = blink::mojom::kInvalidServiceWorkerRegistrationId;
+ int64_t version_id_ = blink::mojom::kInvalidServiceWorkerVersionId;
+
base::RunLoop run_loop_;
ServiceWorkerContextWrapper* context_;
DISALLOW_COPY_AND_ASSIGN(WorkerActivatedObserver);
@@ -290,52 +297,6 @@ VerifySaveDataNotInAccessControlRequestHeader(
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
-// to do that. This interceptor injects headers that give the import
-// an experiration far in the future.
-class LongLivedResourceInterceptor : public net::URLRequestInterceptor {
- public:
- explicit LongLivedResourceInterceptor(const std::string& body)
- : body_(body) {}
- ~LongLivedResourceInterceptor() override {}
-
- // net::URLRequestInterceptor implementation
- net::URLRequestJob* MaybeInterceptRequest(
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const override {
- const char kHeaders[] =
- "HTTP/1.1 200 OK\n"
- "Content-Type: text/javascript\n"
- "Expires: Thu, 1 Jan 2100 20:00:00 GMT\n"
- "\n";
- std::string headers(kHeaders, arraysize(kHeaders));
- return new net::URLRequestTestJob(
- request, network_delegate, headers, body_, true);
- }
-
- private:
- std::string body_;
- DISALLOW_COPY_AND_ASSIGN(LongLivedResourceInterceptor);
-};
-
-void CreateLongLivedResourceInterceptors(
- const GURL& worker_url, const GURL& import_url) {
- ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
- std::unique_ptr<net::URLRequestInterceptor> interceptor;
-
- interceptor.reset(new LongLivedResourceInterceptor(
- "importScripts('long_lived_import.js');"));
- net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
- worker_url, std::move(interceptor));
-
- interceptor.reset(new LongLivedResourceInterceptor(
- "// the imported script does nothing"));
- net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
- import_url, std::move(interceptor));
-}
-
void CountScriptResources(
ServiceWorkerContextWrapper* wrapper,
const GURL& scope,
@@ -437,6 +398,24 @@ net::HttpResponseInfo CreateHttpResponseInfo() {
return info;
}
+// Returns a unique script for each request, to test service worker update.
+std::unique_ptr<net::test_server::HttpResponse> RequestHandlerForUpdateWorker(
+ const net::test_server::HttpRequest& request) {
+ static int counter = 0;
+
+ if (request.relative_url != "/service_worker/update_worker.js")
+ return std::unique_ptr<net::test_server::HttpResponse>();
+
+ auto http_response = std::make_unique<net::test_server::BasicHttpResponse>();
+ http_response->set_code(net::HTTP_OK);
+ http_response->set_content(
+ base::StringPrintf("// empty script. counter = %d\n", counter++));
+ http_response->set_content_type("text/javascript");
+ // Use a large max-age to test the browser cache.
+ http_response->AddCustomHeader("Cache-Control", "max-age=31536000");
+ return http_response;
+}
+
const char kNavigationPreloadAbortError[] =
"NetworkError: The service worker navigation preload request was cancelled "
"before 'preloadResponse' settled. If you intend to use 'preloadResponse', "
@@ -546,8 +525,6 @@ class ConsoleMessageContextObserver
// ServiceWorkerContextCoreObserver overrides.
void OnReportConsoleMessage(int64_t version_id,
- int process_id,
- int thread_id,
const ConsoleMessage& console_message) override {
messages_.push_back(console_message.message);
if (messages_.size() == expected_message_count_) {
@@ -588,25 +565,28 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
~ServiceWorkerVersionBrowserTest() override {}
void TearDownOnIOThread() override {
+ // Ensure that these resources are released while the IO thread still
+ // exists.
registration_ = nullptr;
version_ = nullptr;
+ blob_context_ = nullptr;
remote_endpoints_.clear();
}
void InstallTestHelper(const std::string& worker_url,
- ServiceWorkerStatusCode expected_status) {
+ blink::ServiceWorkerStatusCode expected_status) {
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread,
base::Unretained(this), worker_url));
// Dispatch install on a worker.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop install_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&self::InstallOnIOThread, base::Unretained(this),
install_run_loop.QuitClosure(), &status));
install_run_loop.Run();
- ASSERT_EQ(expected_status, status);
+ ASSERT_EQ(expected_status, status.value());
// Stop the worker.
base::RunLoop stop_run_loop;
@@ -617,17 +597,16 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
stop_run_loop.Run();
}
- void ActivateTestHelper(
- const std::string& worker_url,
- ServiceWorkerStatusCode expected_status) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ void ActivateTestHelper(const std::string& worker_url,
+ blink::ServiceWorkerStatusCode expected_status) {
+ base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&self::ActivateOnIOThread, base::Unretained(this),
run_loop.QuitClosure(), &status));
run_loop.Run();
- ASSERT_EQ(expected_status, status);
+ ASSERT_EQ(expected_status, status.value());
}
void FetchOnRegisteredWorker(
@@ -638,7 +617,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
shell()->web_contents()->GetBrowserContext());
bool prepare_result = false;
FetchResult fetch_result;
- fetch_result.status = SERVICE_WORKER_ERROR_FAILED;
+ fetch_result.status = blink::ServiceWorkerStatusCode::kErrorFailed;
base::RunLoop fetch_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
@@ -650,7 +629,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
*result = fetch_result.result;
*response = fetch_result.response;
*blob_data_handle = std::move(fetch_result.blob_data_handle);
- ASSERT_EQ(SERVICE_WORKER_OK, fetch_result.status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, fetch_result.status);
}
void SetUpRegistrationOnIOThread(const std::string& worker_url) {
@@ -711,16 +690,16 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
registration_->ActivateWaitingVersionWhenReady();
}
- void StartWorker(ServiceWorkerStatusCode expected_status) {
+ void StartWorker(blink::ServiceWorkerStatusCode expected_status) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop start_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
start_run_loop.QuitClosure(), &status));
start_run_loop.Run();
- ASSERT_EQ(expected_status, status);
+ ASSERT_EQ(expected_status, status.value());
}
void StopWorker() {
@@ -734,27 +713,42 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
}
void StoreRegistration(int64_t version_id,
- ServiceWorkerStatusCode expected_status) {
+ blink::ServiceWorkerStatusCode expected_status) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop store_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&self::StoreOnIOThread, base::Unretained(this),
store_run_loop.QuitClosure(), &status, version_id));
store_run_loop.Run();
- ASSERT_EQ(expected_status, status);
+ ASSERT_EQ(expected_status, status.value());
RunOnIOThread(
base::BindOnce(&self::NotifyDoneInstallingRegistrationOnIOThread,
- base::Unretained(this), status));
+ base::Unretained(this), status.value()));
+ }
+
+ void UpdateRegistration(int64_t registration_id,
+ blink::ServiceWorkerStatusCode* out_status,
+ bool* out_update_found) {
+ base::RunLoop update_run_loop;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &self::UpdateOnIOThread, base::Unretained(this), registration_id,
+ base::BindOnce(
+ &self::ReceiveUpdateResultOnIOThread, base::Unretained(this),
+ update_run_loop.QuitClosure(), out_status, out_update_found)));
+ update_run_loop.Run();
}
void FindRegistrationForId(int64_t id,
const GURL& origin,
- ServiceWorkerStatusCode expected_status) {
+ blink::ServiceWorkerStatusCode expected_status) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
base::RunLoop run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
@@ -766,7 +760,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
}
void FindRegistrationForIdOnIOThread(base::OnceClosure done,
- ServiceWorkerStatusCode* result,
+ blink::ServiceWorkerStatusCode* result,
int64_t id,
const GURL& origin) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -777,7 +771,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
}
void NotifyDoneInstallingRegistrationOnIOThread(
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
wrapper()->context()->storage()->NotifyDoneInstallingRegistration(
registration_.get(), version_.get(), status);
@@ -789,15 +783,16 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
}
void StartOnIOThread(const base::Closure& done,
- ServiceWorkerStatusCode* result) {
+ base::Optional<blink::ServiceWorkerStatusCode>* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
version_->SetMainScriptHttpResponseInfo(CreateHttpResponseInfo());
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiver(BrowserThread::UI, done, result));
}
- void InstallOnIOThread(const base::Closure& done,
- ServiceWorkerStatusCode* result) {
+ void InstallOnIOThread(
+ const base::RepeatingClosure& done,
+ base::Optional<blink::ServiceWorkerStatusCode>* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
version_->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::INSTALL,
@@ -807,22 +802,22 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
void DispatchInstallEventOnIOThread(
const base::Closure& done,
- ServiceWorkerStatusCode* result,
- ServiceWorkerStatusCode start_worker_status) {
+ base::Optional<blink::ServiceWorkerStatusCode>* result,
+ blink::ServiceWorkerStatusCode start_worker_status) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ASSERT_EQ(SERVICE_WORKER_OK, start_worker_status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, start_worker_status);
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
int request_id =
version_->StartRequest(ServiceWorkerMetrics::EventType::INSTALL,
CreateReceiver(BrowserThread::UI, done, result));
- version_->event_dispatcher()->DispatchInstallEvent(
+ version_->endpoint()->DispatchInstallEvent(
base::BindOnce(&self::ReceiveInstallEventOnIOThread,
base::Unretained(this), done, result, request_id));
}
void ReceiveInstallEventOnIOThread(
const base::Closure& done,
- ServiceWorkerStatusCode* out_result,
+ base::Optional<blink::ServiceWorkerStatusCode>* out_result,
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
bool has_fetch_handler,
@@ -835,13 +830,13 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
? ServiceWorkerVersion::FetchHandlerExistence::EXISTS
: ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST);
- *out_result = mojo::ConvertTo<ServiceWorkerStatusCode>(status);
+ *out_result = mojo::ConvertTo<blink::ServiceWorkerStatusCode>(status);
if (!done.is_null())
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done);
}
void StoreOnIOThread(const base::Closure& done,
- ServiceWorkerStatusCode* result,
+ base::Optional<blink::ServiceWorkerStatusCode>* result,
int64_t version_id) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
ServiceWorkerVersion* version =
@@ -851,8 +846,9 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
CreateReceiver(BrowserThread::UI, done, result));
}
- void ActivateOnIOThread(const base::Closure& done,
- ServiceWorkerStatusCode* result) {
+ void ActivateOnIOThread(
+ const base::RepeatingClosure& done,
+ base::Optional<blink::ServiceWorkerStatusCode>* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
version_->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::ACTIVATE,
@@ -862,19 +858,45 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
void DispatchActivateEventOnIOThread(
const base::Closure& done,
- ServiceWorkerStatusCode* result,
- ServiceWorkerStatusCode start_worker_status) {
+ base::Optional<blink::ServiceWorkerStatusCode>* result,
+ blink::ServiceWorkerStatusCode start_worker_status) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ASSERT_EQ(SERVICE_WORKER_OK, start_worker_status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, start_worker_status);
version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
registration_->SetActiveVersion(version_.get());
int request_id =
version_->StartRequest(ServiceWorkerMetrics::EventType::INSTALL,
CreateReceiver(BrowserThread::UI, done, result));
- version_->event_dispatcher()->DispatchActivateEvent(
+ version_->endpoint()->DispatchActivateEvent(
version_->CreateSimpleEventCallback(request_id));
}
+ void UpdateOnIOThread(int registration_id,
+ ServiceWorkerContextCore::UpdateCallback callback) {
+ ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ServiceWorkerRegistration* registration =
+ wrapper()->context()->GetLiveRegistration(registration_id);
+ ASSERT_TRUE(registration);
+ wrapper()->context()->UpdateServiceWorker(
+ registration, false /* force_bypass_cache */,
+ false /* skip_script_comparison */, std::move(callback));
+ }
+
+ void ReceiveUpdateResultOnIOThread(const base::RepeatingClosure& done_on_ui,
+ blink::ServiceWorkerStatusCode* out_status,
+ bool* out_update_found,
+ blink::ServiceWorkerStatusCode status,
+ const std::string& status_message,
+ int64_t registration_id) {
+ ServiceWorkerRegistration* registration =
+ wrapper()->context()->GetLiveRegistration(registration_id);
+ DCHECK(registration);
+
+ *out_status = status;
+ *out_update_found = !!registration->installing_version();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_on_ui);
+ }
+
void FetchOnIOThread(const base::Closure& done,
bool* prepare_result,
FetchResult* result) {
@@ -897,6 +919,40 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
fetch_dispatcher_->Run();
}
+ base::Time GetLastUpdateCheck(int64_t registration_id) {
+ base::Time last_update_time;
+ base::RunLoop time_run_loop;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&self::GetLastUpdateCheckOnIOThread,
+ base::Unretained(this), registration_id,
+ &last_update_time, time_run_loop.QuitClosure()));
+ time_run_loop.Run();
+ return last_update_time;
+ }
+
+ void GetLastUpdateCheckOnIOThread(int64_t registration_id,
+ base::Time* out_time,
+ const base::RepeatingClosure& done_on_ui) {
+ ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ServiceWorkerRegistration* registration =
+ wrapper()->context()->GetLiveRegistration(registration_id);
+ ASSERT_TRUE(registration);
+ *out_time = registration->last_update_check();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_on_ui);
+ }
+
+ void SetLastUpdateCheckOnIOThread(int64_t registration_id,
+ base::Time last_update_time,
+ const base::RepeatingClosure& done_on_ui) {
+ ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ServiceWorkerRegistration* registration =
+ wrapper()->context()->GetLiveRegistration(registration_id);
+ ASSERT_TRUE(registration);
+ registration->set_last_update_check(last_update_time);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_on_ui);
+ }
+
// 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.
@@ -904,7 +960,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
const base::Closure& quit,
ChromeBlobStorageContext* blob_context,
FetchResult* out_result,
- ServiceWorkerStatusCode actual_status,
+ blink::ServiceWorkerStatusCode actual_status,
ServiceWorkerFetchDispatcher::FetchEventResult actual_result,
const ServiceWorkerResponse& actual_response,
blink::mojom::ServiceWorkerStreamHandlePtr /* stream */,
@@ -954,14 +1010,14 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
"/service_worker/worker.js"));
// Start a worker.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop start_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
start_run_loop.QuitClosure(), &status));
start_run_loop.Run();
- ASSERT_EQ(SERVICE_WORKER_OK, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
// Stop the worker.
base::RunLoop stop_run_loop;
@@ -981,18 +1037,18 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
base::Unretained(this),
"/service_worker/worker.js"));
// Start a worker.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop start_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
start_run_loop.QuitClosure(), &status));
start_run_loop.Run();
- ASSERT_EQ(SERVICE_WORKER_OK, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
// Expect no PageVisits count.
EXPECT_EQ(nullptr, base::StatisticsRecorder::FindHistogram(
- "Blink.UseCounter.Features_Legacy"));
+ "Blink.UseCounter.Features"));
// Stop the worker.
base::RunLoop stop_run_loop;
@@ -1003,7 +1059,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
stop_run_loop.Run();
// Expect no PageVisits count.
EXPECT_EQ(nullptr, base::StatisticsRecorder::FindHistogram(
- "Blink.UseCounter.Features_Legacy"));
+ "Blink.UseCounter.Features"));
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) {
@@ -1013,7 +1069,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) {
"/service_worker/nonexistent.js"));
// Start a worker for nonexistent URL.
- StartWorker(SERVICE_WORKER_ERROR_NETWORK);
+ StartWorker(blink::ServiceWorkerStatusCode::kErrorNetwork);
}
#if defined(ANDROID)
@@ -1040,10 +1096,11 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
version_->script_cache_map()->SetResources(records);
// Store the registration.
- StoreRegistration(version_->version_id(), SERVICE_WORKER_OK);
+ StoreRegistration(version_->version_id(),
+ blink::ServiceWorkerStatusCode::kOk);
// Start the worker. We'll fail to read the resource.
- StartWorker(SERVICE_WORKER_ERROR_DISK_CACHE);
+ StartWorker(blink::ServiceWorkerStatusCode::kErrorDiskCache);
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
// The registration should be deleted from storage since the broken worker was
@@ -1052,15 +1109,17 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
base::Unretained(this), registration_->id()));
FindRegistrationForId(registration_->id(),
registration_->pattern().GetOrigin(),
- SERVICE_WORKER_ERROR_NOT_FOUND);
+ blink::ServiceWorkerStatusCode::kErrorNotFound);
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
ReadResourceFailure_WaitingWorker) {
StartServerAndNavigateToSetup();
// Create a registration and active version.
- InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
- ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
+ InstallTestHelper("/service_worker/worker.js",
+ blink::ServiceWorkerStatusCode::kOk);
+ ActivateTestHelper("/service_worker/worker.js",
+ blink::ServiceWorkerStatusCode::kOk);
ASSERT_TRUE(registration_->active_version());
// Give the version a controllee.
@@ -1079,12 +1138,12 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
ServiceWorkerDatabase::ResourceRecord(31, version_->script_url(), 100)};
registration_->waiting_version()->script_cache_map()->SetResources(records);
StoreRegistration(registration_->waiting_version()->version_id(),
- SERVICE_WORKER_OK);
+ blink::ServiceWorkerStatusCode::kOk);
// Start the broken worker. We'll fail to read from disk and the worker should
// be doomed.
StopWorker(); // in case it's already running
- StartWorker(SERVICE_WORKER_ERROR_DISK_CACHE);
+ StartWorker(blink::ServiceWorkerStatusCode::kErrorDiskCache);
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
// The registration should still be in storage since the waiting worker was
@@ -1093,25 +1152,27 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
base::Unretained(this), registration_->id()));
FindRegistrationForId(registration_->id(),
registration_->pattern().GetOrigin(),
- SERVICE_WORKER_OK);
+ blink::ServiceWorkerStatusCode::kOk);
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) {
StartServerAndNavigateToSetup();
- InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
+ InstallTestHelper("/service_worker/worker.js",
+ blink::ServiceWorkerStatusCode::kOk);
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
InstallWithWaitUntil_Fulfilled) {
StartServerAndNavigateToSetup();
InstallTestHelper("/service_worker/worker_install_fulfilled.js",
- SERVICE_WORKER_OK);
+ blink::ServiceWorkerStatusCode::kOk);
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
InstallWithFetchHandler) {
StartServerAndNavigateToSetup();
- InstallTestHelper("/service_worker/fetch_event.js", SERVICE_WORKER_OK);
+ InstallTestHelper("/service_worker/fetch_event.js",
+ blink::ServiceWorkerStatusCode::kOk);
EXPECT_EQ(ServiceWorkerVersion::FetchHandlerExistence::EXISTS,
version_->fetch_handler_existence());
}
@@ -1119,7 +1180,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
InstallWithoutFetchHandler) {
StartServerAndNavigateToSetup();
- InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
+ InstallTestHelper("/service_worker/worker.js",
+ blink::ServiceWorkerStatusCode::kOk);
EXPECT_EQ(ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST,
version_->fetch_handler_existence());
}
@@ -1131,30 +1193,35 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
embedded_test_server()->RegisterRequestHandler(
base::Bind(&VerifyServiceWorkerHeaderInRequest));
StartServerAndNavigateToSetup();
- InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK);
+ InstallTestHelper("/service_worker/generated_sw.js",
+ blink::ServiceWorkerStatusCode::kOk);
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
Activate_NoEventListener) {
StartServerAndNavigateToSetup();
- InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
- ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
+ InstallTestHelper("/service_worker/worker.js",
+ blink::ServiceWorkerStatusCode::kOk);
+ ActivateTestHelper("/service_worker/worker.js",
+ blink::ServiceWorkerStatusCode::kOk);
ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
StartServerAndNavigateToSetup();
InstallTestHelper("/service_worker/worker_activate_rejected.js",
- SERVICE_WORKER_OK);
- ActivateTestHelper("/service_worker/worker_activate_rejected.js",
- SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED);
+ blink::ServiceWorkerStatusCode::kOk);
+ ActivateTestHelper(
+ "/service_worker/worker_activate_rejected.js",
+ blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected);
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
InstallWithWaitUntil_Rejected) {
StartServerAndNavigateToSetup();
- InstallTestHelper("/service_worker/worker_install_rejected.js",
- SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED);
+ InstallTestHelper(
+ "/service_worker/worker_install_rejected.js",
+ blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected);
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
@@ -1170,14 +1237,15 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
&console_listener));
// Dispatch install on a worker.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop install_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&self::InstallOnIOThread, base::Unretained(this),
install_run_loop.QuitClosure(), &status));
install_run_loop.Run();
- ASSERT_EQ(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected,
+ status.value());
const base::string16 expected =
base::ASCIIToUTF16("Rejecting oninstall event");
@@ -1193,7 +1261,7 @@ class WaitForLoaded : public EmbeddedWorkerInstance::Listener {
public:
explicit WaitForLoaded(const base::Closure& quit) : quit_(quit) {}
- void OnThreadStarted() override {
+ void OnScriptEvaluationStart() override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_);
}
@@ -1209,7 +1277,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
"/service_worker/while_true_worker.js"));
// Start a worker, waiting until the script is loaded.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop start_run_loop;
base::RunLoop load_run_loop;
WaitForLoaded wait_for_load(load_run_loop.QuitClosure());
@@ -1226,7 +1294,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
&wait_for_load));
// The script has loaded but start has not completed yet.
- ASSERT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
+ ASSERT_FALSE(status);
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
// Simulate execution timeout. Use a delay to prevent killing the worker
@@ -1236,7 +1304,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
base::TimeDelta::FromMilliseconds(100));
start_run_loop.Run();
- EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout, status.value());
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
@@ -1246,14 +1314,14 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
"/service_worker/while_true_in_install_worker.js"));
// Start a worker.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop start_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
start_run_loop.QuitClosure(), &status));
start_run_loop.Run();
- ASSERT_EQ(SERVICE_WORKER_OK, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
// Dispatch an event.
base::RunLoop install_run_loop;
@@ -1271,7 +1339,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
// 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);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected,
+ status.value());
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
@@ -1279,8 +1348,10 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
ServiceWorkerFetchDispatcher::FetchEventResult result;
ServiceWorkerResponse response;
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
- InstallTestHelper("/service_worker/fetch_event.js", SERVICE_WORKER_OK);
- ActivateTestHelper("/service_worker/fetch_event.js", SERVICE_WORKER_OK);
+ InstallTestHelper("/service_worker/fetch_event.js",
+ blink::ServiceWorkerStatusCode::kOk);
+ ActivateTestHelper("/service_worker/fetch_event.js",
+ blink::ServiceWorkerStatusCode::kOk);
FetchOnRegisteredWorker(&result, &response, &blob_data_handle);
ASSERT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
@@ -1307,9 +1378,9 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
const base::Time start_time(base::Time::Now());
InstallTestHelper("/service_worker/fetch_event_response_via_cache.js",
- SERVICE_WORKER_OK);
+ blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper("/service_worker/fetch_event_response_via_cache.js",
- SERVICE_WORKER_OK);
+ blink::ServiceWorkerStatusCode::kOk);
FetchOnRegisteredWorker(&result, &response1, &blob_data_handle);
ASSERT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
@@ -1337,9 +1408,9 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
ServiceWorkerResponse response;
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
InstallTestHelper("/service_worker/fetch_event_rejected.js",
- SERVICE_WORKER_OK);
+ blink::ServiceWorkerStatusCode::kOk);
ActivateTestHelper("/service_worker/fetch_event_rejected.js",
- SERVICE_WORKER_OK);
+ blink::ServiceWorkerStatusCode::kOk);
ConsoleListener console_listener;
RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver,
@@ -1366,6 +1437,82 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
ASSERT_FALSE(blob_data_handle);
}
+// Tests that the browser cache is bypassed on update checks after 24 hours
+// elapsed since the last update check that accessed network.
+//
+// Due to the nature of what this is testing, this test depends on the system
+// clock being reasonable during the test. So it might break on daylight savings
+// leap or something:
+// https://groups.google.com/a/chromium.org/d/msg/chromium-dev/C3EvKPrb0XM/4Jv02SpNYncJ
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+ UpdateBypassesCacheAfter24Hours) {
+ const char kScope[] = "/service_worker/handle_fetch.html";
+ const char kWorkerUrl[] = "/service_worker/update_worker.js";
+
+ // Tell the server to return a new script for each `update_worker.js` request.
+ embedded_test_server()->RegisterRequestHandler(
+ base::BindRepeating(&RequestHandlerForUpdateWorker));
+ StartServerAndNavigateToSetup();
+
+ // Register a service worker.
+
+ // Make options. Set to kAll so updating exercises the browser cache.
+ blink::mojom::ServiceWorkerRegistrationOptions options(
+ embedded_test_server()->GetURL(kScope),
+ blink::mojom::ServiceWorkerUpdateViaCache::kAll);
+
+ // Register and wait for activation.
+ auto observer = base::MakeRefCounted<WorkerActivatedObserver>(wrapper());
+ observer->Init();
+ public_context()->RegisterServiceWorker(
+ embedded_test_server()->GetURL(kWorkerUrl), options,
+ base::BindOnce(&ExpectResultAndRun, true, base::DoNothing()));
+ observer->Wait();
+ int64_t registration_id = observer->registration_id();
+
+ // The registration's last update time should be non-null.
+ base::Time last_update_time = GetLastUpdateCheck(registration_id);
+ EXPECT_NE(base::Time(), last_update_time);
+
+ // Try to update. The request should hit the browser cache so no update should
+ // be found.
+ {
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
+ bool update_found = true;
+ UpdateRegistration(registration_id, &status, &update_found);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
+ EXPECT_FALSE(update_found);
+ }
+ // The last update time should be unchanged.
+ EXPECT_EQ(last_update_time, GetLastUpdateCheck(registration_id));
+
+ // Set the last update time far in the past.
+ {
+ last_update_time = base::Time::Now() - base::TimeDelta::FromHours(24);
+ base::RunLoop time_run_loop;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&self::SetLastUpdateCheckOnIOThread,
+ base::Unretained(this), registration_id,
+ last_update_time, time_run_loop.QuitClosure()));
+ time_run_loop.Run();
+ }
+
+ // Try to update again. The browser cache should be bypassed so the update
+ // should be found.
+ {
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
+ bool update_found = false;
+ UpdateRegistration(registration_id, &status, &update_found);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
+ EXPECT_TRUE(update_found);
+ }
+ // The last update time should be bumped.
+ EXPECT_LT(last_update_time, GetLastUpdateCheck(registration_id));
+}
+
class MockContentBrowserClient : public TestContentBrowserClient {
public:
MockContentBrowserClient()
@@ -1398,7 +1545,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithSaveData) {
ContentBrowserClient* old_client =
SetBrowserClientForTesting(&content_browser_client);
shell()->web_contents()->GetRenderViewHost()->OnWebkitPreferencesChanged();
- InstallTestHelper("/service_worker/fetch_in_install.js", SERVICE_WORKER_OK);
+ InstallTestHelper("/service_worker/fetch_in_install.js",
+ blink::ServiceWorkerStatusCode::kOk);
SetBrowserClientForTesting(old_client);
}
@@ -1412,7 +1560,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
ContentBrowserClient* old_client =
SetBrowserClientForTesting(&content_browser_client);
shell()->web_contents()->GetRenderViewHost()->OnWebkitPreferencesChanged();
- InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK);
+ InstallTestHelper("/service_worker/generated_sw.js",
+ blink::ServiceWorkerStatusCode::kOk);
SetBrowserClientForTesting(old_client);
}
@@ -1423,7 +1572,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithoutSaveData) {
MockContentBrowserClient content_browser_client;
ContentBrowserClient* old_client =
SetBrowserClientForTesting(&content_browser_client);
- InstallTestHelper("/service_worker/fetch_in_install.js", SERVICE_WORKER_OK);
+ InstallTestHelper("/service_worker/fetch_in_install.js",
+ blink::ServiceWorkerStatusCode::kOk);
SetBrowserClientForTesting(old_client);
}
@@ -2038,6 +2188,19 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NetworkError) {
IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
CanceledByInterceptor) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ // This is a test for a ResourceDispatcherHost interceptor cancelling the
+ // Navigation Preload request. The analogue for the
+ // NetworkService/ServiceWorker*Loader code path would be throttles, but
+ // these don't see Navigation Preload (crbug.com/825717) and there is no
+ // plan to allow them to, so just skip this test.
+
+ // This has to be called so the EmbeddedTestServer IO Thread is created,
+ // otherwise we crash on destruction.
+ embedded_test_server()->StartAcceptingConnections();
+ return;
+ }
+
content::ResourceDispatcherHost::Get()->RegisterInterceptor(
kNavigationPreloadHeaderName, "",
base::Bind(&CancellingInterceptorCallback));
@@ -2294,6 +2457,20 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
// correctly.
IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
RespondWithNavigationPreloadWithMimeSniffing) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ // When S13nSW/NetworkService is enabled, we don't do MIME sniffing
+ // (https://crbug.com/771118), so just skip this test. Also, this test was
+ // meant to test an internal quirk of MimeSniffingResourceHandler, which
+ // might not make sense in the NetworkService implementation anyway. If we
+ // want a behavior test for MIME sniffing for navigation preload, it can be
+ // an end-to-end layout test instead.
+
+ // This has to be called so the EmbeddedTestServer IO Thread is created,
+ // otherwise we crash on destruction.
+ embedded_test_server()->StartAcceptingConnections();
+ return;
+ }
+
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
const char kPage[] = "<title>PASS</title>Hello world.";
@@ -2405,15 +2582,9 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ImportsBustMemcache) {
StartServerAndNavigateToSetup();
const char kScopeUrl[] = "/service_worker/imports_bust_memcache_scope/";
const char kPageUrl[] = "/service_worker/imports_bust_memcache.html";
- const char kScriptUrl[] = "/service_worker/worker_with_one_import.js";
- const char kImportUrl[] = "/service_worker/long_lived_import.js";
const base::string16 kOKTitle(base::ASCIIToUTF16("OK"));
const base::string16 kFailTitle(base::ASCIIToUTF16("FAIL"));
- RunOnIOThread(base::BindOnce(&CreateLongLivedResourceInterceptors,
- embedded_test_server()->GetURL(kScriptUrl),
- embedded_test_server()->GetURL(kImportUrl)));
-
TitleWatcher title_watcher(shell()->web_contents(), kOKTitle);
title_watcher.AlsoWaitForTitle(kFailTitle);
NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl));
@@ -2429,8 +2600,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ImportsBustMemcache) {
EXPECT_EQ(kExpectedNumResources, num_resources);
}
-// A listener that waits for the version to stop.
-class StopObserver : public ServiceWorkerVersion::Listener {
+// An observer that waits for the version to stop.
+class StopObserver : public ServiceWorkerVersion::Observer {
public:
explicit StopObserver(const base::Closure& quit_closure)
: quit_closure_(quit_closure) {}
@@ -2450,19 +2621,19 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, RendererCrash) {
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread,
base::Unretained(this),
"/service_worker/worker.js"));
- StartWorker(SERVICE_WORKER_OK);
+ StartWorker(blink::ServiceWorkerStatusCode::kOk);
// Crash the renderer process. The version should stop.
base::RunLoop run_loop;
StopObserver observer(run_loop.QuitClosure());
- RunOnIOThread(base::BindOnce(&ServiceWorkerVersion::AddListener,
+ RunOnIOThread(base::BindOnce(&ServiceWorkerVersion::AddObserver,
base::Unretained(version_.get()), &observer));
shell()->web_contents()->GetMainFrame()->GetProcess()->Shutdown(
content::RESULT_CODE_KILLED);
run_loop.Run();
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
- RunOnIOThread(base::BindOnce(&ServiceWorkerVersion::RemoveListener,
+ RunOnIOThread(base::BindOnce(&ServiceWorkerVersion::RemoveObserver,
base::Unretained(version_.get()), &observer));
}
@@ -2471,7 +2642,7 @@ class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest {
using self = ServiceWorkerBlackBoxBrowserTest;
void FindRegistrationOnIO(const GURL& document_url,
- ServiceWorkerStatusCode* status,
+ blink::ServiceWorkerStatusCode* status,
const base::Closure& continuation) {
wrapper()->FindReadyRegistrationForDocument(
document_url,
@@ -2480,13 +2651,13 @@ class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest {
}
void FindRegistrationOnIO2(
- ServiceWorkerStatusCode* out_status,
+ blink::ServiceWorkerStatusCode* out_status,
const base::Closure& continuation,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
*out_status = status;
if (!registration.get())
- EXPECT_NE(SERVICE_WORKER_OK, status);
+ EXPECT_NE(blink::ServiceWorkerStatusCode::kOk, status);
continuation.Run();
}
};
@@ -2570,12 +2741,13 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, Registration) {
// Should not be able to find it.
{
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
RunOnIOThread(base::Bind(
&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO,
base::Unretained(this),
embedded_test_server()->GetURL("/service_worker/empty.html"), &status));
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound, status);
}
}
@@ -2626,7 +2798,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerSitePerProcessTest,
class ServiceWorkerVersionBrowserV8CacheTest
: public ServiceWorkerVersionBrowserTest,
- public ServiceWorkerVersion::Listener {
+ public ServiceWorkerVersion::Observer {
public:
using self = ServiceWorkerVersionBrowserV8CacheTest;
ServiceWorkerVersionBrowserV8CacheTest() {
@@ -2635,18 +2807,18 @@ class ServiceWorkerVersionBrowserV8CacheTest
}
~ServiceWorkerVersionBrowserV8CacheTest() override {
if (version_)
- version_->RemoveListener(this);
+ version_->RemoveObserver(this);
}
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kV8CacheOptions, "code");
}
void SetUpRegistrationAndListenerOnIOThread(const std::string& worker_url) {
SetUpRegistrationOnIOThread(worker_url);
- version_->AddListener(this);
+ version_->AddObserver(this);
}
protected:
- // ServiceWorkerVersion::Listener overrides
+ // ServiceWorkerVersion::Observer overrides
void OnCachedMetadataUpdated(ServiceWorkerVersion* version,
size_t size) override {
metadata_size_ = size;
@@ -2671,7 +2843,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest, Restart) {
cache_updated_closure_ = cached_metadata_run_loop.QuitClosure();
// Start a worker.
- StartWorker(SERVICE_WORKER_OK);
+ StartWorker(blink::ServiceWorkerStatusCode::kOk);
// Wait for the metadata to be stored. This run loop should finish when
// OnCachedMetadataUpdated() is called.
@@ -2688,14 +2860,14 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest, Restart) {
base::RunLoop cached_metadata_run_loop;
cache_updated_closure_ = cached_metadata_run_loop.QuitClosure();
// Restart the worker.
- StartWorker(SERVICE_WORKER_OK);
+ StartWorker(blink::ServiceWorkerStatusCode::kOk);
// Wait for the matadata to be stored. This run loop should finish when
// OnCachedMetadataUpdated() is called.
cached_metadata_run_loop.Run();
}
// The V8 code cache should be stored to the storage. It must have size
- // greater than 12 bytes.
+ // greater than 16 bytes.
EXPECT_GT(static_cast<int>(metadata_size_), kV8CacheTimeStampDataSize);
// Stop the worker.
@@ -2704,7 +2876,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest, Restart) {
class ServiceWorkerVersionBrowserV8FullCodeCacheTest
: public ServiceWorkerVersionBrowserTest,
- public ServiceWorkerVersion::Listener {
+ public ServiceWorkerVersion::Observer {
public:
using self = ServiceWorkerVersionBrowserV8FullCodeCacheTest;
ServiceWorkerVersionBrowserV8FullCodeCacheTest() {
@@ -2713,15 +2885,15 @@ class ServiceWorkerVersionBrowserV8FullCodeCacheTest
}
~ServiceWorkerVersionBrowserV8FullCodeCacheTest() override {
if (version_)
- version_->RemoveListener(this);
+ version_->RemoveObserver(this);
}
void SetUpRegistrationAndListenerOnIOThread(const std::string& worker_url) {
SetUpRegistrationOnIOThread(worker_url);
- version_->AddListener(this);
+ version_->AddObserver(this);
}
protected:
- // ServiceWorkerVersion::Listener overrides
+ // ServiceWorkerVersion::Observer overrides
void OnCachedMetadataUpdated(ServiceWorkerVersion* version,
size_t size) override {
metadata_size_ = size;
@@ -2746,14 +2918,14 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8FullCodeCacheTest,
cache_updated_closure_ = cached_metadata_run_loop.QuitClosure();
// Start a worker.
- StartWorker(SERVICE_WORKER_OK);
+ StartWorker(blink::ServiceWorkerStatusCode::kOk);
// Wait for the metadata to be stored. This run loop should finish when
// OnCachedMetadataUpdated() is called.
cached_metadata_run_loop.Run();
// The V8 code cache should be stored to the storage. It must have size
- // greater than 12 bytes.
+ // greater than 16 bytes.
EXPECT_GT(static_cast<int>(metadata_size_), kV8CacheTimeStampDataSize);
// Stop the worker.
@@ -2928,7 +3100,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CodeCacheForCacheStorageTest,
WaitUntilSideDataSizeIs(0);
// Second load: The V8 code cache should be stored in CacheStorage. It must
- // have size greater than 12 bytes.
+ // have size greater than 16 bytes.
NavigateToTestPage();
WaitUntilSideDataSizeIsBiggerThan(kV8CacheTimeStampDataSize);
}
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 947d1166e58..c2252ec96fa 100644
--- a/chromium/content/browser/service_worker/service_worker_client_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_client_utils.cc
@@ -549,14 +549,14 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT,
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort,
nullptr /* client_info */);
return;
}
if (render_process_id == ChildProcessHost::kInvalidUniqueID &&
render_frame_id == MSG_ROUTING_NONE) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_FAILED,
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorFailed,
nullptr /* client_info */);
return;
}
@@ -575,13 +575,15 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
base::BindOnce(&GetWindowClientInfoOnUI, provider_host->process_id(),
provider_host->route_id(), provider_host->create_time(),
provider_host->client_uuid()),
- base::BindOnce(std::move(callback), SERVICE_WORKER_OK));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kOk));
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.
- std::move(callback).Run(SERVICE_WORKER_OK, nullptr /* client_info */);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk,
+ nullptr /* client_info */);
}
} // namespace service_worker_client_utils
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 93ac4aba752..e927d202c5d 100644
--- a/chromium/content/browser/service_worker/service_worker_client_utils.h
+++ b/chromium/content/browser/service_worker/service_worker_client_utils.h
@@ -10,7 +10,7 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h"
class GURL;
@@ -24,7 +24,7 @@ class ServiceWorkerVersion;
namespace service_worker_client_utils {
using NavigationCallback = base::OnceCallback<void(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
blink::mojom::ServiceWorkerClientInfoPtr client_info)>;
using ClientCallback = base::OnceCallback<void(
blink::mojom::ServiceWorkerClientInfoPtr client_info)>;
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.cc b/chromium/content/browser/service_worker/service_worker_context_core.cc
index 46f20d354a1..8e6f44affb4 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core.cc
@@ -23,7 +23,6 @@
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_info.h"
#include "content/browser/service_worker/service_worker_job_coordinator.h"
#include "content/browser/service_worker/service_worker_process_manager.h"
@@ -35,6 +34,7 @@
#include "content/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/child_process_host.h"
#include "ipc/ipc_message.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
@@ -69,8 +69,8 @@ void CheckFetchHandlerOfInstalledServiceWorker(
void SuccessCollectorCallback(base::OnceClosure done_closure,
bool* overall_success,
- ServiceWorkerStatusCode status) {
- if (status != ServiceWorkerStatusCode::SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode status) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
*overall_success = false;
}
std::move(done_closure).Run();
@@ -78,12 +78,12 @@ void SuccessCollectorCallback(base::OnceClosure done_closure,
void SuccessReportingCallback(
const bool* success,
- base::OnceCallback<void(ServiceWorkerStatusCode)> callback) {
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
bool result = *success;
- std::move(callback).Run(
- result ? ServiceWorkerStatusCode::SERVICE_WORKER_OK
- : ServiceWorkerStatusCode::SERVICE_WORKER_ERROR_FAILED);
+ std::move(callback).Run(result
+ ? blink::ServiceWorkerStatusCode::kOk
+ : blink::ServiceWorkerStatusCode::kErrorFailed);
}
bool IsSameOriginClientProviderHost(const GURL& origin,
@@ -127,7 +127,7 @@ class ClearAllServiceWorkersHelper
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
- void OnResult(ServiceWorkerStatusCode) {
+ void OnResult(blink::ServiceWorkerStatusCode) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// We do nothing in this method. We use this class to wait for all callbacks
// to be called using the refcount.
@@ -135,9 +135,9 @@ class ClearAllServiceWorkersHelper
void DidGetAllRegistrations(
const base::WeakPtr<ServiceWorkerContextCore>& context,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
- if (!context || status != SERVICE_WORKER_OK)
+ if (!context || status != blink::ServiceWorkerStatusCode::kOk)
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.
@@ -299,7 +299,6 @@ ServiceWorkerContextCore::ServiceWorkerContextCore(
ServiceWorkerContextCore* old_context,
ServiceWorkerContextWrapper* wrapper)
: wrapper_(wrapper),
- dispatcher_hosts_(std::move(old_context->dispatcher_hosts_)),
providers_(old_context->providers_.release()),
provider_by_uuid_(old_context->provider_by_uuid_.release()),
loader_factory_getter_(old_context->loader_factory_getter()),
@@ -321,41 +320,18 @@ ServiceWorkerContextCore::ServiceWorkerContextCore(
ServiceWorkerContextCore::~ServiceWorkerContextCore() {
DCHECK(storage_);
for (const auto& it : live_versions_)
- it.second->RemoveListener(this);
+ it.second->RemoveObserver(this);
weak_factory_.InvalidateWeakPtrs();
}
-void ServiceWorkerContextCore::AddDispatcherHost(
- int process_id,
- content::ServiceWorkerDispatcherHost* dispatcher_host) {
- DCHECK(dispatcher_hosts_.find(process_id) == dispatcher_hosts_.end());
- dispatcher_hosts_[process_id] = dispatcher_host;
-}
-
-ServiceWorkerDispatcherHost* ServiceWorkerContextCore::GetDispatcherHost(
- int process_id) {
- auto it = dispatcher_hosts_.find(process_id);
- if (it == dispatcher_hosts_.end())
- return nullptr;
- return it->second;
-}
-
-void ServiceWorkerContextCore::RemoveDispatcherHost(int process_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- // TODO(falken) Try to remove this call. It should be unnecessary because
- // provider hosts remove themselves when their Mojo connection to the renderer
- // is destroyed. But if we don't remove the hosts immediately here, collisions
- // of <process_id, provider_id> can occur if a new dispatcher host is
- // created for a reused RenderProcessHost. https://crbug.com/736203
- RemoveAllProviderHostsForProcess(process_id);
- dispatcher_hosts_.erase(process_id);
-}
-
void ServiceWorkerContextCore::AddProviderHost(
std::unique_ptr<ServiceWorkerProviderHost> host) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
int process_id = host->process_id();
int provider_id = host->provider_id();
+ // Precreated hosts are stored in the same map regardless of process.
+ if (ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id))
+ process_id = ChildProcessHost::kInvalidUniqueID;
ProviderMap* map = GetProviderMapForProcess(process_id);
if (!map) {
providers_->AddWithID(std::make_unique<ProviderMap>(), process_id);
@@ -364,22 +340,13 @@ void ServiceWorkerContextCore::AddProviderHost(
map->AddWithID(std::move(host), provider_id);
}
-std::unique_ptr<ServiceWorkerProviderHost>
-ServiceWorkerContextCore::ReleaseProviderHost(int process_id, int provider_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ProviderMap* map = GetProviderMapForProcess(process_id);
- if (!map || !map->Lookup(provider_id))
- return nullptr;
- std::unique_ptr<ServiceWorkerProviderHost> host =
- map->Replace(provider_id, nullptr);
- map->Remove(provider_id);
- return host;
-}
-
ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
int process_id,
int provider_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Precreated hosts are stored in the same map regardless of process.
+ if (ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id))
+ process_id = ChildProcessHost::kInvalidUniqueID;
ProviderMap* map = GetProviderMapForProcess(process_id);
if (!map)
return nullptr;
@@ -389,6 +356,9 @@ ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
void ServiceWorkerContextCore::RemoveProviderHost(
int process_id, int provider_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Precreated hosts are stored in the same map regardless of process.
+ if (ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id))
+ process_id = ChildProcessHost::kInvalidUniqueID;
ProviderMap* map = GetProviderMapForProcess(process_id);
DCHECK(map);
map->Remove(provider_id);
@@ -399,6 +369,10 @@ void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (providers_->Lookup(process_id))
providers_->Remove(process_id);
+ // This function is used to prevent <process_id, provider_id> collisions when
+ // a render process host is reused with the same process id. Don't bother
+ // removing the providers in this process with browser-assigned ids, which
+ // live in a different map, since they have unique ids.
}
std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator>
@@ -514,11 +488,11 @@ void ServiceWorkerContextCore::DeleteForOrigin(const GURL& origin,
}
void ServiceWorkerContextCore::DidGetRegistrationsForDeleteForOrigin(
- base::OnceCallback<void(ServiceWorkerStatusCode)> callback,
- ServiceWorkerStatusCode status,
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)> callback,
+ blink::ServiceWorkerStatusCode status,
const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
registrations) {
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(status);
return;
}
@@ -551,10 +525,10 @@ ServiceWorkerContextCore::GetProviderMapForProcess(int process_id) {
void ServiceWorkerContextCore::RegistrationComplete(
const GURL& pattern,
ServiceWorkerContextCore::RegistrationCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
ServiceWorkerRegistration* registration) {
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
DCHECK(!registration);
std::move(callback).Run(status, status_message,
blink::mojom::kInvalidServiceWorkerRegistrationId);
@@ -572,10 +546,10 @@ void ServiceWorkerContextCore::RegistrationComplete(
void ServiceWorkerContextCore::UpdateComplete(
ServiceWorkerContextCore::UpdateCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
ServiceWorkerRegistration* registration) {
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
DCHECK(!registration);
std::move(callback).Run(status, status_message,
blink::mojom::kInvalidServiceWorkerRegistrationId);
@@ -590,9 +564,9 @@ void ServiceWorkerContextCore::UnregistrationComplete(
const GURL& pattern,
ServiceWorkerContextCore::UnregistrationCallback callback,
int64_t registration_id,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
std::move(callback).Run(status);
- if (status == SERVICE_WORKER_OK) {
+ if (status == blink::ServiceWorkerStatusCode::kOk) {
observer_list_->Notify(
FROM_HERE, &ServiceWorkerContextCoreObserver::OnRegistrationDeleted,
registration_id, pattern);
@@ -628,7 +602,7 @@ void ServiceWorkerContextCore::AddLiveVersion(ServiceWorkerVersion* version) {
// the version ID conflict. Otherwise change CHECK to DCHECK.
CHECK(!GetLiveVersion(version->version_id()));
live_versions_[version->version_id()] = version;
- version->AddListener(this);
+ version->AddObserver(this);
ServiceWorkerVersionInfo version_info = version->GetInfo();
observer_list_->Notify(FROM_HERE,
&ServiceWorkerContextCoreObserver::OnNewLiveVersion,
@@ -712,9 +686,9 @@ void ServiceWorkerContextCore::CheckHasServiceWorker(
void ServiceWorkerContextCore::UpdateVersionFailureCount(
int64_t version_id,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
// Don't count these, they aren't start worker failures.
- if (status == SERVICE_WORKER_ERROR_DISALLOWED)
+ if (status == blink::ServiceWorkerStatusCode::kErrorDisallowed)
return;
auto it = failure_counts_.find(version_id);
@@ -723,7 +697,7 @@ void ServiceWorkerContextCore::UpdateVersionFailureCount(
status);
}
- if (status == SERVICE_WORKER_OK) {
+ if (status == blink::ServiceWorkerStatusCode::kOk) {
if (it != failure_counts_.end())
failure_counts_.erase(it);
return;
@@ -810,8 +784,7 @@ void ServiceWorkerContextCore::OnErrorReported(
const GURL& source_url) {
observer_list_->Notify(
FROM_HERE, &ServiceWorkerContextCoreObserver::OnErrorReported,
- version->version_id(), version->embedded_worker()->process_id(),
- version->embedded_worker()->thread_id(),
+ version->version_id(),
ServiceWorkerContextCoreObserver::ErrorInfo(error_message, line_number,
column_number, source_url));
}
@@ -825,8 +798,7 @@ void ServiceWorkerContextCore::OnReportConsoleMessage(
const GURL& source_url) {
observer_list_->Notify(
FROM_HERE, &ServiceWorkerContextCoreObserver::OnReportConsoleMessage,
- version->version_id(), version->embedded_worker()->process_id(),
- version->embedded_worker()->thread_id(),
+ version->version_id(),
ServiceWorkerContextCoreObserver::ConsoleMessage(
source_identifier, message_level, message, line_number, source_url));
}
@@ -855,9 +827,9 @@ ServiceWorkerProcessManager* ServiceWorkerContextCore::process_manager() {
void ServiceWorkerContextCore::DidFindRegistrationForCheckHasServiceWorker(
const GURL& other_url,
ServiceWorkerContext::CheckHasServiceWorkerCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(ServiceWorkerCapability::NO_SERVICE_WORKER);
return;
}
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 5168ea6801c..9a299aa9eb2 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core.h
@@ -43,7 +43,6 @@ namespace content {
class EmbeddedWorkerRegistry;
class ServiceWorkerContextCoreObserver;
class ServiceWorkerContextWrapper;
-class ServiceWorkerDispatcherHost;
class ServiceWorkerJobCoordinator;
class ServiceWorkerProviderHost;
class ServiceWorkerRegistration;
@@ -56,21 +55,22 @@ class URLLoaderFactoryGetter;
// is the root of the containment hierarchy for service worker data
// associated with a particular partition.
class CONTENT_EXPORT ServiceWorkerContextCore
- : public ServiceWorkerVersion::Listener {
+ : public ServiceWorkerVersion::Observer {
public:
using BoolCallback = base::OnceCallback<void(bool)>;
using StatusCallback =
- base::OnceCallback<void(ServiceWorkerStatusCode status)>;
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode status)>;
using RegistrationCallback =
- base::OnceCallback<void(ServiceWorkerStatusCode status,
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id)>;
using UpdateCallback =
- base::OnceCallback<void(ServiceWorkerStatusCode status,
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id)>;
using UnregistrationCallback =
- base::OnceCallback<void(ServiceWorkerStatusCode status)>;
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode status)>;
+ // TODO(falken): Change these to just use std::map.
using ProviderMap = base::IDMap<std::unique_ptr<ServiceWorkerProviderHost>>;
using ProcessToProviderMap = base::IDMap<std::unique_ptr<ProviderMap>>;
@@ -81,6 +81,8 @@ class CONTENT_EXPORT ServiceWorkerContextCore
static const base::FilePath::CharType kServiceWorkerDirectory[];
// Iterates over ServiceWorkerProviderHost objects in a ProcessToProviderMap.
+ // TODO(falken): This can just iterate over the simple map
+ // |providers_by_uuid_| for simplicity.
class CONTENT_EXPORT ProviderHostIterator {
public:
~ProviderHostIterator();
@@ -129,7 +131,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore
void OnStorageWiped();
- // ServiceWorkerVersion::Listener overrides.
+ // ServiceWorkerVersion::Observer overrides.
void OnRunningStateChanged(ServiceWorkerVersion* version) override;
void OnVersionStateChanged(ServiceWorkerVersion* version) override;
void OnDevToolsRoutingIdChanged(ServiceWorkerVersion* version) override;
@@ -161,20 +163,13 @@ class CONTENT_EXPORT ServiceWorkerContextCore
return job_coordinator_.get();
}
- // Maintains DispatcherHosts to exchange service worker related messages
- // through them. The DispatcherHosts are not owned by this class.
- void AddDispatcherHost(int process_id,
- ServiceWorkerDispatcherHost* dispatcher_host);
- ServiceWorkerDispatcherHost* GetDispatcherHost(int process_id);
- void RemoveDispatcherHost(int process_id);
-
// The context class owns the set of ProviderHosts.
+ //
+ // For browser-assigned provider ids, the |process_id| parameter is ignored,
+ // since they have unique ids.
void AddProviderHost(
std::unique_ptr<ServiceWorkerProviderHost> provider_host);
ServiceWorkerProviderHost* GetProviderHost(int process_id, int provider_id);
- std::unique_ptr<ServiceWorkerProviderHost> ReleaseProviderHost(
- int process_id,
- int provider_id);
void RemoveProviderHost(int process_id, int provider_id);
void RemoveAllProviderHostsForProcess(int process_id);
@@ -211,14 +206,16 @@ class CONTENT_EXPORT ServiceWorkerContextCore
UnregistrationCallback callback);
// Callback is called after all deletions occured. The status code is
- // SERVICE_WORKER_OK if all succeed, or SERVICE_WORKER_FAILED
- // if any did not succeed.
+ // blink::ServiceWorkerStatusCode::kOk if all succeed, or
+ // SERVICE_WORKER_FAILED if any did not succeed.
void DeleteForOrigin(const GURL& origin, StatusCallback callback);
// Updates the service worker. If |force_bypass_cache| is true or 24 hours
// have passed since the last update, bypasses the browser cache.
void UpdateServiceWorker(ServiceWorkerRegistration* registration,
bool force_bypass_cache);
+ // |callback| is called when the promise for
+ // ServiceWorkerRegistration.update() would be resolved.
void UpdateServiceWorker(ServiceWorkerRegistration* registration,
bool force_bypass_cache,
bool skip_script_comparison,
@@ -275,7 +272,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore
const ServiceWorkerContext::CheckHasServiceWorkerCallback callback);
void UpdateVersionFailureCount(int64_t version_id,
- ServiceWorkerStatusCode status);
+ blink::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);
@@ -300,37 +297,37 @@ class CONTENT_EXPORT ServiceWorkerContextCore
struct FailureInfo {
int count;
- ServiceWorkerStatusCode last_failure;
+ blink::ServiceWorkerStatusCode last_failure;
};
ProviderMap* GetProviderMapForProcess(int process_id);
void RegistrationComplete(const GURL& pattern,
RegistrationCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
ServiceWorkerRegistration* registration);
void UpdateComplete(UpdateCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
ServiceWorkerRegistration* registration);
void UnregistrationComplete(const GURL& pattern,
UnregistrationCallback callback,
int64_t registration_id,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void DidGetRegistrationsForDeleteForOrigin(
- base::OnceCallback<void(ServiceWorkerStatusCode)> callback,
- ServiceWorkerStatusCode status,
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)> callback,
+ blink::ServiceWorkerStatusCode status,
const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
registrations);
void DidFindRegistrationForCheckHasServiceWorker(
const GURL& other_url,
ServiceWorkerContext::CheckHasServiceWorkerCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void OnRegistrationFinishedForCheckHasServiceWorker(
ServiceWorkerContext::CheckHasServiceWorkerCallback callback,
@@ -340,10 +337,13 @@ class CONTENT_EXPORT ServiceWorkerContextCore
// because the Wrapper::Shutdown call that hops threads to destroy |this| uses
// Bind() to hold a reference to |wrapper_| until |this| is fully destroyed.
ServiceWorkerContextWrapper* wrapper_;
- std::map<int /* process_id */, ServiceWorkerDispatcherHost*>
- dispatcher_hosts_;
+
+ // |providers_| owns the provider hosts. Hosts with browser-assigned provider
+ // ids (unique over all processes), are kept in the map for process id -1.
std::unique_ptr<ProcessToProviderMap> providers_;
+ // |provider_by_uuid_| contains raw pointers to hosts owned by |providers_|.
std::unique_ptr<ProviderByClientUUIDMap> provider_by_uuid_;
+
std::unique_ptr<ServiceWorkerStorage> storage_;
scoped_refptr<EmbeddedWorkerRegistry> embedded_worker_registry_;
std::unique_ptr<ServiceWorkerJobCoordinator> job_coordinator_;
diff --git a/chromium/content/browser/service_worker/service_worker_context_core_observer.h b/chromium/content/browser/service_worker/service_worker_context_core_observer.h
index 99966ec319b..0787d0ed5c3 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core_observer.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core_observer.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CORE_OBSERVER_H_
#include <stdint.h>
+#include <string>
#include "base/callback.h"
#include "base/strings/string16.h"
@@ -71,13 +72,8 @@ class ServiceWorkerContextCoreObserver {
int64_t version_id,
base::Time script_response_time,
base::Time script_last_modified) {}
- virtual void OnErrorReported(int64_t version_id,
- int process_id,
- int thread_id,
- const ErrorInfo& info) {}
+ virtual void OnErrorReported(int64_t version_id, const ErrorInfo& info) {}
virtual void OnReportConsoleMessage(int64_t version_id,
- int process_id,
- int thread_id,
const ConsoleMessage& message) {}
virtual void OnControlleeAdded(int64_t version_id,
const std::string& uuid,
diff --git a/chromium/content/browser/service_worker/service_worker_context_core_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_core_unittest.cc
index 42658be8ceb..b3606460b8e 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core_unittest.cc
@@ -38,23 +38,26 @@ TEST_F(ServiceWorkerContextCoreTest, FailureInfo) {
const int64_t kVersionId = 55; // dummy value
EXPECT_EQ(0, context()->GetVersionFailureCount(kVersionId));
- context()->UpdateVersionFailureCount(kVersionId, SERVICE_WORKER_OK);
context()->UpdateVersionFailureCount(kVersionId,
- SERVICE_WORKER_ERROR_DISALLOWED);
+ blink::ServiceWorkerStatusCode::kOk);
+ context()->UpdateVersionFailureCount(
+ kVersionId, blink::ServiceWorkerStatusCode::kErrorDisallowed);
EXPECT_EQ(0, context()->GetVersionFailureCount(kVersionId));
- context()->UpdateVersionFailureCount(kVersionId,
- SERVICE_WORKER_ERROR_NETWORK);
+ context()->UpdateVersionFailureCount(
+ kVersionId, blink::ServiceWorkerStatusCode::kErrorNetwork);
EXPECT_EQ(1, context()->GetVersionFailureCount(kVersionId));
- EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNetwork,
context()->failure_counts_[kVersionId].last_failure);
- context()->UpdateVersionFailureCount(kVersionId, SERVICE_WORKER_ERROR_ABORT);
+ context()->UpdateVersionFailureCount(
+ kVersionId, blink::ServiceWorkerStatusCode::kErrorAbort);
EXPECT_EQ(2, context()->GetVersionFailureCount(kVersionId));
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
context()->failure_counts_[kVersionId].last_failure);
- context()->UpdateVersionFailureCount(kVersionId, SERVICE_WORKER_OK);
+ context()->UpdateVersionFailureCount(kVersionId,
+ blink::ServiceWorkerStatusCode::kOk);
EXPECT_EQ(0, context()->GetVersionFailureCount(kVersionId));
EXPECT_FALSE(base::ContainsKey(context()->failure_counts_, kVersionId));
}
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 4722982af26..1fcb4c80b49 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
@@ -158,8 +158,6 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJobImpl(
if (resource_id != kInvalidServiceWorkerResourceId) {
if (ServiceWorkerVersion::IsInstalled(version_->status())) {
// An installed worker is loading a stored script.
- if (is_main_script)
- version_->embedded_worker()->OnURLJobCreatedForMainScript();
*out_status = CreateJobStatus::READ_JOB;
} else {
// A new worker is loading a stored script. The script was already
@@ -212,7 +210,6 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJobImpl(
incumbent_resource_id =
stored_version->script_cache_map()->LookupResourceId(request->url());
}
- version_->embedded_worker()->OnURLJobCreatedForMainScript();
}
*out_status = incumbent_resource_id == kInvalidServiceWorkerResourceId
? CreateJobStatus::WRITE_JOB
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 9c653a1e5e2..cdf3aa4bb4c 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
@@ -9,7 +9,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/run_loop.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
@@ -94,13 +94,9 @@ class ServiceWorkerContextRequestHandlerTest : public testing::Test {
ServiceWorkerContextCore* context() const { return helper_->context(); }
void SetUpProvider() {
- std::unique_ptr<ServiceWorkerProviderHost> host =
- CreateProviderHostForServiceWorkerContext(
- helper_->mock_render_process_id(),
- true /* is_parent_frame_secure */, version_.get(),
- context()->AsWeakPtr(), &remote_endpoint_);
- provider_host_ = host->AsWeakPtr();
- context()->AddProviderHost(std::move(host));
+ provider_host_ = CreateProviderHostForServiceWorkerContext(
+ helper_->mock_render_process_id(), true /* is_parent_frame_secure */,
+ version_.get(), context()->AsWeakPtr(), &remote_endpoint_);
}
std::unique_ptr<net::URLRequest> CreateRequest(const GURL& url) {
diff --git a/chromium/content/browser/service_worker/service_worker_context_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
index df64683c72e..f7c92935136 100644
--- a/chromium/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
@@ -33,10 +33,11 @@ namespace {
void SaveResponseCallback(bool* called,
int64_t* store_registration_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
- EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
+ << blink::ServiceWorkerStatusToString(status);
*called = true;
*store_registration_id = registration_id;
}
@@ -47,7 +48,7 @@ ServiceWorkerContextCore::RegistrationCallback MakeRegisteredCallback(
return base::BindOnce(&SaveResponseCallback, called, store_registration_id);
}
-void CallCompletedCallback(bool* called, ServiceWorkerStatusCode) {
+void CallCompletedCallback(bool* called, blink::ServiceWorkerStatusCode) {
*called = true;
}
@@ -57,13 +58,13 @@ ServiceWorkerContextCore::UnregistrationCallback MakeUnregisteredCallback(
}
void ExpectRegisteredWorkers(
- ServiceWorkerStatusCode expect_status,
+ blink::ServiceWorkerStatusCode expect_status,
bool expect_waiting,
bool expect_active,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
ASSERT_EQ(expect_status, status);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
EXPECT_FALSE(registration.get());
return;
}
@@ -89,8 +90,7 @@ class RejectInstallTestHelper : public EmbeddedWorkerTestHelper {
RejectInstallTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
void OnInstallEvent(
- mojom::ServiceWorkerEventDispatcher::DispatchInstallEventCallback
- callback) override {
+ mojom::ServiceWorker::DispatchInstallEventCallback callback) override {
dispatched_events()->push_back(Event::Install);
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
true /* has_fetch_handler */, base::Time::Now());
@@ -102,8 +102,7 @@ class RejectActivateTestHelper : public EmbeddedWorkerTestHelper {
RejectActivateTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
void OnActivateEvent(
- mojom::ServiceWorkerEventDispatcher::DispatchActivateEventCallback
- callback) override {
+ mojom::ServiceWorker::DispatchActivateEventCallback callback) override {
dispatched_events()->push_back(Event::Activate);
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
base::Time::Now());
@@ -247,7 +246,8 @@ TEST_F(ServiceWorkerContextTest, Register) {
context()->storage()->FindRegistrationForId(
registration_id, pattern.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_OK,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kOk,
false /* expect_waiting */, true /* expect_active */));
base::RunLoop().RunUntilIdle();
}
@@ -296,7 +296,8 @@ TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
context()->storage()->FindRegistrationForId(
registration_id, pattern.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_ERROR_NOT_FOUND,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kErrorNotFound,
false /* expect_waiting */, false /* expect_active */));
base::RunLoop().RunUntilIdle();
}
@@ -347,7 +348,8 @@ TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
context()->storage()->FindRegistrationForId(
registration_id, pattern.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_OK,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kOk,
false /* expect_waiting */, true /* expect_active */));
base::RunLoop().RunUntilIdle();
}
@@ -379,7 +381,8 @@ TEST_F(ServiceWorkerContextTest, Unregister) {
context()->storage()->FindRegistrationForId(
registration_id, pattern.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_ERROR_NOT_FOUND,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kErrorNotFound,
false /* expect_waiting */, false /* expect_active */));
base::RunLoop().RunUntilIdle();
@@ -473,20 +476,24 @@ TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
context()->storage()->FindRegistrationForId(
registration_id1, origin1_p1.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_ERROR_NOT_FOUND,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kErrorNotFound,
false /* expect_waiting */, false /* expect_active */));
context()->storage()->FindRegistrationForId(
registration_id2, origin1_p2.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_ERROR_NOT_FOUND,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kErrorNotFound,
false /* expect_waiting */, false /* expect_active */));
context()->storage()->FindRegistrationForId(
registration_id3, origin2_p1.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_OK,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kOk,
false /* expect_waiting */, true /* expect_active */));
context()->storage()->FindRegistrationForId(
registration_id4, origin3_p1.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_OK,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kOk,
false /* expect_waiting */, true /* expect_active */));
base::RunLoop().RunUntilIdle();
@@ -665,12 +672,8 @@ TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
registration.get(),
GURL("https://another-origin.example.net/test/script_url"),
1L /* version_id */, helper_->context()->AsWeakPtr());
- // CreateProviderHostForServiceWorkerContext calls
- // ServiceWorkerProviderHost::CompleteStartWorkerPreparation, which requires a
- // dispatcher host.
- helper_->EnsureDispatcherHostForProcess(kRenderProcessId2);
remote_endpoints.emplace_back();
- std::unique_ptr<ServiceWorkerProviderHost> host4 =
+ base::WeakPtr<ServiceWorkerProviderHost> host4 =
CreateProviderHostForServiceWorkerContext(
kRenderProcessId2, true /* is_parent_frame_secure */, version.get(),
context()->AsWeakPtr(), &remote_endpoints.back());
@@ -684,7 +687,9 @@ TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
context()->AddProviderHost(std::move(host1));
context()->AddProviderHost(std::move(host2));
context()->AddProviderHost(std::move(host3));
- context()->AddProviderHost(std::move(host4));
+ // host4 is already included because CreateProviderHostForServiceWorkerContext
+ // adds it.
+ DCHECK(context()->GetProviderHost(host4->process_id(), host4->provider_id()));
// Iterate over the client provider hosts that belong to kOrigin1.
std::set<ServiceWorkerProviderHost*> results;
@@ -750,7 +755,8 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
context()->storage()->FindRegistrationForId(
registration_id, pattern.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_OK,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kOk,
false /* expect_waiting */, true /* expect_active */));
content::RunAllTasksUntilIdle();
@@ -760,7 +766,8 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
// operation should be aborted.
context()->storage()->FindRegistrationForId(
registration_id, pattern.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_ERROR_ABORT,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kErrorAbort,
false /* expect_waiting */, true /* expect_active */));
content::RunAllTasksUntilIdle();
@@ -768,7 +775,8 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
// registration should not be found.
context()->storage()->FindRegistrationForId(
registration_id, pattern.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_ERROR_NOT_FOUND,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kErrorNotFound,
false /* expect_waiting */, true /* expect_active */));
content::RunAllTasksUntilIdle();
@@ -782,7 +790,8 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
context()->storage()->FindRegistrationForId(
registration_id, pattern.GetOrigin(),
- base::BindOnce(&ExpectRegisteredWorkers, SERVICE_WORKER_OK,
+ base::BindOnce(&ExpectRegisteredWorkers,
+ blink::ServiceWorkerStatusCode::kOk,
false /* expect_waiting */, true /* expect_active */));
content::RunAllTasksUntilIdle();
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 e4d1f2758c4..5bb4c8f5527 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.cc
@@ -64,7 +64,7 @@ void ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread() {
}
void ServiceWorkerContextWatcher::OnStoredRegistrationsOnIOThread(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (is_stopped_)
@@ -297,8 +297,6 @@ void ServiceWorkerContextWatcher::OnMainScriptHttpResponseInfoSet(
}
void ServiceWorkerContextWatcher::OnErrorReported(int64_t version_id,
- int process_id,
- int thread_id,
const ErrorInfo& info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
int64_t registration_id = blink::mojom::kInvalidServiceWorkerRegistrationId;
@@ -314,8 +312,6 @@ void ServiceWorkerContextWatcher::OnErrorReported(int64_t version_id,
void ServiceWorkerContextWatcher::OnReportConsoleMessage(
int64_t version_id,
- int process_id,
- int thread_id,
const ConsoleMessage& message) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (message.message_level != CONSOLE_MESSAGE_LEVEL_ERROR)
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 68f86f49e37..1eb56b76459 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.h
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.h
@@ -7,6 +7,8 @@
#include <stdint.h>
+#include <memory>
+#include <string>
#include <unordered_map>
#include <vector>
@@ -52,7 +54,7 @@ class CONTENT_EXPORT ServiceWorkerContextWatcher
void GetStoredRegistrationsOnIOThread();
void OnStoredRegistrationsOnIOThread(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations);
void StopOnIOThread();
@@ -96,12 +98,8 @@ class CONTENT_EXPORT ServiceWorkerContextWatcher
base::Time script_response_time,
base::Time script_last_modified) override;
void OnErrorReported(int64_t version_id,
- int process_id,
- int thread_id,
const ErrorInfo& info) override;
void OnReportConsoleMessage(int64_t version_id,
- int process_id,
- int thread_id,
const ConsoleMessage& message) override;
void OnControlleeAdded(int64_t version_id,
const std::string& uuid,
diff --git a/chromium/content/browser/service_worker/service_worker_context_watcher_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_watcher_unittest.cc
index 3bc8afdbd8a..5ba18ee124c 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher_unittest.cc
@@ -18,16 +18,16 @@ namespace content {
namespace {
void DidRegisterServiceWorker(int64_t* registration_id_out,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
ASSERT_TRUE(registration_id_out);
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
*registration_id_out = registration_id;
}
-void DidUnregisterServiceWorker(ServiceWorkerStatusCode* status_out,
- ServiceWorkerStatusCode status) {
+void DidUnregisterServiceWorker(blink::ServiceWorkerStatusCode* status_out,
+ blink::ServiceWorkerStatusCode status) {
ASSERT_TRUE(status_out);
*status_out = status;
}
@@ -151,8 +151,9 @@ class ServiceWorkerContextWatcherTest : public testing::Test {
return registration_id;
}
- ServiceWorkerStatusCode UnregisterServiceWorker(const GURL& scope) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ blink::ServiceWorkerStatusCode UnregisterServiceWorker(const GURL& scope) {
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
context()->UnregisterServiceWorker(
scope, base::BindOnce(&DidUnregisterServiceWorker, &status));
base::RunLoop().RunUntilIdle();
@@ -163,8 +164,7 @@ class ServiceWorkerContextWatcherTest : public testing::Test {
scoped_refptr<ServiceWorkerContextWatcher> watcher,
int64_t version_id,
const ServiceWorkerContextCoreObserver::ErrorInfo& error_info) {
- watcher->OnErrorReported(version_id, 0 /* process_id */, 0 /* thread_id */,
- error_info);
+ watcher->OnErrorReported(version_id, error_info);
}
private:
@@ -297,7 +297,8 @@ TEST_F(ServiceWorkerContextWatcherTest, UnregisteredServiceWorker) {
watcher_callback.registrations().at(registration_id_2).pattern);
ASSERT_EQ(2u, watcher_callback.versions().size());
- ASSERT_EQ(SERVICE_WORKER_OK, UnregisterServiceWorker(scope_1));
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ UnregisterServiceWorker(scope_1));
ASSERT_EQ(1u, watcher_callback.registrations().size());
EXPECT_EQ(scope_2,
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 b91bad88fcd..9927359ee1b 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -24,7 +24,6 @@
#include "content/browser/service_worker/service_worker_quota_client.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/storage_partition_impl.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -32,6 +31,7 @@
#include "net/base/url_util.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/special_storage_policy.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace content {
@@ -43,7 +43,7 @@ base::LazyInstance<HeaderNameSet>::DestructorAtExit g_excluded_header_name_set =
LAZY_INSTANCE_INITIALIZER;
void WorkerStarted(ServiceWorkerContextWrapper::StatusCallback callback,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(callback), status));
@@ -51,10 +51,10 @@ void WorkerStarted(ServiceWorkerContextWrapper::StatusCallback callback,
void StartActiveWorkerOnIO(
ServiceWorkerContextWrapper::StatusCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status == SERVICE_WORKER_OK) {
+ if (status == blink::ServiceWorkerStatusCode::kOk) {
// Pass the reference of |registration| to WorkerStarted callback to prevent
// it from being deleted while starting the worker. If the refcount of
// |registration| is 1, it will be deleted after WorkerStarted is called.
@@ -65,26 +65,27 @@ void StartActiveWorkerOnIO(
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_NOT_FOUND));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorNotFound));
}
void SkipWaitingWorkerOnIO(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK || !registration->waiting_version())
+ if (status != blink::ServiceWorkerStatusCode::kOk ||
+ !registration->waiting_version())
return;
registration->waiting_version()->set_skip_waiting(true);
registration->ActivateWaitingVersionWhenReady();
}
-void DidStartActiveWorker(
- scoped_refptr<ServiceWorkerVersion> version,
- ServiceWorkerContext::StartActiveWorkerCallback info_callback,
- base::OnceClosure error_callback,
- ServiceWorkerStatusCode start_worker_status) {
- if (start_worker_status != SERVICE_WORKER_OK) {
+void DidStartWorker(scoped_refptr<ServiceWorkerVersion> version,
+ ServiceWorkerContext::StartWorkerCallback info_callback,
+ base::OnceClosure error_callback,
+ blink::ServiceWorkerStatusCode start_worker_status) {
+ if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
std::move(error_callback).Run();
return;
}
@@ -92,51 +93,63 @@ void DidStartActiveWorker(
std::move(info_callback).Run(instance->process_id(), instance->thread_id());
}
-void FoundReadyRegistrationForStartActiveWorker(
- ServiceWorkerContext::StartActiveWorkerCallback info_callback,
+void FoundRegistrationForStartWorker(
+ ServiceWorkerContext::StartWorkerCallback info_callback,
base::OnceClosure failure_callback,
- ServiceWorkerStatusCode service_worker_status,
- scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
+ blink::ServiceWorkerStatusCode service_worker_status,
+ scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (service_worker_status == SERVICE_WORKER_OK) {
- // Note: There might be a remote possibility that
- // |service_worker_registration|'s active version might change
- // between here and DidStartActiveWorker, so
- // bind |active_version| to RunAfterStartWorker.
- scoped_refptr<ServiceWorkerVersion> active_version =
- service_worker_registration->active_version();
- DCHECK(active_version.get());
- active_version->RunAfterStartWorker(
- ServiceWorkerMetrics::EventType::EXTERNAL_REQUEST,
- base::BindOnce(&DidStartActiveWorker, active_version,
- std::move(info_callback), std::move(failure_callback)));
- } else {
+ if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
std::move(failure_callback).Run();
+ return;
}
+
+ ServiceWorkerVersion* version_ptr = registration->active_version()
+ ? registration->active_version()
+ : registration->installing_version();
+ // Since FindRegistrationForPattern returned
+ // blink::ServiceWorkerStatusCode::kOk, there must be either: -
+ // an active version, which optionally might have activated from a waiting
+ // version (as DidFindRegistrationForFindImpl will activate any waiting
+ // version).
+ // - or an installing version.
+ DCHECK(version_ptr);
+
+ // Note: There might be a remote possibility that |registration|'s |version|
+ // might change between here and DidStartWorker, so bind |version| to
+ // RunAfterStartWorker.
+ scoped_refptr<ServiceWorkerVersion> version =
+ base::WrapRefCounted(version_ptr);
+ version->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::EXTERNAL_REQUEST,
+ base::BindOnce(&DidStartWorker, version, std::move(info_callback),
+ std::move(failure_callback)));
}
void StatusCodeToBoolCallbackAdapter(
ServiceWorkerContext::ResultCallback callback,
- ServiceWorkerStatusCode code) {
- std::move(callback).Run(code == ServiceWorkerStatusCode::SERVICE_WORKER_OK);
+ blink::ServiceWorkerStatusCode code) {
+ std::move(callback).Run(code == blink::ServiceWorkerStatusCode::kOk);
}
void FinishRegistrationOnIO(ServiceWorkerContext::ResultCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), status == SERVICE_WORKER_OK));
+ base::BindOnce(std::move(callback),
+ status == blink::ServiceWorkerStatusCode::kOk));
}
void FinishUnregistrationOnIO(ServiceWorkerContext::ResultCallback callback,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), status == SERVICE_WORKER_OK));
+ base::BindOnce(std::move(callback),
+ status == blink::ServiceWorkerStatusCode::kOk));
}
} // namespace
@@ -410,15 +423,15 @@ void ServiceWorkerContextWrapper::ClearAllServiceWorkersForTest(
context_core_->ClearAllServiceWorkersForTest(std::move(callback));
}
-void ServiceWorkerContextWrapper::StartActiveWorkerForPattern(
+void ServiceWorkerContextWrapper::StartWorkerForPattern(
const GURL& pattern,
- StartActiveWorkerCallback info_callback,
+ StartWorkerCallback info_callback,
base::OnceClosure failure_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FindReadyRegistrationForPattern(
+ FindRegistrationForPattern(
pattern,
- base::BindOnce(&FoundReadyRegistrationForStartActiveWorker,
- std::move(info_callback), std::move(failure_callback)));
+ base::BindOnce(&FoundRegistrationForStartWorker, std::move(info_callback),
+ std::move(failure_callback)));
}
void ServiceWorkerContextWrapper::StartServiceWorkerForNavigationHint(
@@ -542,7 +555,8 @@ void ServiceWorkerContextWrapper::FindReadyRegistrationForDocument(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context_core_) {
// FindRegistrationForDocument() can run the callback synchronously.
- std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT, nullptr);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort,
+ nullptr);
return;
}
context_core_->storage()->FindRegistrationForDocument(
@@ -556,17 +570,16 @@ void ServiceWorkerContextWrapper::FindReadyRegistrationForPattern(
const GURL& scope,
FindRegistrationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!context_core_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback),
- SERVICE_WORKER_ERROR_ABORT, nullptr));
- return;
- }
- context_core_->storage()->FindRegistrationForPattern(
- net::SimplifyUrlForRequest(scope),
- base::BindOnce(
- &ServiceWorkerContextWrapper::DidFindRegistrationForFindReady, this,
- std::move(callback)));
+ FindRegistrationForPatternImpl(scope, false /* include_installing_version */,
+ std::move(callback));
+}
+
+void ServiceWorkerContextWrapper::FindRegistrationForPattern(
+ const GURL& scope,
+ FindRegistrationCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ FindRegistrationForPatternImpl(scope, true /* include_installing_version */,
+ std::move(callback));
}
void ServiceWorkerContextWrapper::FindReadyRegistrationForId(
@@ -576,7 +589,8 @@ void ServiceWorkerContextWrapper::FindReadyRegistrationForId(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context_core_) {
// FindRegistrationForId() can run the callback synchronously.
- std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT, nullptr);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort,
+ nullptr);
return;
}
context_core_->storage()->FindRegistrationForId(
@@ -592,7 +606,8 @@ void ServiceWorkerContextWrapper::FindReadyRegistrationForIdOnly(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context_core_) {
// FindRegistrationForIdOnly() can run the callback synchronously.
- std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT, nullptr);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort,
+ nullptr);
return;
}
context_core_->storage()->FindRegistrationForIdOnly(
@@ -608,7 +623,8 @@ void ServiceWorkerContextWrapper::GetAllRegistrations(
if (!context_core_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT,
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort,
std::vector<ServiceWorkerRegistrationInfo>()));
return;
}
@@ -624,7 +640,7 @@ void ServiceWorkerContextWrapper::GetRegistrationUserData(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), std::vector<std::string>(),
- SERVICE_WORKER_ERROR_ABORT));
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
context_core_->storage()->GetUserData(registration_id, keys,
@@ -640,7 +656,7 @@ void ServiceWorkerContextWrapper::GetRegistrationUserDataByKeyPrefix(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), std::vector<std::string>(),
- SERVICE_WORKER_ERROR_ABORT));
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
context_core_->storage()->GetUserDataByKeyPrefix(registration_id, key_prefix,
@@ -656,7 +672,7 @@ void ServiceWorkerContextWrapper::GetRegistrationUserKeysAndDataByKeyPrefix(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback),
base::flat_map<std::string, std::string>(),
- SERVICE_WORKER_ERROR_ABORT));
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
context_core_->storage()->GetUserKeysAndDataByKeyPrefix(
@@ -671,8 +687,8 @@ void ServiceWorkerContextWrapper::StoreRegistrationUserData(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context_core_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT));
+ FROM_HERE, base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
context_core_->storage()->StoreUserData(registration_id, origin.GetOrigin(),
@@ -686,8 +702,8 @@ void ServiceWorkerContextWrapper::ClearRegistrationUserData(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context_core_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT));
+ FROM_HERE, base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
context_core_->storage()->ClearUserData(registration_id, keys,
@@ -701,8 +717,8 @@ void ServiceWorkerContextWrapper::ClearRegistrationUserDataByKeyPrefixes(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context_core_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT));
+ FROM_HERE, base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
context_core_->storage()->ClearUserDataByKeyPrefixes(
@@ -718,7 +734,7 @@ void ServiceWorkerContextWrapper::GetUserDataForAllRegistrations(
FROM_HERE,
base::BindOnce(std::move(callback),
std::vector<std::pair<int64_t, std::string>>(),
- SERVICE_WORKER_ERROR_ABORT));
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
context_core_->storage()->GetUserDataForAllRegistrations(key,
@@ -734,7 +750,7 @@ void ServiceWorkerContextWrapper::GetUserDataForAllRegistrationsByKeyPrefix(
FROM_HERE,
base::BindOnce(std::move(callback),
std::vector<std::pair<int64_t, std::string>>(),
- SERVICE_WORKER_ERROR_ABORT));
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
context_core_->storage()->GetUserDataForAllRegistrationsByKeyPrefix(
@@ -753,7 +769,8 @@ void ServiceWorkerContextWrapper::StartServiceWorker(const GURL& pattern,
if (!context_core_) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
context_core_->storage()->FindRegistrationForPattern(
@@ -863,18 +880,38 @@ void ServiceWorkerContextWrapper::InitInternal(
this);
}
+void ServiceWorkerContextWrapper::FindRegistrationForPatternImpl(
+ const GURL& scope,
+ bool include_installing_version,
+ FindRegistrationCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!context_core_) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort, nullptr));
+ return;
+ }
+ context_core_->storage()->FindRegistrationForPattern(
+ net::SimplifyUrlForRequest(scope),
+ base::BindOnce(
+ &ServiceWorkerContextWrapper::DidFindRegistrationForFindImpl, this,
+ include_installing_version, std::move(callback)));
+}
+
void ServiceWorkerContextWrapper::ShutdownOnIO() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
resource_context_ = nullptr;
context_core_.reset();
}
-void ServiceWorkerContextWrapper::DidFindRegistrationForFindReady(
+void ServiceWorkerContextWrapper::DidFindRegistrationForFindImpl(
+ bool include_installing_version,
FindRegistrationCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(status, nullptr);
return;
}
@@ -886,21 +923,38 @@ void ServiceWorkerContextWrapper::DidFindRegistrationForFindReady(
scoped_refptr<ServiceWorkerVersion> active_version =
registration->active_version();
- if (!active_version) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_NOT_FOUND, nullptr);
+ if (active_version) {
+ if (active_version->status() == ServiceWorkerVersion::ACTIVATING) {
+ // Wait until the version is activated.
+ active_version->RegisterStatusChangeCallback(base::BindOnce(
+ &ServiceWorkerContextWrapper::OnStatusChangedForFindReadyRegistration,
+ this, std::move(callback), std::move(registration)));
+ return;
+ }
+ DCHECK_EQ(ServiceWorkerVersion::ACTIVATED, active_version->status());
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk,
+ std::move(registration));
return;
}
- if (active_version->status() == ServiceWorkerVersion::ACTIVATING) {
- // Wait until the version is activated.
- active_version->RegisterStatusChangeCallback(base::BindOnce(
- &ServiceWorkerContextWrapper::OnStatusChangedForFindReadyRegistration,
- this, std::move(callback), std::move(registration)));
+ if (include_installing_version && registration->installing_version()) {
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk,
+ std::move(registration));
return;
}
- DCHECK_EQ(ServiceWorkerVersion::ACTIVATED, active_version->status());
- std::move(callback).Run(SERVICE_WORKER_OK, std::move(registration));
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorNotFound,
+ nullptr);
+}
+
+void ServiceWorkerContextWrapper::DidFindRegistrationForFindReady(
+ FindRegistrationCallback callback,
+ blink::ServiceWorkerStatusCode status,
+ scoped_refptr<ServiceWorkerRegistration> registration) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DidFindRegistrationForFindImpl(false /* include_installing_version */,
+ std::move(callback), status,
+ std::move(registration));
}
void ServiceWorkerContextWrapper::OnStatusChangedForFindReadyRegistration(
@@ -911,16 +965,17 @@ void ServiceWorkerContextWrapper::OnStatusChangedForFindReadyRegistration(
registration->active_version();
if (!active_version ||
active_version->status() != ServiceWorkerVersion::ACTIVATED) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_NOT_FOUND, nullptr);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorNotFound,
+ nullptr);
return;
}
- std::move(callback).Run(SERVICE_WORKER_OK, registration);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk, registration);
}
void ServiceWorkerContextWrapper::DidDeleteAndStartOver(
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
context_core_.reset();
return;
}
@@ -931,7 +986,7 @@ void ServiceWorkerContextWrapper::DidDeleteAndStartOver(
void ServiceWorkerContextWrapper::DidGetAllRegistrationsForGetAllOrigins(
GetUsageInfoCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::vector<ServiceWorkerUsageInfo> usage_infos;
@@ -963,11 +1018,11 @@ void ServiceWorkerContextWrapper::DidCheckHasServiceWorker(
}
void ServiceWorkerContextWrapper::DidFindRegistrationForUpdate(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (status != SERVICE_WORKER_OK)
+ if (status != blink::ServiceWorkerStatusCode::kOk)
return;
if (!context_core_)
return;
@@ -1022,13 +1077,13 @@ void ServiceWorkerContextWrapper::StartServiceWorkerForNavigationHintOnIO(
void ServiceWorkerContextWrapper::DidFindRegistrationForNavigationHint(
StartServiceWorkerForNavigationHintCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
TRACE_EVENT1("ServiceWorker", "DidFindRegistrationForNavigationHint",
- "status", ServiceWorkerStatusToString(status));
+ "status", blink::ServiceWorkerStatusToString(status));
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!registration) {
- DCHECK_NE(status, SERVICE_WORKER_OK);
+ DCHECK_NE(status, blink::ServiceWorkerStatusCode::kOk);
std::move(callback).Run(StartServiceWorkerForNavigationHintResult::
NO_SERVICE_WORKER_REGISTRATION);
return;
@@ -1061,12 +1116,13 @@ void ServiceWorkerContextWrapper::DidFindRegistrationForNavigationHint(
void ServiceWorkerContextWrapper::DidStartServiceWorkerForNavigationHint(
const GURL& pattern,
StartServiceWorkerForNavigationHintCallback callback,
- ServiceWorkerStatusCode code) {
+ blink::ServiceWorkerStatusCode code) {
TRACE_EVENT2("ServiceWorker", "DidStartServiceWorkerForNavigationHint", "url",
- pattern.spec(), "code", ServiceWorkerStatusToString(code));
+ pattern.spec(), "code",
+ blink::ServiceWorkerStatusToString(code));
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::move(callback).Run(
- code == SERVICE_WORKER_OK
+ code == blink::ServiceWorkerStatusCode::kOk
? StartServiceWorkerForNavigationHintResult::STARTED
: StartServiceWorkerForNavigationHintResult::FAILED);
}
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 e06300d2141..f1b9b94c5cc 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
@@ -48,7 +48,8 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
public ServiceWorkerContextCoreObserver,
public base::RefCountedThreadSafe<ServiceWorkerContextWrapper> {
public:
- using StatusCallback = base::OnceCallback<void(ServiceWorkerStatusCode)>;
+ using StatusCallback =
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)>;
using BoolCallback = base::OnceCallback<void(bool)>;
using FindRegistrationCallback =
ServiceWorkerStorage::FindRegistrationCallback;
@@ -123,9 +124,9 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
const GURL& other_url,
CheckHasServiceWorkerCallback callback) override;
void ClearAllServiceWorkersForTest(base::OnceClosure callback) override;
- void StartActiveWorkerForPattern(const GURL& pattern,
- StartActiveWorkerCallback info_callback,
- base::OnceClosure failure_callback) override;
+ void StartWorkerForPattern(const GURL& pattern,
+ StartWorkerCallback info_callback,
+ base::OnceClosure failure_callback) override;
void StartServiceWorkerForNavigationHint(
const GURL& document_url,
StartServiceWorkerForNavigationHintCallback callback) override;
@@ -175,6 +176,12 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
void FindReadyRegistrationForPattern(const GURL& scope,
FindRegistrationCallback callback);
+ // Similar to FindReadyRegistrationForPattern, but in the case no waiting or
+ // active worker is found (i.e., there is only an installing worker),
+ // |callback| is called without waiting for the worker to reach active.
+ void FindRegistrationForPattern(const GURL& scope,
+ FindRegistrationCallback callback);
+
// Returns the registration for |registration_id|. It is guaranteed that the
// returned registration has the activated worker.
//
@@ -289,26 +296,37 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
URLLoaderFactoryGetter* url_loader_factory_getter);
void ShutdownOnIO();
+ // If |include_installing_version| is true, |callback| is called if there is
+ // an installing version with no waiting or active version.
+ void FindRegistrationForPatternImpl(const GURL& scope,
+ bool include_installing_version,
+ FindRegistrationCallback callback);
+
void DidFindRegistrationForFindReady(
FindRegistrationCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
+ scoped_refptr<ServiceWorkerRegistration> registration);
+ void DidFindRegistrationForFindImpl(
+ bool include_installing_version,
+ FindRegistrationCallback callback,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void OnStatusChangedForFindReadyRegistration(
FindRegistrationCallback callback,
scoped_refptr<ServiceWorkerRegistration> registration);
- void DidDeleteAndStartOver(ServiceWorkerStatusCode status);
+ void DidDeleteAndStartOver(blink::ServiceWorkerStatusCode status);
void DidGetAllRegistrationsForGetAllOrigins(
GetUsageInfoCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& registrations);
void DidCheckHasServiceWorker(CheckHasServiceWorkerCallback callback,
content::ServiceWorkerCapability status);
void DidFindRegistrationForUpdate(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<content::ServiceWorkerRegistration> registration);
void CountExternalRequests(const GURL& url,
@@ -320,13 +338,13 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
void DidFindRegistrationForNavigationHint(
StartServiceWorkerForNavigationHintCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void DidStartServiceWorkerForNavigationHint(
const GURL& pattern,
StartServiceWorkerForNavigationHintCallback callback,
- ServiceWorkerStatusCode code);
+ blink::ServiceWorkerStatusCode code);
void RecordStartServiceWorkerForNavigationHintResult(
StartServiceWorkerForNavigationHintCallback callback,
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 d2dcaa67d40..dc214676e02 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
@@ -30,6 +30,7 @@
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/cpp/resource_response_info.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "ui/base/page_transition_types.h"
#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
@@ -95,6 +96,7 @@ ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
provider_host,
blob_storage_context,
resource_type),
+ resource_type_(resource_type),
is_main_resource_load_(
ServiceWorkerUtils::IsMainResourceType(resource_type)),
is_main_frame_load_(resource_type == RESOURCE_TYPE_MAIN_FRAME),
@@ -112,19 +114,42 @@ ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
ServiceWorkerControlleeRequestHandler::
~ServiceWorkerControlleeRequestHandler() {
- // Navigation triggers an update to occur shortly after the page and
- // its initial subresources load.
- if (provider_host_ && provider_host_->active_version()) {
- if (is_main_resource_load_ && !force_update_started_)
- provider_host_->active_version()->ScheduleUpdate();
- else
- provider_host_->active_version()->DeferScheduledUpdate();
- }
+ MaybeScheduleUpdate();
if (is_main_resource_load_ && provider_host_)
provider_host_->SetAllowAssociation(true);
}
+void ServiceWorkerControlleeRequestHandler::MaybeScheduleUpdate() {
+ if (!provider_host_ || !provider_host_->active_version())
+ return;
+
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ // For subresources: S13nServiceWorker doesn't come here.
+ DCHECK(is_main_resource_load_);
+
+ // For navigations, the update logic is taken care of
+ // during navigation and waits for the HintToUpdateServiceWorker message.
+ if (IsResourceTypeFrame(resource_type_))
+ return;
+
+ // Continue to the common non-S13nServiceWorker code for triggering update
+ // for shared workers. The renderer doesn't yet send a
+ // HintToUpdateServiceWorker message.
+ // TODO(falken): Make the renderer send the message for shared worker,
+ // to simplify the code.
+ }
+
+ // If DevTools forced an update, there is no need to update again.
+ if (force_update_started_)
+ return;
+
+ if (is_main_resource_load_)
+ provider_host_->active_version()->ScheduleUpdate();
+ else
+ provider_host_->active_version()->DeferScheduledUpdate();
+}
+
net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
@@ -198,7 +223,7 @@ void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader(
const network::ResourceRequest& resource_request,
ResourceContext* resource_context,
LoaderCallback callback) {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
DCHECK(is_main_resource_load_);
ClearJob();
@@ -244,7 +269,7 @@ void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader(
base::Optional<SubresourceLoaderParams>
ServiceWorkerControlleeRequestHandler::MaybeCreateSubresourceLoaderParams() {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
// We didn't create URLLoader for this request.
if (!url_job_)
@@ -258,22 +283,23 @@ ServiceWorkerControlleeRequestHandler::MaybeCreateSubresourceLoaderParams() {
// Otherwise let's send the controller service worker information along
// with the navigation commit.
- // Note that |controller_info->endpoint| could be null if the controller
- // service worker isn't starting up or running, e.g. in no-fetch worker
- // cases. In that case the renderer frame won't get the controller pointer
- // upon the navigation commit, and subresource loading will not be intercepted
- // at least until the frame gets a new controller ptr by SetController.
SubresourceLoaderParams params;
auto controller_info = mojom::ControllerServiceWorkerInfo::New();
+ controller_info->mode = provider_host_->GetControllerMode();
+ // Note that |controller_info->endpoint| is null if the controller has no
+ // fetch event handler. In that case the renderer frame won't get the
+ // controller pointer upon the navigation commit, and subresource loading will
+ // not be intercepted. (It might get intercepted later if the controller
+ // changes due to skipWaiting() so SetController is sent.)
controller_info->endpoint =
provider_host_->GetControllerServiceWorkerPtr().PassInterface();
controller_info->client_id = provider_host_->client_uuid();
- base::WeakPtr<ServiceWorkerHandle> handle =
- provider_host_->GetOrCreateServiceWorkerHandle(
+ base::WeakPtr<ServiceWorkerObjectHost> object_host =
+ provider_host_->GetOrCreateServiceWorkerObjectHost(
provider_host_->controller());
- if (handle) {
- params.controller_service_worker_handle = handle;
- controller_info->object_info = handle->CreateIncompleteObjectInfo();
+ if (object_host) {
+ params.controller_service_worker_object_host = object_host;
+ controller_info->object_info = object_host->CreateIncompleteObjectInfo();
}
params.controller_service_worker_info = std::move(controller_info);
return base::Optional<SubresourceLoaderParams>(std::move(params));
@@ -307,7 +333,7 @@ void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
void ServiceWorkerControlleeRequestHandler::
DidLookupRegistrationForMainResource(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
// The job may have been canceled before this was invoked.
if (JobWasCanceled())
@@ -318,16 +344,34 @@ void ServiceWorkerControlleeRequestHandler::
if (provider_host_ && !need_to_update)
provider_host_->SetAllowAssociation(true);
- if (status != SERVICE_WORKER_OK || !provider_host_ || !context_) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Status", status);
+ url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status));
return;
}
DCHECK(registration.get());
+ if (!provider_host_) {
+ url_job_->FallbackToNetwork();
+ TRACE_EVENT_ASYNC_END1(
+ "ServiceWorker",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+ url_job_.get(), "Info", "No Provider");
+ return;
+ }
+
+ if (!context_) {
+ url_job_->FallbackToNetwork();
+ TRACE_EVENT_ASYNC_END1(
+ "ServiceWorker",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+ url_job_.get(), "Info", "No Context");
+ return;
+ }
+
if (!GetContentClient()->browser()->AllowServiceWorker(
registration->pattern(), provider_host_->topmost_frame_url(),
resource_context_, provider_host_->web_contents_getter())) {
@@ -335,7 +379,8 @@ void ServiceWorkerControlleeRequestHandler::
TRACE_EVENT_ASYNC_END2(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Status", status, "Info", "ServiceWorker is blocked");
+ url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
+ "Info", "ServiceWorker is blocked");
return;
}
@@ -373,17 +418,20 @@ void ServiceWorkerControlleeRequestHandler::
if (active_version.get() &&
active_version->status() == ServiceWorkerVersion::ACTIVATING) {
provider_host_->SetAllowAssociation(false);
- registration->active_version()->RegisterStatusChangeCallback(base::BindOnce(
- &self::OnVersionStatusChanged, weak_factory_.GetWeakPtr(),
- base::RetainedRef(registration), base::RetainedRef(active_version)));
+ active_version->RegisterStatusChangeCallback(base::BindOnce(
+ &self::OnVersionStatusChanged, weak_factory_.GetWeakPtr(), registration,
+ active_version));
TRACE_EVENT_ASYNC_END2(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Status", status, "Info",
- "Wait until finished SW activation");
+ url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
+ "Info", "Wait until finished SW activation");
return;
}
+ // TODO(falken): Factor out the rest of this function and
+ // OnVersionStatusChanged into the same function.
+
// A registration exists, so associate it. Note that the controller is only
// set if there's an active version. If there's no active version, we should
// still associate so the provider host can use .ready.
@@ -396,7 +444,8 @@ void ServiceWorkerControlleeRequestHandler::
TRACE_EVENT_ASYNC_END2(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Status", status, "Info",
+ url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
+ "Info",
"ServiceWorkerVersion is not available, so falling back to network");
return;
}
@@ -406,20 +455,25 @@ void ServiceWorkerControlleeRequestHandler::
ServiceWorkerMetrics::CountControlledPageLoad(
active_version->site_for_uma(), stripped_url_, is_main_frame_load_);
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
+ IsResourceTypeFrame(resource_type_)) {
+ provider_host_->AddServiceWorkerToUpdate(active_version);
+ }
bool is_forwarded =
MaybeForwardToServiceWorker(url_job_.get(), active_version.get());
TRACE_EVENT_ASYNC_END2(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Status", status, "Info",
+ url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status),
+ "Info",
(is_forwarded) ? "Forwarded to the ServiceWorker"
: "Skipped the ServiceWorker which has no fetch handler");
}
void ServiceWorkerControlleeRequestHandler::OnVersionStatusChanged(
- ServiceWorkerRegistration* registration,
- ServiceWorkerVersion* version) {
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ scoped_refptr<ServiceWorkerVersion> version) {
// The job may have been canceled before this was invoked.
if (JobWasCanceled())
return;
@@ -438,15 +492,19 @@ void ServiceWorkerControlleeRequestHandler::OnVersionStatusChanged(
ServiceWorkerMetrics::CountControlledPageLoad(
version->site_for_uma(), stripped_url_, is_main_frame_load_);
- provider_host_->AssociateRegistration(registration,
+ provider_host_->AssociateRegistration(registration.get(),
false /* notify_controllerchange */);
- MaybeForwardToServiceWorker(url_job_.get(), version);
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
+ IsResourceTypeFrame(resource_type_)) {
+ provider_host_->AddServiceWorkerToUpdate(version);
+ }
+ MaybeForwardToServiceWorker(url_job_.get(), version.get());
}
void ServiceWorkerControlleeRequestHandler::DidUpdateRegistration(
const scoped_refptr<ServiceWorkerRegistration>& original_registration,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
DCHECK(force_update_started_);
@@ -459,7 +517,7 @@ void ServiceWorkerControlleeRequestHandler::DidUpdateRegistration(
url_job_->FallbackToNetwork();
return;
}
- if (status != SERVICE_WORKER_OK ||
+ if (status != blink::ServiceWorkerStatusCode::kOk ||
!original_registration->installing_version()) {
// Update failed. Look up the registration again since the original
// registration was possibly unregistered in the meantime.
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 f5b750685e3..ed148bea249 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
@@ -40,7 +40,7 @@ class ServiceWorkerVersion;
// A request handler derivative used to handle requests from
// controlled documents.
// Note that in IsServicificationEnabled cases this is used only for
-// main resource fetch during navigation.
+// main resource fetch during navigation or shared worker creation.
class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
: public ServiceWorkerRequestHandler,
public ServiceWorkerURLJobWrapper::Delegate {
@@ -94,15 +94,15 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
// For main resource case.
void PrepareForMainResource(const GURL& url, const GURL& site_for_cookies);
void DidLookupRegistrationForMainResource(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void OnVersionStatusChanged(
- ServiceWorkerRegistration* registration,
- ServiceWorkerVersion* version);
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ scoped_refptr<ServiceWorkerVersion> version);
void DidUpdateRegistration(
const scoped_refptr<ServiceWorkerRegistration>& original_registration,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id);
void OnUpdatedVersionStatusChanged(
@@ -130,6 +130,11 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
bool JobWasCanceled() const;
+ // Schedules a service worker update to occur shortly after the page and its
+ // initial subresources load, if this handler was for a navigation.
+ void MaybeScheduleUpdate();
+
+ const ResourceType resource_type_;
const bool is_main_resource_load_;
const bool is_main_frame_load_;
std::unique_ptr<ServiceWorkerURLJobWrapper> url_job_;
diff --git a/chromium/content/browser/service_worker/service_worker_database.cc b/chromium/content/browser/service_worker/service_worker_database.cc
index c34711b2eb7..c7610f12b60 100644
--- a/chromium/content/browser/service_worker/service_worker_database.cc
+++ b/chromium/content/browser/service_worker/service_worker_database.cc
@@ -1226,12 +1226,8 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DestroyDatabase() {
return STATUS_OK;
}
- // Directly delete the database instead of calling leveldb::DestroyDB()
- // because the API does not delete the directory if there are unrelated files.
- // (https://code.google.com/p/chromium/issues/detail?id=468926#c24)
- Status status = base::DeleteFile(path_, true /* recursive */)
- ? STATUS_OK
- : STATUS_ERROR_FAILED;
+ Status status = LevelDBStatusToServiceWorkerDBStatus(
+ leveldb_chrome::DeleteDB(path_, leveldb_env::Options()));
ServiceWorkerMetrics::RecordDestroyDatabaseResult(status);
return status;
}
@@ -1246,12 +1242,11 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen(
if (IsOpen())
return STATUS_OK;
- if (!create_if_missing) {
+ if (!create_if_missing &&
+ (IsDatabaseInMemory() ||
+ !leveldb_chrome::PossiblyValidDB(path_, leveldb::Env::Default()))) {
// Avoid opening a database if it does not exist at the |path_|.
- if (IsDatabaseInMemory() || !base::PathExists(path_) ||
- base::IsDirectoryEmpty(path_)) {
- return STATUS_ERROR_NOT_FOUND;
- }
+ return STATUS_ERROR_NOT_FOUND;
}
leveldb_env::Options options;
diff --git a/chromium/content/browser/service_worker/service_worker_database.h b/chromium/content/browser/service_worker/service_worker_database.h
index c320569785c..c99a3d88f66 100644
--- a/chromium/content/browser/service_worker/service_worker_database.h
+++ b/chromium/content/browser/service_worker/service_worker_database.h
@@ -21,9 +21,9 @@
#include "base/sequence_checker.h"
#include "base/time/time.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 "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
#include "url/origin.h"
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
index 0f7a0bbd637..93a89c2faac 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -6,175 +6,112 @@
#include <utility>
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
-#include "content/browser/bad_message.h"
-#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_handle.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
-#include "content/browser/service_worker/service_worker_registration.h"
-#include "content/common/service_worker/service_worker_messages.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/browser/render_frame_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/origin_util.h"
-#include "ipc/ipc_message_macros.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h"
-#include "url/gurl.h"
-
-using blink::MessagePortChannel;
-using blink::WebServiceWorkerError;
namespace content {
-namespace {
-
-const uint32_t kServiceWorkerFilteredMessageClasses[] = {
- ServiceWorkerMsgStart,
-};
-
-} // namespace
-
-ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(int render_process_id)
- : BrowserMessageFilter(kServiceWorkerFilteredMessageClasses,
- arraysize(kServiceWorkerFilteredMessageClasses)),
- BrowserAssociatedInterface<mojom::ServiceWorkerDispatcherHost>(this,
- this),
- render_process_id_(render_process_id),
- weak_ptr_factory_(this) {}
+ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
+ scoped_refptr<ServiceWorkerContextWrapper> context_wrapper,
+ int render_process_id)
+ : render_process_id_(render_process_id), context_wrapper_(context_wrapper) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (GetContext() && phase_ == Phase::kAddedToContext)
- GetContext()->RemoveDispatcherHost(render_process_id_);
-}
-
-void ServiceWorkerDispatcherHost::Init(
- ServiceWorkerContextWrapper* context_wrapper) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ServiceWorkerDispatcherHost::Init, this,
- base::RetainedRef(context_wrapper)));
- return;
- }
-
- // Just speculating that maybe we were destructed before Init() was called on
- // the IO thread in order to try to fix https://crbug.com/750267.
- if (phase_ != Phase::kInitial)
- return;
-
- context_wrapper_ = context_wrapper;
- if (!GetContext())
- return;
- GetContext()->AddDispatcherHost(render_process_id_, this);
- phase_ = Phase::kAddedToContext;
}
-void ServiceWorkerDispatcherHost::OnFilterRemoved() {
+void ServiceWorkerDispatcherHost::AddBinding(
+ mojom::ServiceWorkerDispatcherHostAssociatedRequest request) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- // Don't wait until the destructor to teardown since a new dispatcher host
- // for this process might be created before then.
- if (GetContext() && phase_ == Phase::kAddedToContext) {
- GetContext()->RemoveDispatcherHost(render_process_id_);
- weak_ptr_factory_.InvalidateWeakPtrs();
- }
- phase_ = Phase::kRemovedFromContext;
- context_wrapper_ = nullptr;
-}
-
-void ServiceWorkerDispatcherHost::OnDestruct() const {
- // Destruct on the IO thread since |context_wrapper_| should only be accessed
- // on the IO thread.
- BrowserThread::DeleteOnIOThread::Destruct(this);
+ bindings_.AddBinding(this, std::move(request));
}
-bool ServiceWorkerDispatcherHost::OnMessageReceived(
- const IPC::Message& message) {
- return false;
-}
-
-base::WeakPtr<ServiceWorkerDispatcherHost>
-ServiceWorkerDispatcherHost::AsWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
+void ServiceWorkerDispatcherHost::RenderProcessExited(
+ RenderProcessHost* host,
+ const ChildProcessTerminationInfo& info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // TODO(crbug.com/736203) Try to remove this call. It should be unnecessary
+ // because provider hosts remove themselves when their Mojo connection to the
+ // renderer is destroyed. But if we don't remove the hosts immediately here,
+ // collisions of <process_id, provider_id> can occur if |this| is reused for
+ // another new renderer process due to reuse of the RenderProcessHost.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &ServiceWorkerDispatcherHost::RemoveAllProviderHostsForProcess,
+ base::Unretained(this)));
}
void ServiceWorkerDispatcherHost::OnProviderCreated(
- ServiceWorkerProviderHostInfo info) {
+ mojom::ServiceWorkerProviderHostInfoPtr info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerDispatcherHost::OnProviderCreated");
- if (!GetContext())
- return;
- if (GetContext()->GetProviderHost(render_process_id_, info.provider_id)) {
- bad_message::ReceivedBadMessage(
- this, bad_message::SWDH_PROVIDER_CREATED_DUPLICATE_ID);
+ ServiceWorkerContextCore* context = context_wrapper_->context();
+ if (!context)
return;
- }
// Provider hosts for navigations are precreated on the browser process with a
// browser-assigned id. The renderer process calls OnProviderCreated once it
// creates the provider.
- if (ServiceWorkerUtils::IsBrowserAssignedProviderId(info.provider_id)) {
- if (info.type != blink::mojom::ServiceWorkerProviderType::kForWindow) {
- bad_message::ReceivedBadMessage(
- this, bad_message::SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_NOT_WINDOW);
+ if (ServiceWorkerUtils::IsBrowserAssignedProviderId(info->provider_id)) {
+ if (info->type != blink::mojom::ServiceWorkerProviderType::kForWindow) {
+ bindings_.ReportBadMessage(
+ "SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_NOT_WINDOW");
return;
}
// Retrieve the provider host pre-created for the navigation.
- std::unique_ptr<ServiceWorkerProviderHost> provider_host =
- GetContext()->ReleaseProviderHost(ChildProcessHost::kInvalidUniqueID,
- info.provider_id);
+ ServiceWorkerProviderHost* provider_host = context->GetProviderHost(
+ ChildProcessHost::kInvalidUniqueID, info->provider_id);
// If no host is found, create one.
// TODO(crbug.com/789111#c14): This is probably not right, see bug.
if (!provider_host) {
- GetContext()->AddProviderHost(ServiceWorkerProviderHost::Create(
- render_process_id_, std::move(info), GetContext()->AsWeakPtr(),
- AsWeakPtr()));
+ context->AddProviderHost(ServiceWorkerProviderHost::Create(
+ render_process_id_, std::move(info), context->AsWeakPtr()));
return;
}
// Otherwise, complete initialization of the pre-created host.
+ if (provider_host->process_id() != ChildProcessHost::kInvalidUniqueID) {
+ bindings_.ReportBadMessage("SWDH_PRECREATED_PROVIDER_RESUED");
+ return;
+ }
provider_host->CompleteNavigationInitialized(render_process_id_,
- std::move(info), AsWeakPtr());
- GetContext()->AddProviderHost(std::move(provider_host));
+ std::move(info));
return;
}
// Provider hosts for service workers don't call OnProviderCreated. They are
// precreated and ServiceWorkerProviderHost::CompleteStartWorkerPreparation is
// called during the startup sequence once a process is allocated.
- if (info.type == blink::mojom::ServiceWorkerProviderType::kForServiceWorker) {
- bad_message::ReceivedBadMessage(
- this, bad_message::SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_SERVICE_WORKER);
+ if (info->type ==
+ blink::mojom::ServiceWorkerProviderType::kForServiceWorker) {
+ bindings_.ReportBadMessage(
+ "SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_SERVICE_WORKER");
return;
}
- GetContext()->AddProviderHost(ServiceWorkerProviderHost::Create(
- render_process_id_, std::move(info), GetContext()->AsWeakPtr(),
- AsWeakPtr()));
+ if (context->GetProviderHost(render_process_id_, info->provider_id)) {
+ bindings_.ReportBadMessage("SWDH_PROVIDER_CREATED_DUPLICATE_ID");
+ return;
+ }
+ context->AddProviderHost(ServiceWorkerProviderHost::Create(
+ render_process_id_, std::move(info), context->AsWeakPtr()));
}
-ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
+void ServiceWorkerDispatcherHost::RemoveAllProviderHostsForProcess() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!context_wrapper_.get())
- return nullptr;
- return context_wrapper_->context();
+ if (context_wrapper_->context()) {
+ context_wrapper_->context()->RemoveAllProviderHostsForProcess(
+ render_process_id_);
+ }
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
index 0a096b2d367..ede12c7f019 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -7,25 +7,16 @@
#include <stdint.h>
-#include <memory>
-#include <vector>
-
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
-#include "base/strings/string16.h"
-#include "content/browser/service_worker/service_worker_registration_status.h"
-#include "content/common/service_worker/service_worker.mojom.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "content/common/content_export.h"
+#include "content/common/service_worker/service_worker_provider.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/browser/browser_associated_interface.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "mojo/public/cpp/bindings/strong_associated_binding_set.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host_observer.h"
+#include "mojo/public/cpp/bindings/associated_binding_set.h"
namespace content {
-class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
namespace service_worker_dispatcher_host_unittest {
@@ -34,47 +25,31 @@ class TestingServiceWorkerDispatcherHost;
FORWARD_DECLARE_TEST(ServiceWorkerDispatcherHostTest,
ProviderCreatedAndDestroyed);
FORWARD_DECLARE_TEST(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash);
-FORWARD_DECLARE_TEST(BackgroundSyncManagerTest,
- RegisterWithoutLiveSWRegistration);
} // namespace service_worker_dispatcher_host_unittest
-// ServiceWorkerDispatcherHost is the browser-side endpoint for several IPC
-// messages for service workers. There is a 1:1 correspondence between
-// renderer processes and ServiceWorkerDispatcherHosts. Currently
-// ServiceWorkerDispatcherHost sends the legacy IPC message
-// ServiceWorkerMsg_ServiceWorkerStateChanged to its corresponding
-// ServiceWorkerDispatcher on the renderer and receives Mojo IPC messages from
-// any ServiceWorkerNetworkProvider on the renderer.
-//
-// ServiceWorkerDispatcherHost is created on the UI thread in
-// RenderProcessHostImpl::Init() via CreateMessageFilters(), but initialization,
-// destruction, and IPC message handling occur on the IO thread. It lives as
-// long as the renderer process lives. Therefore much tracking of renderer
-// processes in browser-side service worker code is built on
-// ServiceWorkerDispatcherHost lifetime.
+// ServiceWorkerDispatcherHost is a browser-side endpoint for the renderer to
+// notify the browser a service worker provider is created.
+// Unless otherwise noted, all methods are called on the IO thread.
//
-// This class is bound with mojom::ServiceWorkerDispatcherHost. All
-// InterfacePtrs on the same render process are bound to the same
-// content::ServiceWorkerDispatcherHost. This can be overridden only for
-// testing.
-//
-// TODO(leonhsl): This class no longer needs to be a BrowserMessageFilter
-// because we are already in a pure Mojo world.
+// In order to keep ordering with navigation IPCs to avoid potential races,
+// currently mojom::ServiceWorkerDispatcherHost interface is associated with the
+// legacy IPC channel.
+// TODO(leonhsl): Remove this class once we can understand how to move
+// OnProviderCreated() to an isolated message pipe.
class CONTENT_EXPORT ServiceWorkerDispatcherHost
- : public BrowserMessageFilter,
- public BrowserAssociatedInterface<mojom::ServiceWorkerDispatcherHost>,
- public mojom::ServiceWorkerDispatcherHost {
+ : public mojom::ServiceWorkerDispatcherHost,
+ public RenderProcessHostObserver {
public:
- explicit ServiceWorkerDispatcherHost(int render_process_id);
-
- void Init(ServiceWorkerContextWrapper* context_wrapper);
+ // Called on the UI thread.
+ ServiceWorkerDispatcherHost(
+ scoped_refptr<ServiceWorkerContextWrapper> context_wrapper,
+ int render_process_id);
- // BrowserMessageFilter implementation
- void OnFilterRemoved() override;
- void OnDestruct() const override;
- bool OnMessageReceived(const IPC::Message& message) override;
+ void AddBinding(mojom::ServiceWorkerDispatcherHostAssociatedRequest request);
- base::WeakPtr<ServiceWorkerDispatcherHost> AsWeakPtr();
+ // Called on the UI thread.
+ void RenderProcessExited(RenderProcessHost* host,
+ const ChildProcessTerminationInfo& info) override;
protected:
~ServiceWorkerDispatcherHost() override;
@@ -92,26 +67,16 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost
FRIEND_TEST_ALL_PREFIXES(
service_worker_dispatcher_host_unittest::ServiceWorkerDispatcherHostTest,
CleanupOnRendererCrash);
- FRIEND_TEST_ALL_PREFIXES(
- service_worker_dispatcher_host_unittest::BackgroundSyncManagerTest,
- RegisterWithoutLiveSWRegistration);
-
- enum class ProviderStatus { OK, NO_CONTEXT, DEAD_HOST, NO_HOST, NO_URL };
- // Debugging for https://crbug.com/750267
- enum class Phase { kInitial, kAddedToContext, kRemovedFromContext };
// mojom::ServiceWorkerDispatcherHost implementation
- void OnProviderCreated(ServiceWorkerProviderHostInfo info) override;
+ void OnProviderCreated(mojom::ServiceWorkerProviderHostInfoPtr info) override;
- ServiceWorkerContextCore* GetContext();
+ void RemoveAllProviderHostsForProcess();
const int render_process_id_;
// Only accessed on the IO thread.
- Phase phase_ = Phase::kInitial;
- // Only accessed on the IO thread.
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
-
- base::WeakPtrFactory<ServiceWorkerDispatcherHost> weak_ptr_factory_;
+ mojo::AssociatedBindingSet<mojom::ServiceWorkerDispatcherHost> bindings_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDispatcherHost);
};
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index 1505284dc5f..fae15052435 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
@@ -18,14 +18,16 @@
#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/browser/service_worker/service_worker_navigation_handle_core.h"
+#include "content/browser/service_worker/service_worker_object_host.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/browser/child_process_termination_info.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "mojo/core/embedder/embedder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
@@ -35,8 +37,8 @@ namespace content {
namespace service_worker_dispatcher_host_unittest {
static void SaveStatusCallback(bool* called,
- ServiceWorkerStatusCode* out,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode* out,
+ blink::ServiceWorkerStatusCode status) {
*called = true;
*out = status;
}
@@ -46,22 +48,6 @@ struct RemoteProviderInfo {
mojom::ServiceWorkerContainerAssociatedRequest client_request;
};
-RemoteProviderInfo SetupProviderHostInfoPtrs(
- ServiceWorkerProviderHostInfo* host_info) {
- RemoteProviderInfo remote_info;
- mojom::ServiceWorkerContainerAssociatedPtr browser_side_client_ptr;
- remote_info.client_request =
- mojo::MakeRequestAssociatedWithDedicatedPipe(&browser_side_client_ptr);
- host_info->host_request =
- mojo::MakeRequestAssociatedWithDedicatedPipe(&remote_info.host_ptr);
- host_info->client_ptr_info = browser_side_client_ptr.PassInterface();
- EXPECT_TRUE(host_info->host_request.is_pending());
- EXPECT_TRUE(host_info->client_ptr_info.is_valid());
- EXPECT_TRUE(remote_info.host_ptr.is_bound());
- EXPECT_TRUE(remote_info.client_request.is_pending());
- return remote_info;
-}
-
std::unique_ptr<ServiceWorkerNavigationHandleCore> CreateNavigationHandleCore(
ServiceWorkerContextWrapper* context_wrapper) {
std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core;
@@ -83,27 +69,6 @@ std::unique_ptr<ServiceWorkerNavigationHandleCore> CreateNavigationHandleCore(
return navigation_handle_core;
}
-class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
- public:
- TestingServiceWorkerDispatcherHost(int process_id,
- EmbeddedWorkerTestHelper* helper)
- : ServiceWorkerDispatcherHost(process_id),
- bad_messages_received_count_(0),
- helper_(helper) {}
-
- bool Send(IPC::Message* message) override { return helper_->Send(message); }
-
- IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); }
-
- void ShutdownForBadMessage() override { ++bad_messages_received_count_; }
-
- int bad_messages_received_count_;
-
- protected:
- EmbeddedWorkerTestHelper* helper_;
- ~TestingServiceWorkerDispatcherHost() override {}
-};
-
class ServiceWorkerDispatcherHostTest : public testing::Test {
protected:
ServiceWorkerDispatcherHostTest()
@@ -111,14 +76,20 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
void SetUp() override {
Initialize(std::make_unique<EmbeddedWorkerTestHelper>(base::FilePath()));
+ mojo::core::SetDefaultProcessErrorCallback(base::BindRepeating(
+ &ServiceWorkerDispatcherHostTest::OnMojoError, base::Unretained(this)));
}
void TearDown() override {
version_ = nullptr;
registration_ = nullptr;
helper_.reset();
+ mojo::core::SetDefaultProcessErrorCallback(
+ mojo::core::ProcessErrorCallback());
}
+ void OnMojoError(const std::string& error) { bad_messages_.push_back(error); }
+
ServiceWorkerContextCore* context() { return helper_->context(); }
ServiceWorkerContextWrapper* context_wrapper() {
return helper_->context_wrapper();
@@ -128,10 +99,8 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
helper_.reset(helper.release());
// Replace the default dispatcher host.
int process_id = helper_->mock_render_process_id();
- dispatcher_host_ =
- new TestingServiceWorkerDispatcherHost(process_id, helper_.get());
- helper_->RegisterDispatcherHost(process_id, nullptr);
- dispatcher_host_->Init(context_wrapper());
+ dispatcher_host_.reset(
+ new ServiceWorkerDispatcherHost(context_wrapper(), process_id));
}
void SetUpRegistration(const GURL& scope, const GURL& script_url) {
@@ -155,95 +124,151 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
context()->storage()->LazyInitializeForTest(base::DoNothing());
base::RunLoop().RunUntilIdle();
bool called = false;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
context()->storage()->StoreRegistration(
registration_.get(), version_.get(),
base::BindOnce(&SaveStatusCallback, &called, &status));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
}
- void SendProviderCreated(blink::mojom::ServiceWorkerProviderType type,
- const GURL& pattern) {
- const int64_t kProviderId = 99;
- ServiceWorkerProviderHostInfo info(kProviderId, MSG_ROUTING_NONE, type,
- true /* is_parent_frame_secure */);
- remote_endpoint_.BindWithProviderHostInfo(&info);
-
- dispatcher_host_->OnProviderCreated(std::move(info));
- provider_host_ = context()->GetProviderHost(
- helper_->mock_render_process_id(), kProviderId);
+ RemoteProviderInfo SendProviderCreated(
+ mojom::ServiceWorkerProviderHostInfoPtr host_info) {
+ DCHECK(!host_info->host_request.is_pending());
+ DCHECK(!host_info->client_ptr_info.is_valid());
+
+ RemoteProviderInfo remote_info;
+ mojom::ServiceWorkerContainerAssociatedPtrInfo client;
+ remote_info.client_request = mojo::MakeRequest(&client);
+ host_info->host_request = mojo::MakeRequest(&remote_info.host_ptr);
+ host_info->client_ptr_info = std::move(client);
+
+ mojom::ServiceWorkerDispatcherHostAssociatedPtr ptr;
+ dispatcher_host_->AddBinding(
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&ptr));
+ ptr->OnProviderCreated(std::move(host_info));
+ base::RunLoop().RunUntilIdle();
+ return remote_info;
}
TestBrowserThreadBundle browser_thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
- scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_;
+ std::unique_ptr<ServiceWorkerDispatcherHost, BrowserThread::DeleteOnIOThread>
+ dispatcher_host_;
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
- ServiceWorkerProviderHost* provider_host_;
- ServiceWorkerRemoteProviderEndpoint remote_endpoint_;
+ std::vector<std::string> bad_messages_;
};
-TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
+TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedForNavigation) {
int process_id = helper_->mock_render_process_id();
- std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core;
+ // Prepare the navigation handle to create provider host.
+ std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core =
+ CreateNavigationHandleCore(helper_->context_wrapper());
+ base::WeakPtr<ServiceWorkerProviderHost> host =
+ ServiceWorkerProviderHost::PreCreateNavigationHost(
+ context()->AsWeakPtr(), true /* are_ancestors_secure */,
+ base::RepeatingCallback<WebContents*(void)>());
+ int provider_id = host->provider_id();
+ mojom::ServiceWorkerProviderHostInfoPtr host_info =
+ CreateProviderHostInfoForWindow(provider_id, 1 /* route_id */);
+ EXPECT_TRUE(context()->GetProviderHost(ChildProcessHost::kInvalidUniqueID,
+ provider_id));
+ EXPECT_TRUE(context()->GetProviderHost(process_id, provider_id));
+ navigation_handle_core->DidPreCreateProviderHost(provider_id);
+ RemoteProviderInfo remote_provider =
+ SendProviderCreated(std::move(host_info));
+
+ // Releasing the interface pointer destroys the host.
+ remote_provider.host_ptr.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context()->GetProviderHost(ChildProcessHost::kInvalidUniqueID,
+ provider_id));
+ EXPECT_FALSE(context()->GetProviderHost(process_id, provider_id));
+}
+
+// Two with the same browser-assigned ID should be seen as a bad message.
+TEST_F(ServiceWorkerDispatcherHostTest, ReusedProviderCreatedForNavigation) {
+ int process_id = helper_->mock_render_process_id();
- // Prepare the first navigation handle to create provider host.
- const int kProviderId1 = -2;
- navigation_handle_core =
+ std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core =
CreateNavigationHandleCore(helper_->context_wrapper());
- ASSERT_TRUE(navigation_handle_core);
- base::WeakPtr<ServiceWorkerProviderHost> host1 =
+ base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
context()->AsWeakPtr(), true /* are_ancestors_secure */,
base::RepeatingCallback<WebContents*(void)>());
- EXPECT_EQ(kProviderId1, host1->provider_id());
- ServiceWorkerProviderHostInfo host_info_1(
- host1->provider_id(), 1 /* route_id */, host1->provider_type(),
- host1->is_parent_frame_secure());
- ServiceWorkerProviderHostInfo host_info_1_copy(
- host1->provider_id(), 1 /* route_id */, host1->provider_type(),
- host1->is_parent_frame_secure());
- RemoteProviderInfo remote_info_1 = SetupProviderHostInfoPtrs(&host_info_1);
- navigation_handle_core->DidPreCreateProviderHost(host1->provider_id());
-
- dispatcher_host_->OnProviderCreated(std::move(host_info_1));
- EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId1));
-
- // Two with the same ID should be seen as a bad message.
- dispatcher_host_->OnProviderCreated(std::move(host_info_1_copy));
- EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
-
- // Releasing the interface pointer destroys the counterpart.
- remote_info_1.host_ptr.reset();
+ int provider_id = host->provider_id();
+ EXPECT_EQ(provider_id, host->provider_id());
+ mojom::ServiceWorkerProviderHostInfoPtr host_info =
+ CreateProviderHostInfoForWindow(provider_id, 1 /* route_id */);
+ EXPECT_TRUE(context()->GetProviderHost(ChildProcessHost::kInvalidUniqueID,
+ provider_id));
+ EXPECT_TRUE(context()->GetProviderHost(process_id, provider_id));
+ navigation_handle_core->DidPreCreateProviderHost(provider_id);
+ RemoteProviderInfo remote_provider =
+ SendProviderCreated(std::move(host_info));
+
+ host_info = CreateProviderHostInfoForWindow(provider_id, 2 /* route_id */);
+ RemoteProviderInfo remote_provider2 =
+ SendProviderCreated(std::move(host_info));
+
+ ASSERT_EQ(1u, bad_messages_.size());
+ EXPECT_EQ("SWDH_PRECREATED_PROVIDER_RESUED", bad_messages_[0]);
+
+ // Releasing the interface pointer destroys the host.
+ remote_provider.host_ptr.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId1));
+ EXPECT_FALSE(context()->GetProviderHost(ChildProcessHost::kInvalidUniqueID,
+ provider_id));
+ EXPECT_FALSE(context()->GetProviderHost(process_id, provider_id));
+}
- // Prepare another navigation handle to create another provider host.
- const int kProviderId2 = -3;
- navigation_handle_core =
+TEST_F(ServiceWorkerDispatcherHostTest,
+ RendererDiesWithProviderCreatedForNavigation) {
+ int process_id = helper_->mock_render_process_id();
+
+ // Prepare a navigation handle to create a provider host.
+ std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core =
CreateNavigationHandleCore(helper_->context_wrapper());
- ASSERT_TRUE(navigation_handle_core);
- base::WeakPtr<ServiceWorkerProviderHost> host2 =
+ base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
context()->AsWeakPtr(), true /* are_ancestors_secure */,
base::RepeatingCallback<WebContents*(void)>());
- EXPECT_EQ(kProviderId2, host2->provider_id());
- ServiceWorkerProviderHostInfo host_info_2(
- host2->provider_id(), 2 /* route_id */, host2->provider_type(),
- host2->is_parent_frame_secure());
- RemoteProviderInfo remote_info_2 = SetupProviderHostInfoPtrs(&host_info_2);
- navigation_handle_core->DidPreCreateProviderHost(host2->provider_id());
-
- // Deletion of the dispatcher_host should cause providers for that
- // process to get deleted as well.
- dispatcher_host_->OnProviderCreated(std::move(host_info_2));
- EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId2));
- EXPECT_TRUE(dispatcher_host_->HasOneRef());
- dispatcher_host_ = nullptr;
- EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId2));
+ int provider_id = host->provider_id();
+ mojom::ServiceWorkerProviderHostInfoPtr host_info =
+ CreateProviderHostInfoForWindow(provider_id, 2 /* route_id */);
+ navigation_handle_core->DidPreCreateProviderHost(provider_id);
+ RemoteProviderInfo remote_provider =
+ SendProviderCreated(std::move(host_info));
+ EXPECT_TRUE(context()->GetProviderHost(process_id, provider_id));
+
+ // Simulate that the corresponding renderer process died.
+ dispatcher_host_->RenderProcessExited(nullptr /* host */,
+ ChildProcessTerminationInfo());
+ base::RunLoop().RunUntilIdle();
+ // The host still exists but is removed when the Mojo connection is
+ // destroyed.
+ EXPECT_TRUE(context()->GetProviderHost(process_id, provider_id));
+ // Releasing the interface pointer destroys the host.
+ remote_provider.host_ptr.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context()->GetProviderHost(process_id, provider_id));
+}
+
+// Two with the same renderer-assigned ID should be seen as a bad message.
+TEST_F(ServiceWorkerDispatcherHostTest, DuplicateProvider) {
+ const int kProviderId = 99;
+ RemoteProviderInfo remote_provider_1 = SendProviderCreated(
+ CreateProviderHostInfoForWindow(kProviderId, 1 /* route_id */));
+
+ EXPECT_TRUE(bad_messages_.empty());
+ RemoteProviderInfo remote_provider_2 = SendProviderCreated(
+ CreateProviderHostInfoForWindow(kProviderId, 1 /* route_id */));
+ ASSERT_EQ(1u, bad_messages_.size());
+ EXPECT_EQ("SWDH_PROVIDER_CREATED_DUPLICATE_ID", bad_messages_[0]);
}
TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
@@ -251,53 +276,48 @@ TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
GURL script_url = GURL("https://www.example.com/service_worker.js");
int process_id = helper_->mock_render_process_id();
- SendProviderCreated(blink::mojom::ServiceWorkerProviderType::kForWindow,
- pattern);
+ const int64_t kProviderId = 99;
+ mojom::ServiceWorkerProviderHostInfoPtr host_info_1 =
+ CreateProviderHostInfoForWindow(kProviderId, MSG_ROUTING_NONE);
+ RemoteProviderInfo remote_provider_1 =
+ SendProviderCreated(std::move(host_info_1));
+ ServiceWorkerProviderHost* provider_host = context()->GetProviderHost(
+ helper_->mock_render_process_id(), kProviderId);
SetUpRegistration(pattern, script_url);
- int64_t provider_id = provider_host_->provider_id();
+ EXPECT_EQ(kProviderId, provider_host->provider_id());
// Start up the worker.
bool called = false;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_ABORT;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorAbort;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
base::BindOnce(&SaveStatusCallback, &called, &status));
base::RunLoop().RunUntilIdle();
-
EXPECT_TRUE(called);
- EXPECT_EQ(SERVICE_WORKER_OK, status);
-
- EXPECT_TRUE(context()->GetProviderHost(process_id, provider_id));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
+ EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId));
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
- // Simulate the render process crashing.
- dispatcher_host_->OnFilterRemoved();
-
+ // Simulate that the corresponding renderer process died.
+ dispatcher_host_->RenderProcessExited(nullptr /* host */,
+ ChildProcessTerminationInfo());
+ base::RunLoop().RunUntilIdle();
// The dispatcher host should have removed the provider host.
- EXPECT_FALSE(context()->GetProviderHost(process_id, provider_id));
-
+ EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId));
// The EmbeddedWorkerInstance should still think it is running, since it will
// clean itself up when its Mojo connection to the renderer breaks.
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, 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
- // render process.
- auto new_dispatcher_host =
- base::MakeRefCounted<TestingServiceWorkerDispatcherHost>(process_id,
- helper_.get());
- new_dispatcher_host->Init(context_wrapper());
-
- // To show the new dispatcher can operate, simulate provider creation. Since
- // the old dispatcher cleaned up the old provider host, the new one won't
+ // Simulate that the browser process reused the dispatcher host due to reuse
+ // of the RenderProcessHost for another new renderer process, then the new
+ // renderer process creates a provider with the same |kProviderId|. Since the
+ // dispatcher host already cleaned up the old provider host, the new one won't
// complain.
- ServiceWorkerProviderHostInfo host_info(
- provider_id, MSG_ROUTING_NONE,
- blink::mojom::ServiceWorkerProviderType::kForWindow,
- true /* is_parent_frame_secure */);
- ServiceWorkerRemoteProviderEndpoint remote_endpoint;
- remote_endpoint.BindWithProviderHostInfo(&host_info);
- new_dispatcher_host->OnProviderCreated(std::move(host_info));
- EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_);
+ mojom::ServiceWorkerProviderHostInfoPtr host_info_2 =
+ CreateProviderHostInfoForWindow(kProviderId, MSG_ROUTING_NONE);
+ RemoteProviderInfo remote_provider_2 =
+ SendProviderCreated(std::move(host_info_2));
+ EXPECT_TRUE(bad_messages_.empty());
}
} // namespace service_worker_dispatcher_host_unittest
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 740ca70679f..dcc36e82bc0 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -24,11 +24,9 @@
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/url_loader_factory_getter.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "content/common/service_worker/service_worker_messages.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_features.h"
@@ -40,6 +38,9 @@
#include "net/log/net_log_event_type.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request.h"
+#include "services/network/throttling/throttling_controller.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
@@ -53,12 +54,14 @@ class DelegatingURLLoader final : public network::mojom::URLLoader {
: binding_(this), loader_(std::move(loader)) {}
~DelegatingURLLoader() override {}
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override {
DCHECK(!modified_request_headers.has_value())
<< "Redirect with modified headers was not supported yet. "
"crbug.com/845683";
- loader_->FollowRedirect(base::nullopt);
+ loader_->FollowRedirect(base::nullopt, base::nullopt);
}
void ProceedWithResponse() override { NOTREACHED(); }
@@ -166,9 +169,6 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
MaybeRunDevToolsCallbacks();
}
- void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {
- client_->OnDataDownloaded(data_length, encoded_length);
- }
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override {
@@ -181,10 +181,8 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
void OnTransferSizeUpdated(int32_t transfer_size_diff) override {
client_->OnTransferSizeUpdated(transfer_size_diff);
}
- void OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override {
- client_->OnReceiveResponse(head, std::move(downloaded_file));
+ void OnReceiveResponse(const network::ResourceResponseHead& head) override {
+ client_->OnReceiveResponse(head);
DCHECK(on_response_);
std::move(on_response_).Run();
if (!devtools_enabled_)
@@ -286,28 +284,29 @@ EventType ResourceTypeToEventType(ResourceType resource_type) {
}
std::unique_ptr<base::Value> NetLogServiceWorkerStatusCallback(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
net::NetLogCaptureMode) {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
- dict->SetString("status", ServiceWorkerStatusToString(status));
+ dict->SetString("status", blink::ServiceWorkerStatusToString(status));
return std::move(dict);
}
std::unique_ptr<base::Value> NetLogFetchEventCallback(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
ServiceWorkerFetchDispatcher::FetchEventResult result,
net::NetLogCaptureMode) {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
- dict->SetString("status", ServiceWorkerStatusToString(status));
+ dict->SetString("status", blink::ServiceWorkerStatusToString(status));
dict->SetBoolean(
"has_response",
result == ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse);
return std::move(dict);
}
-void EndNetLogEventWithServiceWorkerStatus(const net::NetLogWithSource& net_log,
- net::NetLogEventType type,
- ServiceWorkerStatusCode status) {
+void EndNetLogEventWithServiceWorkerStatus(
+ const net::NetLogWithSource& net_log,
+ net::NetLogEventType type,
+ blink::ServiceWorkerStatusCode status) {
net_log.EndEvent(type,
base::Bind(&NetLogServiceWorkerStatusCallback, status));
}
@@ -392,14 +391,6 @@ class ServiceWorkerFetchDispatcher::ResponseCallback
nullptr /* body_as_stream */, std::move(body_as_blob),
FetchEventResult::kGotResponse, dispatch_event_time);
}
- void OnResponseLegacyBlob(const ServiceWorkerResponse& response,
- base::Time dispatch_event_time,
- OnResponseLegacyBlobCallback callback) override {
- HandleResponse(fetch_dispatcher_, version_, fetch_event_id_, response,
- nullptr /* body_as_stream */, nullptr /* body_as_blob */,
- FetchEventResult::kGotResponse, dispatch_event_time);
- std::move(callback).Run();
- }
void OnResponseStream(
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
@@ -503,7 +494,7 @@ ServiceWorkerFetchDispatcher::ServiceWorkerFetchDispatcher(
did_complete_(false),
weak_factory_(this) {
#if DCHECK_IS_ON()
- if (ServiceWorkerUtils::IsServicificationEnabled()) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
DCHECK((request_body_blob_uuid_.empty() && request_body_blob_size_ == 0 &&
!request_body_blob_ && client_id_.empty()));
}
@@ -546,7 +537,7 @@ void ServiceWorkerFetchDispatcher::StartWorker() {
// before we could finish activation.
if (version_->status() != ServiceWorkerVersion::ACTIVATED) {
DCHECK_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
- DidFail(SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED);
+ DidFail(blink::ServiceWorkerStatusCode::kErrorActivateWorkerFailed);
return;
}
@@ -563,8 +554,8 @@ void ServiceWorkerFetchDispatcher::StartWorker() {
}
void ServiceWorkerFetchDispatcher::DidStartWorker(
- ServiceWorkerStatusCode status) {
- if (status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode status) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
EndNetLogEventWithServiceWorkerStatus(
net_log_, net::NetLogEventType::SERVICE_WORKER_START_WORKER, status);
DidFail(status);
@@ -609,18 +600,18 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
}
// Dispatch the fetch event.
- auto params = mojom::DispatchFetchEventParams::New();
+ auto params = blink::mojom::DispatchFetchEventParams::New();
params->request = *request_;
params->request_body_blob_uuid = request_body_blob_uuid_;
params->request_body_blob_size = request_body_blob_size_;
params->request_body_blob = request_body_blob_.PassInterface();
params->client_id = client_id_;
params->preload_handle = std::move(preload_handle_);
- // |event_dispatcher| is owned by |version_|. So it is safe to pass the
+ // |endpoint()| is owned by |version_|. So it is safe to pass the
// unretained raw pointer of |version_| to OnFetchEventFinished callback.
// Pass |url_loader_assets_| to the callback to keep the URL loader related
// assets alive while the FetchEvent is ongoing in the service worker.
- version_->event_dispatcher()->DispatchFetchEvent(
+ version_->endpoint()->DispatchFetchEvent(
std::move(params), std::move(response_callback_ptr),
base::BindOnce(&ServiceWorkerFetchDispatcher::OnFetchEventFinished,
base::Unretained(version_.get()), event_finish_id,
@@ -629,14 +620,15 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
void ServiceWorkerFetchDispatcher::DidFailToDispatch(
std::unique_ptr<ResponseCallback> response_callback,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
EndNetLogEventWithServiceWorkerStatus(
net_log_, net::NetLogEventType::SERVICE_WORKER_FETCH_EVENT, status);
DidFail(status);
}
-void ServiceWorkerFetchDispatcher::DidFail(ServiceWorkerStatusCode status) {
- DCHECK_NE(SERVICE_WORKER_OK, status);
+void ServiceWorkerFetchDispatcher::DidFail(
+ blink::ServiceWorkerStatusCode status) {
+ DCHECK_NE(blink::ServiceWorkerStatusCode::kOk, status);
Complete(status, FetchEventResult::kShouldFallback, ServiceWorkerResponse(),
nullptr /* body_as_stream */, nullptr /* body_as_blob */);
}
@@ -648,12 +640,12 @@ void ServiceWorkerFetchDispatcher::DidFinish(
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
blink::mojom::BlobPtr body_as_blob) {
net_log_.EndEvent(net::NetLogEventType::SERVICE_WORKER_FETCH_EVENT);
- Complete(SERVICE_WORKER_OK, fetch_result, response, std::move(body_as_stream),
- std::move(body_as_blob));
+ Complete(blink::ServiceWorkerStatusCode::kOk, fetch_result, response,
+ std::move(body_as_stream), std::move(body_as_blob));
}
void ServiceWorkerFetchDispatcher::Complete(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
FetchEventResult fetch_result,
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
@@ -723,6 +715,9 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
request.is_main_frame = original_info->IsMainFrame();
request.enable_load_timing = original_info->is_load_timing_enabled();
request.report_raw_headers = original_info->ShouldReportRawHeaders();
+ request.throttling_profile_id =
+ network::ThrottlingController::GetProfileIDForNetLogSource(
+ original_request->net_log().source().id);
DCHECK(net::HttpUtil::IsValidHeaderValue(
version_->navigation_preload_state().header));
@@ -735,7 +730,7 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
const int request_id = ResourceDispatcherHostImpl::Get()->MakeRequestID();
DCHECK_LT(request_id, -1);
- preload_handle_ = mojom::FetchEventPreloadHandle::New();
+ preload_handle_ = blink::mojom::FetchEventPreloadHandle::New();
network::mojom::URLLoaderClientPtr url_loader_client_ptr;
preload_handle_->url_loader_client_request =
mojo::MakeRequest(&url_loader_client_ptr);
@@ -795,7 +790,7 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreloadWithURLLoader(
"Service-Worker-Navigation-Preload",
version_->navigation_preload_state().header);
- preload_handle_ = mojom::FetchEventPreloadHandle::New();
+ preload_handle_ = blink::mojom::FetchEventPreloadHandle::New();
// Create the DelegatingURLLoaderClient, which becomes the
// URLLoaderClient for the navigation preload network request.
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 f2ac45ac5ca..29c19dca1fe 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -15,14 +15,14 @@
#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_event_dispatcher.mojom.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/resource_type.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/log/net_log_with_source.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
@@ -47,7 +47,7 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
};
using FetchCallback =
- base::OnceCallback<void(ServiceWorkerStatusCode,
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode,
FetchEventResult,
const ServiceWorkerResponse&,
blink::mojom::ServiceWorkerStreamHandlePtr,
@@ -80,9 +80,9 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
base::OnceClosure on_response);
// Dispatches a fetch event to the |version| given in ctor, and fires
- // |fetch_callback| (also given in ctor) when finishes. It runs
- // |prepare_callback| as an intermediate step once the version is activated
- // and running.
+ // |fetch_callback_| (also given in ctor) once a response is received from the
+ // service worker. It runs |prepare_callback_| as an intermediate step once
+ // the version is activated and running.
void Run();
private:
@@ -91,22 +91,26 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
void DidWaitForActivation();
void StartWorker();
- void DidStartWorker(ServiceWorkerStatusCode status);
+ void DidStartWorker(blink::ServiceWorkerStatusCode status);
void DispatchFetchEvent();
void DidFailToDispatch(std::unique_ptr<ResponseCallback> callback,
- ServiceWorkerStatusCode status);
- void DidFail(ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
+ void DidFail(blink::ServiceWorkerStatusCode status);
void DidFinish(int request_id,
FetchEventResult fetch_result,
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
blink::mojom::BlobPtr body_as_blob);
- void Complete(ServiceWorkerStatusCode status,
+ void Complete(blink::ServiceWorkerStatusCode status,
FetchEventResult fetch_result,
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
blink::mojom::BlobPtr body_as_blob);
+ // The fetch event stays open until all respondWith() and waitUntil() promises
+ // are settled. This function is called once the renderer signals that
+ // happened. |fetch_callback_| can run before this, once respondWith() is
+ // settled.
static void OnFetchEventFinished(
ServiceWorkerVersion* version,
int event_finish_id,
@@ -137,7 +141,7 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
// |preload_handle_| holds the URLLoader and URLLoaderClient for the service
// worker to receive the navigation preload response. It's passed to the
// service worker along with the fetch event.
- mojom::FetchEventPreloadHandlePtr preload_handle_;
+ blink::mojom::FetchEventPreloadHandlePtr preload_handle_;
base::WeakPtrFactory<ServiceWorkerFetchDispatcher> weak_factory_;
diff --git a/chromium/content/browser/service_worker/service_worker_installed_script_loader.cc b/chromium/content/browser/service_worker/service_worker_installed_script_loader.cc
index 09bba617925..4bd65c56647 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_script_loader.cc
+++ b/chromium/content/browser/service_worker/service_worker_installed_script_loader.cc
@@ -81,7 +81,15 @@ void ServiceWorkerInstalledScriptLoader::OnHttpInfoRead(
if (options_ & network::mojom::kURLLoadOptionSendSSLInfoWithResponse)
head.ssl_info = info->ssl_info;
- client_->OnReceiveResponse(head, nullptr /* downloaded_file */);
+ client_->OnReceiveResponse(head);
+
+ if (info->metadata) {
+ const uint8_t* data =
+ reinterpret_cast<const uint8_t*>(info->metadata->data());
+ client_->OnReceiveCachedMetadata(
+ std::vector<uint8_t>(data, data + info->metadata->size()));
+ }
+
client_->OnStartLoadingResponseBody(std::move(body_handle_));
// We continue in OnFinished().
}
@@ -111,6 +119,8 @@ void ServiceWorkerInstalledScriptLoader::OnFinished(FinishedReason reason) {
}
void ServiceWorkerInstalledScriptLoader::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
// This class never returns a redirect response to its client, so should never
// be asked to follow one.
diff --git a/chromium/content/browser/service_worker/service_worker_installed_script_loader.h b/chromium/content/browser/service_worker/service_worker_installed_script_loader.h
index 89a412e2270..f006e3b17d6 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_script_loader.h
+++ b/chromium/content/browser/service_worker/service_worker_installed_script_loader.h
@@ -48,7 +48,9 @@ class CONTENT_EXPORT ServiceWorkerInstalledScriptLoader
ServiceWorkerInstalledScriptReader::FinishedReason reason) override;
// network::mojom::URLLoader overrides:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
diff --git a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc
index c7dd5fee1e2..7e35d7ae938 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc
+++ b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc
@@ -166,7 +166,8 @@ void ServiceWorkerInstalledScriptsSender::Abort(
case ServiceWorkerInstalledScriptReader::FinishedReason::kNoHttpInfoError:
case ServiceWorkerInstalledScriptReader::FinishedReason::
kResponseReaderError:
- owner_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_DISK_CACHE);
+ owner_->SetStartWorkerStatusCode(
+ blink::ServiceWorkerStatusCode::kErrorDiskCache);
// Abort the worker by deleting from the registration since the data was
// corrupted.
if (owner_->context()) {
diff --git a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
index 4a441aaf7e2..db4c5af12d0 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
@@ -7,7 +7,7 @@
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.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_disk_cache.h"
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 5fba22499c9..3b93dc19aa0 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
@@ -50,7 +50,7 @@ using GetRegistrationsCallback =
void OperationCompleteCallback(WeakPtr<ServiceWorkerInternalsUI> internals,
int callback_id,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::BindOnce(OperationCompleteCallback, internals,
@@ -206,7 +206,7 @@ std::unique_ptr<ListValue> GetVersionListValue(
void DidGetStoredRegistrationsOnIOThread(
scoped_refptr<ServiceWorkerContextWrapper> context,
const GetRegistrationsCallback& callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
@@ -268,15 +268,11 @@ class ServiceWorkerInternalsUI::PartitionObserver
Value(base::Int64ToString(version_id)));
}
void OnErrorReported(int64_t version_id,
- int process_id,
- int thread_id,
const ErrorInfo& info) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::vector<std::unique_ptr<const Value>> args;
args.push_back(std::make_unique<Value>(partition_id_));
args.push_back(std::make_unique<Value>(base::Int64ToString(version_id)));
- args.push_back(std::make_unique<Value>(process_id));
- args.push_back(std::make_unique<Value>(thread_id));
auto value = std::make_unique<DictionaryValue>();
value->SetString("message", info.error_message);
value->SetInteger("lineNumber", info.line_number);
@@ -287,15 +283,11 @@ class ServiceWorkerInternalsUI::PartitionObserver
ConvertToRawPtrVector(args));
}
void OnReportConsoleMessage(int64_t version_id,
- int process_id,
- int thread_id,
const ConsoleMessage& message) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::vector<std::unique_ptr<const Value>> args;
args.push_back(std::make_unique<Value>(partition_id_));
args.push_back(std::make_unique<Value>(base::Int64ToString(version_id)));
- args.push_back(std::make_unique<Value>(process_id));
- args.push_back(std::make_unique<Value>(thread_id));
auto value = std::make_unique<DictionaryValue>();
value->SetInteger("sourceIdentifier", message.source_identifier);
value->SetInteger("message_level", message.message_level);
@@ -328,6 +320,8 @@ ServiceWorkerInternalsUI::ServiceWorkerInternalsUI(WebUI* web_ui)
: WebUIController(web_ui), next_partition_id_(0) {
WebUIDataSource* source =
WebUIDataSource::Create(kChromeUIServiceWorkerInternalsHost);
+ source->OverrideContentSecurityPolicyScriptSrc(
+ "script-src chrome://resources 'self' 'unsafe-eval';");
source->SetJsonPath("strings.js");
source->AddResourcePath("serviceworker_internals.js",
IDR_SERVICE_WORKER_INTERNALS_JS);
@@ -496,7 +490,7 @@ void ServiceWorkerInternalsUI::StopWorker(const ListValue* args) {
return;
}
- base::OnceCallback<void(ServiceWorkerStatusCode)> callback =
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)> callback =
base::BindOnce(OperationCompleteCallback, AsWeakPtr(), callback_id);
StopWorkerWithId(context, version_id, std::move(callback));
}
@@ -514,18 +508,18 @@ void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) {
&devtools_agent_route_id)) {
return;
}
- base::Callback<void(ServiceWorkerStatusCode)> callback =
- base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)> callback =
+ base::BindOnce(OperationCompleteCallback, AsWeakPtr(), callback_id);
scoped_refptr<ServiceWorkerDevToolsAgentHost> agent_host(
ServiceWorkerDevToolsManager::GetInstance()
->GetDevToolsAgentHostForWorker(process_host_id,
devtools_agent_route_id));
if (!agent_host.get()) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_NOT_FOUND);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorNotFound);
return;
}
agent_host->Inspect();
- std::move(callback).Run(SERVICE_WORKER_OK);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk);
}
void ServiceWorkerInternalsUI::Unregister(const ListValue* args) {
@@ -543,8 +537,8 @@ void ServiceWorkerInternalsUI::Unregister(const ListValue* args) {
return;
}
- base::Callback<void(ServiceWorkerStatusCode)> callback =
- base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)> callback =
+ base::BindOnce(OperationCompleteCallback, AsWeakPtr(), callback_id);
UnregisterWithScope(context, GURL(scope_string), std::move(callback));
}
@@ -562,8 +556,8 @@ void ServiceWorkerInternalsUI::StartWorker(const ListValue* args) {
!cmd_args->GetString("scope", &scope_string)) {
return;
}
- base::Callback<void(ServiceWorkerStatusCode)> callback =
- base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)> callback =
+ base::BindOnce(OperationCompleteCallback, AsWeakPtr(), callback_id);
context->StartServiceWorker(GURL(scope_string), std::move(callback));
}
@@ -583,13 +577,14 @@ void ServiceWorkerInternalsUI::StopWorkerWithId(
scoped_refptr<ServiceWorkerVersion> version =
context->GetLiveVersion(version_id);
if (!version.get()) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_NOT_FOUND);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorNotFound);
return;
}
// ServiceWorkerVersion::StopWorker() takes a base::OnceClosure for argument,
- // so bind SERVICE_WORKER_OK to callback here.
- version->StopWorker(base::BindOnce(std::move(callback), SERVICE_WORKER_OK));
+ // so bind blink::ServiceWorkerStatusCode::kOk to callback here.
+ version->StopWorker(
+ base::BindOnce(std::move(callback), blink::ServiceWorkerStatusCode::kOk));
}
void ServiceWorkerInternalsUI::UnregisterWithScope(
@@ -606,7 +601,7 @@ void ServiceWorkerInternalsUI::UnregisterWithScope(
}
if (!context->context()) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort);
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 b9237da3b73..38dafe15874 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.h
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.h
@@ -12,8 +12,8 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/browser/web_ui_controller.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace base {
class ListValue;
@@ -28,15 +28,16 @@ class ServiceWorkerInternalsUI
: public WebUIController,
public base::SupportsWeakPtr<ServiceWorkerInternalsUI> {
public:
- using StatusCallback = base::OnceCallback<void(ServiceWorkerStatusCode)>;
+ using StatusCallback =
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)>;
explicit ServiceWorkerInternalsUI(WebUI* web_ui);
+ ~ServiceWorkerInternalsUI() override;
private:
class OperationProxy;
class PartitionObserver;
- ~ServiceWorkerInternalsUI() override;
void AddContextFromStoragePartition(StoragePartition* partition);
void RemoveObserverFromStoragePartition(StoragePartition* partition);
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 f39721041ba..724ffb5a524 100644
--- a/chromium/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
@@ -18,8 +18,8 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/browser/service_worker/service_worker_handle.h"
#include "content/browser/service_worker/service_worker_job_coordinator.h"
+#include "content/browser/service_worker/service_worker_object_host.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_registration_object_host.h"
#include "content/browser/service_worker/service_worker_registration_status.h"
@@ -49,10 +49,10 @@ namespace content {
namespace {
void SaveRegistrationCallback(
- ServiceWorkerStatusCode expected_status,
+ blink::ServiceWorkerStatusCode expected_status,
bool* called,
scoped_refptr<ServiceWorkerRegistration>* registration_out,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
ServiceWorkerRegistration* registration) {
EXPECT_EQ(expected_status, status);
@@ -61,10 +61,10 @@ void SaveRegistrationCallback(
}
void SaveFoundRegistrationCallback(
- ServiceWorkerStatusCode expected_status,
+ blink::ServiceWorkerStatusCode expected_status,
bool* called,
scoped_refptr<ServiceWorkerRegistration>* registration,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> result) {
EXPECT_EQ(expected_status, status);
*called = true;
@@ -77,7 +77,7 @@ void SaveFoundRegistrationCallback(
// 'called' is useful for making sure a sychronous callback is or
// isn't called.
ServiceWorkerRegisterJob::RegistrationCallback SaveRegistration(
- ServiceWorkerStatusCode expected_status,
+ blink::ServiceWorkerStatusCode expected_status,
bool* called,
scoped_refptr<ServiceWorkerRegistration>* registration) {
*called = false;
@@ -86,7 +86,7 @@ ServiceWorkerRegisterJob::RegistrationCallback SaveRegistration(
}
ServiceWorkerStorage::FindRegistrationCallback SaveFoundRegistration(
- ServiceWorkerStatusCode expected_status,
+ blink::ServiceWorkerStatusCode expected_status,
bool* called,
scoped_refptr<ServiceWorkerRegistration>* registration) {
*called = false;
@@ -94,16 +94,16 @@ ServiceWorkerStorage::FindRegistrationCallback SaveFoundRegistration(
registration);
}
-void SaveUnregistrationCallback(ServiceWorkerStatusCode expected_status,
+void SaveUnregistrationCallback(blink::ServiceWorkerStatusCode expected_status,
bool* called,
int64_t registration_id,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
EXPECT_EQ(expected_status, status);
*called = true;
}
ServiceWorkerUnregisterJob::UnregistrationCallback SaveUnregistration(
- ServiceWorkerStatusCode expected_status,
+ blink::ServiceWorkerStatusCode expected_status,
bool* called) {
*called = false;
return base::BindOnce(&SaveUnregistrationCallback, expected_status, called);
@@ -133,13 +133,15 @@ class ServiceWorkerJobTest : public testing::Test {
scoped_refptr<ServiceWorkerRegistration> RunRegisterJob(
const GURL& script_url,
const blink::mojom::ServiceWorkerRegistrationOptions& options,
- ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK);
- void RunUnregisterJob(
- const GURL& pattern,
- ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK);
+ blink::ServiceWorkerStatusCode expected_status =
+ blink::ServiceWorkerStatusCode::kOk);
+ void RunUnregisterJob(const GURL& pattern,
+ blink::ServiceWorkerStatusCode expected_status =
+ blink::ServiceWorkerStatusCode::kOk);
scoped_refptr<ServiceWorkerRegistration> FindRegistrationForPattern(
const GURL& pattern,
- ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK);
+ blink::ServiceWorkerStatusCode expected_status =
+ blink::ServiceWorkerStatusCode::kOk);
ServiceWorkerProviderHost* CreateControllee();
TestBrowserThreadBundle browser_thread_bundle_;
@@ -150,7 +152,7 @@ class ServiceWorkerJobTest : public testing::Test {
scoped_refptr<ServiceWorkerRegistration> ServiceWorkerJobTest::RunRegisterJob(
const GURL& script_url,
const blink::mojom::ServiceWorkerRegistrationOptions& options,
- ServiceWorkerStatusCode expected_status) {
+ blink::ServiceWorkerStatusCode expected_status) {
scoped_refptr<ServiceWorkerRegistration> registration;
bool called;
job_coordinator()->Register(
@@ -164,7 +166,7 @@ scoped_refptr<ServiceWorkerRegistration> ServiceWorkerJobTest::RunRegisterJob(
void ServiceWorkerJobTest::RunUnregisterJob(
const GURL& pattern,
- ServiceWorkerStatusCode expected_status) {
+ blink::ServiceWorkerStatusCode expected_status) {
bool called;
job_coordinator()->Unregister(pattern,
SaveUnregistration(expected_status, &called));
@@ -176,7 +178,7 @@ void ServiceWorkerJobTest::RunUnregisterJob(
scoped_refptr<ServiceWorkerRegistration>
ServiceWorkerJobTest::FindRegistrationForPattern(
const GURL& pattern,
- ServiceWorkerStatusCode expected_status) {
+ blink::ServiceWorkerStatusCode expected_status) {
bool called;
scoped_refptr<ServiceWorkerRegistration> registration;
storage()->FindRegistrationForPattern(
@@ -211,11 +213,13 @@ TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
scoped_refptr<ServiceWorkerRegistration> registration1;
storage()->FindRegistrationForDocument(
GURL("https://www.example.com/"),
- SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration1));
+ SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk, &called,
+ &registration1));
scoped_refptr<ServiceWorkerRegistration> registration2;
storage()->FindRegistrationForDocument(
GURL("https://www.example.com/"),
- SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration2));
+ SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk, &called,
+ &registration2));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
ASSERT_TRUE(registration1.get());
@@ -236,14 +240,16 @@ TEST_F(ServiceWorkerJobTest, SameMatchSameRegistration) {
scoped_refptr<ServiceWorkerRegistration> registration1;
storage()->FindRegistrationForDocument(
GURL("https://www.example.com/one"),
- SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration1));
+ SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk, &called,
+ &registration1));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
scoped_refptr<ServiceWorkerRegistration> registration2;
storage()->FindRegistrationForDocument(
GURL("https://www.example.com/two"),
- SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration2));
+ SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk, &called,
+ &registration2));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
ASSERT_EQ(registration1, original_registration);
@@ -257,7 +263,8 @@ TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
scoped_refptr<ServiceWorkerRegistration> original_registration1;
job_coordinator()->Register(
GURL("https://www.example.com/service_worker.js"), options1,
- SaveRegistration(SERVICE_WORKER_OK, &called1, &original_registration1));
+ SaveRegistration(blink::ServiceWorkerStatusCode::kOk, &called1,
+ &original_registration1));
bool called2;
blink::mojom::ServiceWorkerRegistrationOptions options2;
@@ -265,7 +272,8 @@ TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
scoped_refptr<ServiceWorkerRegistration> original_registration2;
job_coordinator()->Register(
GURL("https://www.example.com/service_worker.js"), options2,
- SaveRegistration(SERVICE_WORKER_OK, &called2, &original_registration2));
+ SaveRegistration(blink::ServiceWorkerStatusCode::kOk, &called2,
+ &original_registration2));
EXPECT_FALSE(called1);
EXPECT_FALSE(called2);
@@ -276,11 +284,13 @@ TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
scoped_refptr<ServiceWorkerRegistration> registration1;
storage()->FindRegistrationForDocument(
GURL("https://www.example.com/one/"),
- SaveFoundRegistration(SERVICE_WORKER_OK, &called1, &registration1));
+ SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk, &called1,
+ &registration1));
scoped_refptr<ServiceWorkerRegistration> registration2;
storage()->FindRegistrationForDocument(
GURL("https://www.example.com/two/"),
- SaveFoundRegistration(SERVICE_WORKER_OK, &called2, &registration2));
+ SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk, &called2,
+ &registration2));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called2);
@@ -316,23 +326,23 @@ TEST_F(ServiceWorkerJobTest, Unregister) {
// One ServiceWorkerRegistrationObjectHost should have been created for the
// new registration.
EXPECT_EQ(1UL, provider_host->registration_object_hosts_.size());
- // One ServiceWorkerHandle should have been created for the new service
+ // One ServiceWorkerObjectHost should have been created for the new service
// worker.
- EXPECT_EQ(1UL, provider_host->handles_.size());
+ EXPECT_EQ(1UL, provider_host->service_worker_object_hosts_.size());
RunUnregisterJob(options.scope);
- // The service worker registration object host and service worker handle have
- // been destroyed together with |provider_host| by the above unregistration.
- // Then |registration| and |version| should be the last one reference to the
- // corresponding instance.
+ // The service worker registration object host and service worker object host
+ // have been destroyed together with |provider_host| by the above
+ // unregistration. Then |registration| and |version| should be the last one
+ // reference to the corresponding instance.
EXPECT_TRUE(registration->HasOneRef());
EXPECT_TRUE(version->HasOneRef());
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
- registration =
- FindRegistrationForPattern(options.scope, SERVICE_WORKER_ERROR_NOT_FOUND);
+ registration = FindRegistrationForPattern(
+ options.scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
EXPECT_FALSE(registration);
}
@@ -340,7 +350,7 @@ TEST_F(ServiceWorkerJobTest, Unregister) {
TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) {
GURL pattern("https://www.example.com/");
- RunUnregisterJob(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
+ RunUnregisterJob(pattern, blink::ServiceWorkerStatusCode::kErrorNotFound);
}
// Make sure registering a new script creates a new version and shares an
@@ -386,8 +396,8 @@ TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
old_registration->active_version()->provider_host();
ASSERT_NE(nullptr, provider_host);
- // Clear all service worker handles.
- provider_host->handles_.clear();
+ // Clear all service worker object hosts.
+ provider_host->service_worker_object_hosts_.clear();
// Ensure that the registration's object host doesn't have the reference.
EXPECT_EQ(1UL, provider_host->registration_object_hosts_.size());
provider_host->registration_object_hosts_.clear();
@@ -433,8 +443,8 @@ TEST_F(ServiceWorkerJobTest, RegisterWithDifferentUpdateViaCache) {
old_registration->active_version()->provider_host();
ASSERT_NE(nullptr, provider_host);
- // Clear all service worker handles.
- provider_host->handles_.clear();
+ // Clear all service worker object hosts.
+ provider_host->service_worker_object_hosts_.clear();
// Ensure that the registration's object host doesn't have the reference.
EXPECT_EQ(1UL, provider_host->registration_object_hosts_.size());
provider_host->registration_object_hosts_.clear();
@@ -473,7 +483,7 @@ class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
const GURL& scope,
const GURL& script_url,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -493,7 +503,7 @@ TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
options.scope = GURL("https://www.example.com/");
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(GURL("https://www.example.com/service_worker.js"), options,
- SERVICE_WORKER_ERROR_START_WORKER_FAILED);
+ blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed);
ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(nullptr), registration);
}
@@ -509,12 +519,13 @@ TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
scoped_refptr<ServiceWorkerRegistration> registration;
job_coordinator()->Register(
script_url, options,
- SaveRegistration(SERVICE_WORKER_OK, &registration_called, &registration));
+ SaveRegistration(blink::ServiceWorkerStatusCode::kOk,
+ &registration_called, &registration));
bool unregistration_called = false;
job_coordinator()->Unregister(
- options.scope,
- SaveUnregistration(SERVICE_WORKER_OK, &unregistration_called));
+ options.scope, SaveUnregistration(blink::ServiceWorkerStatusCode::kOk,
+ &unregistration_called));
ASSERT_FALSE(registration_called);
ASSERT_FALSE(unregistration_called);
@@ -522,8 +533,8 @@ TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
ASSERT_TRUE(registration_called);
ASSERT_TRUE(unregistration_called);
- registration =
- FindRegistrationForPattern(options.scope, SERVICE_WORKER_ERROR_NOT_FOUND);
+ registration = FindRegistrationForPattern(
+ options.scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
}
@@ -541,8 +552,8 @@ TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
script_url1,
blink::mojom::ServiceWorkerRegistrationOptions(
pattern, blink::mojom::ServiceWorkerUpdateViaCache::kNone),
- SaveRegistration(SERVICE_WORKER_OK, &registration1_called,
- &registration1));
+ SaveRegistration(blink::ServiceWorkerStatusCode::kOk,
+ &registration1_called, &registration1));
GURL script_url2("https://www.example.com/service_worker2.js");
bool registration2_called = false;
@@ -551,8 +562,8 @@ TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
script_url2,
blink::mojom::ServiceWorkerRegistrationOptions(
pattern, blink::mojom::ServiceWorkerUpdateViaCache::kAll),
- SaveRegistration(SERVICE_WORKER_OK, &registration2_called,
- &registration2));
+ SaveRegistration(blink::ServiceWorkerStatusCode::kOk,
+ &registration2_called, &registration2));
ASSERT_FALSE(registration1_called);
ASSERT_FALSE(registration2_called);
@@ -578,15 +589,15 @@ TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
scoped_refptr<ServiceWorkerRegistration> registration1;
job_coordinator()->Register(
script_url, options,
- SaveRegistration(SERVICE_WORKER_OK, &registration1_called,
- &registration1));
+ SaveRegistration(blink::ServiceWorkerStatusCode::kOk,
+ &registration1_called, &registration1));
bool registration2_called = false;
scoped_refptr<ServiceWorkerRegistration> registration2;
job_coordinator()->Register(
script_url, options,
- SaveRegistration(SERVICE_WORKER_OK, &registration2_called,
- &registration2));
+ SaveRegistration(blink::ServiceWorkerStatusCode::kOk,
+ &registration2_called, &registration2));
ASSERT_FALSE(registration1_called);
ASSERT_FALSE(registration2_called);
@@ -610,13 +621,13 @@ TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
bool unregistration1_called = false;
job_coordinator()->Unregister(
pattern,
- SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND,
+ SaveUnregistration(blink::ServiceWorkerStatusCode::kErrorNotFound,
&unregistration1_called));
bool unregistration2_called = false;
job_coordinator()->Unregister(
pattern,
- SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND,
+ SaveUnregistration(blink::ServiceWorkerStatusCode::kErrorNotFound,
&unregistration2_called));
ASSERT_FALSE(unregistration1_called);
@@ -629,7 +640,8 @@ TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
// but we can make sure they can exist simultaneously without
// crashing.
scoped_refptr<ServiceWorkerRegistration> registration =
- FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
+ FindRegistrationForPattern(
+ pattern, blink::ServiceWorkerStatusCode::kErrorNotFound);
ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
}
@@ -647,15 +659,15 @@ TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
scoped_refptr<ServiceWorkerRegistration> registration1;
job_coordinator()->Register(
script_url1, options1,
- SaveRegistration(SERVICE_WORKER_ERROR_ABORT, &registration_called1,
- &registration1));
+ SaveRegistration(blink::ServiceWorkerStatusCode::kErrorAbort,
+ &registration_called1, &registration1));
bool registration_called2 = false;
scoped_refptr<ServiceWorkerRegistration> registration2;
job_coordinator()->Register(
script_url2, options2,
- SaveRegistration(SERVICE_WORKER_ERROR_ABORT, &registration_called2,
- &registration2));
+ SaveRegistration(blink::ServiceWorkerStatusCode::kErrorAbort,
+ &registration_called2, &registration2));
ASSERT_FALSE(registration_called1);
ASSERT_FALSE(registration_called2);
@@ -667,13 +679,15 @@ TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
bool find_called1 = false;
storage()->FindRegistrationForPattern(
- options1.scope, SaveFoundRegistration(SERVICE_WORKER_ERROR_NOT_FOUND,
- &find_called1, &registration1));
+ options1.scope,
+ SaveFoundRegistration(blink::ServiceWorkerStatusCode::kErrorNotFound,
+ &find_called1, &registration1));
bool find_called2 = false;
storage()->FindRegistrationForPattern(
- options2.scope, SaveFoundRegistration(SERVICE_WORKER_ERROR_NOT_FOUND,
- &find_called2, &registration2));
+ options2.scope,
+ SaveFoundRegistration(blink::ServiceWorkerStatusCode::kErrorNotFound,
+ &find_called2, &registration2));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(find_called1);
@@ -689,15 +703,13 @@ TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
bool unregistration_called1 = false;
scoped_refptr<ServiceWorkerRegistration> registration1;
job_coordinator()->Unregister(
- pattern1,
- SaveUnregistration(SERVICE_WORKER_ERROR_ABORT,
- &unregistration_called1));
+ pattern1, SaveUnregistration(blink::ServiceWorkerStatusCode::kErrorAbort,
+ &unregistration_called1));
bool unregistration_called2 = false;
job_coordinator()->Unregister(
- pattern2,
- SaveUnregistration(SERVICE_WORKER_ERROR_ABORT,
- &unregistration_called2));
+ pattern2, SaveUnregistration(blink::ServiceWorkerStatusCode::kErrorAbort,
+ &unregistration_called2));
ASSERT_FALSE(unregistration_called1);
ASSERT_FALSE(unregistration_called2);
@@ -717,13 +729,14 @@ TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
scoped_refptr<ServiceWorkerRegistration> registration;
job_coordinator()->Register(
script_url, options,
- SaveRegistration(SERVICE_WORKER_ERROR_ABORT, &registration_called,
- &registration));
+ SaveRegistration(blink::ServiceWorkerStatusCode::kErrorAbort,
+ &registration_called, &registration));
bool unregistration_called = false;
job_coordinator()->Unregister(
options.scope,
- SaveUnregistration(SERVICE_WORKER_ERROR_ABORT, &unregistration_called));
+ SaveUnregistration(blink::ServiceWorkerStatusCode::kErrorAbort,
+ &unregistration_called));
ASSERT_FALSE(registration_called);
ASSERT_FALSE(unregistration_called);
@@ -733,8 +746,8 @@ TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
ASSERT_TRUE(registration_called);
ASSERT_TRUE(unregistration_called);
- registration =
- FindRegistrationForPattern(options.scope, SERVICE_WORKER_ERROR_NOT_FOUND);
+ registration = FindRegistrationForPattern(
+ options.scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
}
@@ -753,11 +766,11 @@ TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
// waiting worker until Update is implemented.
scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
registration.get(), script_url, 1L, helper_->context()->AsWeakPtr());
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
version->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(SERVICE_WORKER_OK, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
version->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
@@ -877,10 +890,9 @@ void WriteStringResponse(ServiceWorkerStorage* storage,
WriteResponse(storage, id, headers, body_buffer.get(), body.length());
}
-class UpdateJobTestHelper
- : public EmbeddedWorkerTestHelper,
- public ServiceWorkerRegistration::Listener,
- public ServiceWorkerVersion::Listener {
+class UpdateJobTestHelper : public EmbeddedWorkerTestHelper,
+ public ServiceWorkerRegistration::Listener,
+ public ServiceWorkerVersion::Observer {
public:
struct AttributeChangeLogEntry {
int64_t registration_id;
@@ -898,7 +910,7 @@ class UpdateJobTestHelper
if (observed_registration_.get())
observed_registration_->RemoveListener(this);
for (auto& version : observed_versions_)
- version->RemoveListener(this);
+ version->RemoveObserver(this);
}
ServiceWorkerStorage* storage() { return context()->storage(); }
@@ -918,7 +930,8 @@ class UpdateJobTestHelper
bool called = false;
job_coordinator()->Register(
test_origin.Resolve(kScript), options,
- SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
+ SaveRegistration(blink::ServiceWorkerStatusCode::kOk, &called,
+ &registration));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
EXPECT_TRUE(registration.get());
@@ -936,7 +949,7 @@ class UpdateJobTestHelper
const GURL& scope,
const GURL& script,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -952,7 +965,7 @@ class UpdateJobTestHelper
ASSERT_TRUE(version);
observed_versions_.push_back(base::WrapRefCounted(version));
- version->AddListener(this);
+ version->AddObserver(this);
// Simulate network access.
base::TimeDelta time_since_last_check =
@@ -998,7 +1011,7 @@ class UpdateJobTestHelper
started_workers_.insert(embedded_worker_id);
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id, version_id, scope, script, pause_after_download,
- std::move(dispatcher_request), std::move(controller_request),
+ std::move(service_worker_request), std::move(controller_request),
std::move(instance_host), std::move(provider_info),
std::move(installed_scripts_info));
}
@@ -1014,12 +1027,15 @@ class UpdateJobTestHelper
}
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);
+ if (force_start_worker_failure_) {
+ SimulateScriptEvaluationStart(embedded_worker_id);
+ SimulateWorkerStarted(
+ embedded_worker_id,
+ blink::mojom::ServiceWorkerStartStatus::kAbruptCompletion,
+ GetNextThreadId());
+ return;
}
+ EmbeddedWorkerTestHelper::OnResumeAfterDownload(embedded_worker_id);
}
// ServiceWorkerRegistration::Listener overrides
@@ -1042,7 +1058,7 @@ class UpdateJobTestHelper
update_found_ = true;
}
- // ServiceWorkerVersion::Listener overrides
+ // ServiceWorkerVersion::Observer overrides
void OnVersionStateChanged(ServiceWorkerVersion* version) override {
StateChangeLogEntry entry;
entry.version_id = version->version_id();
@@ -1073,7 +1089,7 @@ class EvictIncumbentVersionHelper : public UpdateJobTestHelper {
const GURL& scope,
const GURL& script,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -1092,7 +1108,7 @@ class EvictIncumbentVersionHelper : public UpdateJobTestHelper {
}
UpdateJobTestHelper::OnStartWorker(
embedded_worker_id, version_id, scope, script, pause_after_download,
- std::move(dispatcher_request), std::move(controller_request),
+ std::move(service_worker_request), std::move(controller_request),
std::move(instance_host), std::move(provider_info),
std::move(installed_scripts_info));
}
@@ -1354,8 +1370,9 @@ TEST_F(ServiceWorkerJobTest, Update_UninstallingRegistration) {
ServiceWorkerProviderHost* host = CreateControllee();
ServiceWorkerVersion* active_version = registration->active_version();
active_version->AddControllee(host);
- job_coordinator()->Unregister(GURL("https://www.example.com/one/"),
- SaveUnregistration(SERVICE_WORKER_OK, &called));
+ job_coordinator()->Unregister(
+ GURL("https://www.example.com/one/"),
+ SaveUnregistration(blink::ServiceWorkerStatusCode::kOk, &called));
// Update should abort after it starts and sees uninstalling.
job_coordinator()->Update(registration.get(), false);
@@ -1449,9 +1466,11 @@ TEST_F(ServiceWorkerJobTest, RegisterAndUnregisterWhileUninstalling) {
// Unregister the registration (but it's still live).
RunUnregisterJob(options.scope);
// Now it's not found in the storage.
- RunUnregisterJob(options.scope, SERVICE_WORKER_ERROR_NOT_FOUND);
+ RunUnregisterJob(options.scope,
+ blink::ServiceWorkerStatusCode::kErrorNotFound);
- FindRegistrationForPattern(options.scope, SERVICE_WORKER_ERROR_NOT_FOUND);
+ FindRegistrationForPattern(options.scope,
+ blink::ServiceWorkerStatusCode::kErrorNotFound);
EXPECT_TRUE(registration->is_uninstalling());
EXPECT_EQ(old_version, registration->active_version());
@@ -1591,8 +1610,7 @@ class EventCallbackHelper : public EmbeddedWorkerTestHelper {
blink::mojom::ServiceWorkerEventStatus::COMPLETED) {}
void OnInstallEvent(
- mojom::ServiceWorkerEventDispatcher::DispatchInstallEventCallback
- callback) override {
+ mojom::ServiceWorker::DispatchInstallEventCallback callback) override {
if (!install_callback_.is_null())
install_callback_.Run();
std::move(callback).Run(install_event_result_, has_fetch_handler_,
@@ -1600,8 +1618,7 @@ class EventCallbackHelper : public EmbeddedWorkerTestHelper {
}
void OnActivateEvent(
- mojom::ServiceWorkerEventDispatcher::DispatchActivateEventCallback
- callback) override {
+ mojom::ServiceWorker::DispatchActivateEventCallback callback) override {
std::move(callback).Run(activate_event_result_, base::Time::Now());
}
@@ -1702,7 +1719,8 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringRejectedInstall) {
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, old_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
- FindRegistrationForPattern(options.scope, SERVICE_WORKER_ERROR_NOT_FOUND);
+ FindRegistrationForPattern(options.scope,
+ blink::ServiceWorkerStatusCode::kErrorNotFound);
}
TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) {
@@ -1740,7 +1758,8 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) {
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, old_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
- FindRegistrationForPattern(options.scope, SERVICE_WORKER_OK);
+ FindRegistrationForPattern(options.scope,
+ blink::ServiceWorkerStatusCode::kOk);
}
TEST_F(ServiceWorkerJobTest, HasFetchHandler) {
diff --git a/chromium/content/browser/service_worker/service_worker_lifetime_tracker_unittest.cc b/chromium/content/browser/service_worker/service_worker_lifetime_tracker_unittest.cc
index 9b42bdbfa73..c8a912123f0 100644
--- a/chromium/content/browser/service_worker/service_worker_lifetime_tracker_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_lifetime_tracker_unittest.cc
@@ -4,7 +4,7 @@
#include "content/browser/service_worker/service_worker_lifetime_tracker.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/tick_clock.h"
#include "content/public/test/test_utils.h"
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.cc b/chromium/content/browser/service_worker/service_worker_metrics.cc
index f5fc5073da2..40bd68cfec9 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.cc
+++ b/chromium/content/browser/service_worker/service_worker_metrics.cc
@@ -16,6 +16,7 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "net/url_request/url_request.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
@@ -28,18 +29,30 @@ std::string StartSituationToSuffix(
switch (situation) {
case ServiceWorkerMetrics::StartSituation::UNKNOWN:
NOTREACHED();
- return "_Unknown";
+ return ".Unknown";
case ServiceWorkerMetrics::StartSituation::DURING_STARTUP:
- return "_DuringStartup";
+ return ".DuringStartup";
case ServiceWorkerMetrics::StartSituation::NEW_PROCESS:
- return "_NewProcess";
+ return ".NewProcess";
case ServiceWorkerMetrics::StartSituation::EXISTING_UNREADY_PROCESS:
- return "_ExistingUnreadyProcess";
+ return ".ExistingUnreadyProcess";
case ServiceWorkerMetrics::StartSituation::EXISTING_READY_PROCESS:
- return "_ExistingReadyProcess";
+ return ".ExistingReadyProcess";
}
NOTREACHED() << static_cast<int>(situation);
- return "_Unknown";
+ return ".Unknown";
+}
+
+// TODO(falken): Remove this when the associated UMA are removed.
+std::string StartSituationToDeprecatedSuffix(
+ ServiceWorkerMetrics::StartSituation situation) {
+ // Don't change this returned string. It is written (in hashed form) into
+ // logs.
+ std::string suffix = StartSituationToSuffix(situation);
+ // Replace '.' separator with '_'.
+ DCHECK(suffix.length() > 1 && suffix[0] == '.');
+ suffix[0] = '_';
+ return suffix;
}
std::string EventTypeToSuffix(ServiceWorkerMetrics::EventType event_type) {
@@ -160,27 +173,6 @@ std::string GetWorkerPreparationSuffix(
return "_UNKNOWN";
}
-std::string GetSiteSuffix(ServiceWorkerMetrics::Site site) {
- switch (site) {
- case ServiceWorkerMetrics::Site::OTHER:
- case ServiceWorkerMetrics::Site::WITH_FETCH_HANDLER:
- case ServiceWorkerMetrics::Site::WITHOUT_FETCH_HANDLER:
- return "";
- case ServiceWorkerMetrics::Site::NEW_TAB_PAGE:
- return ".ntp";
- case ServiceWorkerMetrics::Site::PLUS:
- return ".plus";
- case ServiceWorkerMetrics::Site::INBOX:
- return ".inbox";
- case ServiceWorkerMetrics::Site::DOCS:
- return ".docs";
- case ServiceWorkerMetrics::Site::NUM_TYPES:
- NOTREACHED() << static_cast<int>(site);
- }
- NOTREACHED();
- return "";
-}
-
// 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,
@@ -224,72 +216,22 @@ void RecordURLMetricOnUI(const std::string& metric_name, const GURL& url) {
GetContentClient()->browser()->RecordURLMetric(metric_name, url);
}
-enum EventHandledRatioType {
- EVENT_HANDLED_NONE,
- EVENT_HANDLED_SOME,
- EVENT_HANDLED_ALL,
- NUM_EVENT_HANDLED_RATIO_TYPE,
-};
-
} // namespace
using ScopedEventRecorder = ServiceWorkerMetrics::ScopedEventRecorder;
-ScopedEventRecorder::ScopedEventRecorder(
- ServiceWorkerMetrics::EventType start_worker_purpose)
- : start_worker_purpose_(start_worker_purpose) {}
+ScopedEventRecorder::ScopedEventRecorder() = default;
ScopedEventRecorder::~ScopedEventRecorder() {
- for (const auto& ev : event_stats_) {
- RecordEventHandledRatio(ev.first, ev.second.handled_events,
- ev.second.fired_events);
- }
- if (start_worker_purpose_ == EventType::NAVIGATION_HINT) {
- bool frame_fetch_event_fired =
- event_stats_[EventType::FETCH_MAIN_FRAME].fired_events ||
- event_stats_[EventType::FETCH_SUB_FRAME].fired_events;
- UMA_HISTOGRAM_BOOLEAN("ServiceWorker.StartHintPrecision",
- frame_fetch_event_fired);
- }
+ UMA_HISTOGRAM_BOOLEAN("ServiceWorker.StartHintPrecision",
+ frame_fetch_event_fired_);
}
void ScopedEventRecorder::RecordEventHandledStatus(
- ServiceWorkerMetrics::EventType event,
- bool handled) {
- event_stats_[event].fired_events++;
- if (handled)
- event_stats_[event].handled_events++;
-}
-
-void ScopedEventRecorder::RecordEventHandledRatio(
- ServiceWorkerMetrics::EventType event,
- size_t handled_events,
- size_t fired_events) {
- if (!fired_events)
- return;
- EventHandledRatioType type = EVENT_HANDLED_SOME;
- if (fired_events == handled_events)
- type = EVENT_HANDLED_ALL;
- else if (handled_events == 0)
- type = EVENT_HANDLED_NONE;
-
- // 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;
+ ServiceWorkerMetrics::EventType event) {
+ if (event == EventType::FETCH_MAIN_FRAME ||
+ event == EventType::FETCH_SUB_FRAME) {
+ frame_fetch_event_fired_ = true;
}
}
@@ -478,23 +420,23 @@ void ServiceWorkerMetrics::CountControlledPageLoad(Site site,
}
void ServiceWorkerMetrics::RecordStartWorkerStatus(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
EventType purpose,
bool is_installed) {
if (!is_installed) {
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartNewWorker.Status", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartNewWorker.Status", status);
return;
}
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
- RecordHistogramEnum(std::string("ServiceWorker.StartWorker.StatusByPurpose") +
- EventTypeToSuffix(purpose),
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status);
+ RecordHistogramEnum(
+ std::string("ServiceWorker.StartWorker.StatusByPurpose") +
+ EventTypeToSuffix(purpose),
+ static_cast<uint32_t>(status),
+ static_cast<uint32_t>(blink::ServiceWorkerStatusCode::kMaxValue));
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Purpose", purpose,
EventType::NUM_TYPES);
- if (status == SERVICE_WORKER_ERROR_TIMEOUT) {
+ if (status == blink::ServiceWorkerStatusCode::kErrorTimeout) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Timeout.StartPurpose",
purpose, EventType::NUM_TYPES);
}
@@ -513,12 +455,13 @@ void ServiceWorkerMetrics::RecordStartWorkerTime(base::TimeDelta time,
EventType purpose) {
if (is_installed) {
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartWorker.Time", time);
- RecordSuffixedMediumTimeHistogram("ServiceWorker.StartWorker.Time",
- StartSituationToSuffix(start_situation),
- time);
RecordSuffixedMediumTimeHistogram(
"ServiceWorker.StartWorker.Time",
- StartSituationToSuffix(start_situation) + EventTypeToSuffix(purpose),
+ StartSituationToDeprecatedSuffix(start_situation), time);
+ RecordSuffixedMediumTimeHistogram(
+ "ServiceWorker.StartWorker.Time",
+ StartSituationToDeprecatedSuffix(start_situation) +
+ EventTypeToSuffix(purpose),
time);
} else {
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartNewWorker.Time", time);
@@ -562,6 +505,11 @@ void ServiceWorkerMetrics::RecordActivatedWorkerPreparationForMainFrame(
static_cast<int>(WorkerPreparationType::NUM_TYPES));
}
+ // Don't record .Time if S13nServiceWorker is enabled.
+ // https://crbug.com/852664
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
// Record the preparation time.
UMA_HISTOGRAM_MEDIUM_TIMES(
"ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time", time);
@@ -598,33 +546,28 @@ void ServiceWorkerMetrics::RecordStopWorkerTime(base::TimeDelta time) {
}
void ServiceWorkerMetrics::RecordActivateEventStatus(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
bool is_shutdown) {
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.ActivateEventStatus", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.ActivateEventStatus", status);
if (is_shutdown) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.ActivateEventStatus_InShutdown",
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
+ status);
} else {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.ActivateEventStatus_NotInShutdown",
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
+ status);
}
}
void ServiceWorkerMetrics::RecordInstallEventStatus(
- ServiceWorkerStatusCode status) {
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.InstallEventStatus", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
+ blink::ServiceWorkerStatusCode status) {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.InstallEventStatus", status);
}
void ServiceWorkerMetrics::RecordEventDispatchingDelay(EventType event_type,
- base::TimeDelta time,
- Site site_for_metrics) {
+ base::TimeDelta time) {
const std::string name = "ServiceWorker.EventDispatchingDelay";
UMA_HISTOGRAM_TIMES(name, time);
- const std::string event_type_suffix = EventTypeToSuffix(event_type);
- const std::string site_suffix = GetSiteSuffix(site_for_metrics);
- RecordSuffixedTimeHistogram(name, event_type_suffix + site_suffix, time);
+ RecordSuffixedTimeHistogram(name, EventTypeToSuffix(event_type), time);
}
void ServiceWorkerMetrics::RecordEventTimeout(EventType event) {
@@ -736,13 +679,13 @@ void ServiceWorkerMetrics::RecordEventDuration(EventType event,
void ServiceWorkerMetrics::RecordFetchEventStatus(
bool is_main_resource,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
if (is_main_resource) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.FetchEvent.MainResource.Status",
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
+ status);
} else {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.FetchEvent.Subresource.Status",
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
+ status);
}
}
@@ -781,133 +724,77 @@ void ServiceWorkerMetrics::RecordProcessCreated(bool is_new_process) {
is_new_process);
}
-void ServiceWorkerMetrics::RecordTimeToSendStartWorker(
- base::TimeDelta duration,
- StartSituation situation) {
- std::string name = "EmbeddedWorkerInstance.Start.TimeToSendStartWorker";
- UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
- RecordSuffixedMediumTimeHistogram(name, StartSituationToSuffix(situation),
- duration);
-}
-
-void ServiceWorkerMetrics::RecordTimeToURLJob(base::TimeDelta duration,
- StartSituation situation) {
- std::string name = "EmbeddedWorkerInstance.Start.TimeToURLJob";
- UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
- RecordSuffixedMediumTimeHistogram(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);
- RecordSuffixedMediumTimeHistogram(name, StartSituationToSuffix(situation),
- duration);
- break;
- case LoadSource::HTTP_CACHE:
- name = "EmbeddedWorkerInstance.Start.TimeToLoad.HttpCache";
- UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
- RecordSuffixedMediumTimeHistogram(name, StartSituationToSuffix(situation),
- duration);
- break;
- case LoadSource::SERVICE_WORKER_STORAGE:
- name = "EmbeddedWorkerInstance.Start.TimeToLoad.InstalledScript";
- UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
- RecordSuffixedMediumTimeHistogram(name, StartSituationToSuffix(situation),
- duration);
- break;
- default:
- NOTREACHED() << static_cast<int>(source);
- }
-}
-
-void ServiceWorkerMetrics::RecordTimeToStartThread(base::TimeDelta duration,
+void ServiceWorkerMetrics::RecordStartWorkerTiming(const StartTimes& times,
StartSituation situation) {
- std::string name = "EmbeddedWorkerInstance.Start.TimeToStartThread";
- UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
- RecordSuffixedMediumTimeHistogram(name, StartSituationToSuffix(situation),
- duration);
-}
-
-void ServiceWorkerMetrics::RecordTimeToEvaluateScript(
- base::TimeDelta duration,
- StartSituation situation) {
- std::string name = "EmbeddedWorkerInstance.Start.TimeToEvaluateScript";
- UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
- RecordSuffixedMediumTimeHistogram(name, StartSituationToSuffix(situation),
- duration);
-}
-
-void ServiceWorkerMetrics::RecordStartMessageLatencyType(
- CrossProcessTimeDelta type) {
- UMA_HISTOGRAM_ENUMERATION(
- "EmbeddedWorkerInstance.Start.StartMessageLatency.Type", type,
- CrossProcessTimeDelta::NUM_TYPES);
-}
-
-void ServiceWorkerMetrics::RecordWaitedForRendererSetup(bool waited) {
- UMA_HISTOGRAM_BOOLEAN("EmbeddedWorkerInstance.Start.WaitedForRendererSetup",
- waited);
-}
-
-void ServiceWorkerMetrics::RecordEmbeddedWorkerStartTiming(
- mojom::EmbeddedWorkerStartTimingPtr start_timing,
- base::TimeTicks start_worker_sent_time,
- StartSituation situation) {
+ // Bail if the timings across processes weren't consistent.
if (!base::TimeTicks::IsHighResolution() ||
!base::TimeTicks::IsConsistentAcrossProcesses()) {
- RecordStartMessageLatencyType(CrossProcessTimeDelta::INACCURATE_CLOCK);
+ RecordStartWorkerTimingClockConsistency(
+ CrossProcessTimeDelta::INACCURATE_CLOCK);
return;
}
- if (start_timing->start_worker_received_time < start_worker_sent_time) {
- RecordStartMessageLatencyType(CrossProcessTimeDelta::NEGATIVE);
+ if (times.remote_start_worker_received < times.local_start_worker_sent ||
+ times.local_end < times.remote_script_evaluation_end) {
+ RecordStartWorkerTimingClockConsistency(CrossProcessTimeDelta::NEGATIVE);
return;
}
+ RecordStartWorkerTimingClockConsistency(CrossProcessTimeDelta::NORMAL);
- RecordStartMessageLatencyType(CrossProcessTimeDelta::NORMAL);
+ // Total duration.
+ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartTiming.Duration",
+ times.local_end - times.local_start);
+ RecordSuffixedMediumTimeHistogram("ServiceWorker.StartTiming.Duration",
+ StartSituationToSuffix(situation),
+ times.local_end - times.local_start);
- const base::TimeDelta start_worker_message_latency =
- start_timing->start_worker_received_time - start_worker_sent_time;
- UMA_HISTOGRAM_MEDIUM_TIMES("EmbeddedWorkerInstance.Start.StartMessageLatency",
- start_worker_message_latency);
- RecordSuffixedMediumTimeHistogram(
- "EmbeddedWorkerInstance.Start.StartMessageLatency",
- StartSituationToSuffix(situation), start_worker_message_latency);
+ // SentStartWorker milestone.
+ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartTiming.StartToSentStartWorker",
+ times.local_start_worker_sent - times.local_start);
- if (start_worker_sent_time < start_timing->blink_initialized_time) {
- RecordWaitedForRendererSetup(true);
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "EmbeddedWorkerInstance.Start.WaitedForRendererSetup.Time",
- (start_timing->blink_initialized_time - start_worker_sent_time));
- } else {
- RecordWaitedForRendererSetup(false);
- }
+ // ReceivedStartWorker milestone.
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.StartTiming.StartToReceivedStartWorker",
+ times.remote_start_worker_received - times.local_start);
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.StartTiming.SentStartWorkerToReceivedStartWorker",
+ times.remote_start_worker_received - times.local_start_worker_sent);
+
+ // ScriptEvaluationStart milestone.
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.StartTiming.StartToScriptEvaluationStart",
+ times.remote_script_evaluation_start - times.local_start);
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.StartTiming.ReceivedStartWorkerToScriptEvaluationStart",
+ times.remote_script_evaluation_start -
+ times.remote_start_worker_received);
+
+ // ScriptEvaluationEnd milestone.
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.StartTiming.StartToScriptEvaluationEnd",
+ times.remote_script_evaluation_end - times.local_start);
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.StartTiming.ScriptEvaluationStartToScriptEvaluationEnd",
+ times.remote_script_evaluation_end -
+ times.remote_script_evaluation_start);
+
+ // End milestone.
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.StartTiming.ScriptEvaluationEndToEnd",
+ times.local_end - times.remote_script_evaluation_end);
}
-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;
+void ServiceWorkerMetrics::RecordStartWorkerTimingClockConsistency(
+ CrossProcessTimeDelta type) {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartTiming.ClockConsistency", type,
+ CrossProcessTimeDelta::NUM_TYPES);
}
void ServiceWorkerMetrics::RecordStartStatusAfterFailure(
int failure_count,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK_GT(failure_count, 0);
- if (status == SERVICE_WORKER_OK) {
+ if (status == blink::ServiceWorkerStatusCode::kOk) {
UMA_HISTOGRAM_COUNTS_1000("ServiceWorker.StartWorker.FailureStreakEnded",
failure_count);
} else if (failure_count < std::numeric_limits<int>::max()) {
@@ -917,13 +804,13 @@ void ServiceWorkerMetrics::RecordStartStatusAfterFailure(
if (failure_count == 1) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.AfterFailureStreak_1",
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
+ status);
} else if (failure_count == 2) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.AfterFailureStreak_2",
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
+ status);
} else if (failure_count == 3) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.AfterFailureStreak_3",
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
+ status);
}
}
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.h b/chromium/content/browser/service_worker/service_worker_metrics.h
index 5c3c51296be..d4a4a6bea09 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.h
+++ b/chromium/content/browser/service_worker/service_worker_metrics.h
@@ -54,27 +54,71 @@ class ServiceWorkerMetrics {
// Used for UMA. Append-only.
enum URLRequestJobResult {
- REQUEST_JOB_FALLBACK_RESPONSE,
- REQUEST_JOB_FALLBACK_FOR_CORS,
- REQUEST_JOB_HEADERS_ONLY_RESPONSE,
- REQUEST_JOB_STREAM_RESPONSE,
- REQUEST_JOB_BLOB_RESPONSE,
- REQUEST_JOB_ERROR_RESPONSE_STATUS_ZERO,
- REQUEST_JOB_ERROR_BAD_BLOB,
- REQUEST_JOB_ERROR_NO_PROVIDER_HOST,
- REQUEST_JOB_ERROR_NO_ACTIVE_VERSION,
- REQUEST_JOB_ERROR_NO_REQUEST,
- REQUEST_JOB_ERROR_FETCH_EVENT_DISPATCH,
- REQUEST_JOB_ERROR_BLOB_READ,
- REQUEST_JOB_ERROR_STREAM_ABORTED,
- REQUEST_JOB_ERROR_KILLED,
- REQUEST_JOB_ERROR_KILLED_WITH_BLOB,
- REQUEST_JOB_ERROR_KILLED_WITH_STREAM,
- REQUEST_JOB_ERROR_DESTROYED,
- REQUEST_JOB_ERROR_DESTROYED_WITH_BLOB,
- REQUEST_JOB_ERROR_DESTROYED_WITH_STREAM,
- REQUEST_JOB_ERROR_BAD_DELEGATE,
- REQUEST_JOB_ERROR_REQUEST_BODY_BLOB_FAILED,
+ // The service worker fell back to network.
+ REQUEST_JOB_FALLBACK_RESPONSE = 0,
+
+ // The service worker fell back to network and CORS check is needed.
+ REQUEST_JOB_FALLBACK_FOR_CORS = 1,
+
+ // The service worker responded with headers only (no body).
+ REQUEST_JOB_HEADERS_ONLY_RESPONSE = 2,
+
+ // The service worker responded with a stream body.
+ REQUEST_JOB_STREAM_RESPONSE = 3,
+
+ // The service worker responded with a blob body.
+ REQUEST_JOB_BLOB_RESPONSE = 4,
+
+ // The renderer responded with network error (see
+ // RecordStatusZeroResponseError() for error reasons).
+ REQUEST_JOB_ERROR_RESPONSE_STATUS_ZERO = 5,
+
+ // The renderer returned a response blob that could not be read.
+ REQUEST_JOB_ERROR_BAD_BLOB = 6,
+
+ // The provider host for the request was destroyed before the request
+ // could start.
+ REQUEST_JOB_ERROR_NO_PROVIDER_HOST = 7,
+
+ // The service worker assigned to the request could not be found, when
+ // the request tried to start.
+ REQUEST_JOB_ERROR_NO_ACTIVE_VERSION = 8,
+
+ // Obsolete.
+ // REQUEST_JOB_ERROR_NO_REQUEST = 9,
+
+ // An error occurred attempting to dispatch the event to the service worker.
+ REQUEST_JOB_ERROR_FETCH_EVENT_DISPATCH = 10,
+
+ // An error occurred while reading the blob response.
+ REQUEST_JOB_ERROR_BLOB_READ = 11,
+
+ // The connection to the stream response was destroyed before all the data
+ // was read.
+ REQUEST_JOB_ERROR_STREAM_ABORTED = 12,
+
+ // The request job destructed before it finished.
+ REQUEST_JOB_ERROR_KILLED = 13,
+
+ // The request job destructed before it finished. It was reading
+ // a blob response.
+ REQUEST_JOB_ERROR_KILLED_WITH_BLOB = 14,
+
+ // The request job was destructed before it finished. It was reading
+ // a stream response.
+ REQUEST_JOB_ERROR_KILLED_WITH_STREAM = 15,
+
+ // Obsolete.
+ // REQUEST_JOB_ERROR_DESTROYED = 16,
+ // REQUEST_JOB_ERROR_DESTROYED_WITH_BLOB = 17,
+ // REQUEST_JOB_ERROR_DESTROYED_WITH_STREAM = 18,
+
+ // The request job delegate behaved incorrectly.
+ REQUEST_JOB_ERROR_BAD_DELEGATE = 19,
+
+ // The browser failed to construct the request body.
+ REQUEST_JOB_ERROR_REQUEST_BODY_BLOB_FAILED = 20,
+
NUM_REQUEST_JOB_RESULT_TYPES,
};
@@ -203,29 +247,39 @@ class ServiceWorkerMetrics {
NUM_TYPES
};
- // Not used for UMA.
- enum class LoadSource { NETWORK, HTTP_CACHE, SERVICE_WORKER_STORAGE };
+ // These are prefixed with "local" or "remote" to indicate whether the browser
+ // process or renderer process recorded the timing (browser is local).
+ struct StartTimes {
+ // The browser started the service worker startup sequence.
+ base::TimeTicks local_start;
+
+ // The browser sent the start worker IPC to the renderer.
+ base::TimeTicks local_start_worker_sent;
+
+ // The renderer received the start worker IPC.
+ base::TimeTicks remote_start_worker_received;
+
+ // The renderer started script evaluation on the worker thread.
+ base::TimeTicks remote_script_evaluation_start;
+ // The renderer finished script evaluation on the worker thread.
+ base::TimeTicks remote_script_evaluation_end;
+
+ // The browser received the worker started IPC.
+ base::TimeTicks local_end;
+ };
+
+ // Records worker activities. Currently this only records
+ // StartHintPrecision histogram.
class ScopedEventRecorder {
public:
- explicit ScopedEventRecorder(EventType start_worker_purpose);
+ ScopedEventRecorder();
~ScopedEventRecorder();
- void RecordEventHandledStatus(EventType event, bool handled);
+ void RecordEventHandledStatus(EventType event);
private:
- struct EventStat {
- size_t fired_events = 0;
- size_t handled_events = 0;
- };
-
- // Records how much of dispatched events are handled.
- static void RecordEventHandledRatio(EventType event,
- size_t handled_events,
- size_t fired_events);
-
- std::map<EventType, EventStat> event_stats_;
- const EventType start_worker_purpose_;
+ bool frame_fetch_event_fired_ = false;
DISALLOW_COPY_AND_ASSIGN(ScopedEventRecorder);
};
@@ -266,7 +320,7 @@ 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,
+ static void RecordStartWorkerStatus(blink::ServiceWorkerStatusCode status,
EventType purpose,
bool is_installed);
@@ -276,6 +330,8 @@ class ServiceWorkerMetrics {
// Records the time taken to successfully start a worker. |is_installed|
// indicates whether the version has been installed.
+ //
+ // TODO(crbug.com/855952): Replace this with RecordStartWorkerTiming().
static void RecordStartWorkerTime(base::TimeDelta time,
bool is_installed,
StartSituation start_situation,
@@ -296,9 +352,9 @@ class ServiceWorkerMetrics {
// Records the time taken to successfully stop a worker.
static void RecordStopWorkerTime(base::TimeDelta time);
- static void RecordActivateEventStatus(ServiceWorkerStatusCode status,
+ static void RecordActivateEventStatus(blink::ServiceWorkerStatusCode status,
bool is_shutdown);
- static void RecordInstallEventStatus(ServiceWorkerStatusCode status);
+ static void RecordInstallEventStatus(blink::ServiceWorkerStatusCode status);
// Records how often a dispatched event times out.
static void RecordEventTimeout(EventType event);
@@ -312,12 +368,11 @@ class ServiceWorkerMetrics {
// process to a Service Worker and executing the event handler in the Service
// Worker.
static void RecordEventDispatchingDelay(EventType event,
- base::TimeDelta time,
- Site site_for_metrics);
+ base::TimeDelta time);
// Records the result of dispatching a fetch event to a service worker.
static void RecordFetchEventStatus(bool is_main_resource,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// Records result of a ServiceWorkerURLRequestJob that was forwarded to
// the service worker.
@@ -334,37 +389,18 @@ class ServiceWorkerMetrics {
static void RecordFallbackedRequestMode(
network::mojom::FetchRequestMode mode);
- // 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(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 void RecordStartMessageLatencyType(CrossProcessTimeDelta type);
- static void RecordWaitedForRendererSetup(bool waited);
- CONTENT_EXPORT static void RecordEmbeddedWorkerStartTiming(
- mojom::EmbeddedWorkerStartTimingPtr start_timing,
- base::TimeTicks start_worker_sent_time,
- StartSituation start_situation);
-
- static const char* LoadSourceToString(LoadSource source);
+
+ CONTENT_EXPORT static void RecordStartWorkerTiming(const StartTimes& times,
+ StartSituation situation);
+ static void RecordStartWorkerTimingClockConsistency(
+ CrossProcessTimeDelta type);
// Records the result of a start attempt that occurred after the worker had
// failed |failure_count| consecutive times.
- static void RecordStartStatusAfterFailure(int failure_count,
- ServiceWorkerStatusCode status);
+ static void RecordStartStatusAfterFailure(
+ int failure_count,
+ blink::ServiceWorkerStatusCode status);
// Records the size of Service-Worker-Navigation-Preload header when the
// navigation preload request is to be sent.
diff --git a/chromium/content/browser/service_worker/service_worker_metrics_unittest.cc b/chromium/content/browser/service_worker/service_worker_metrics_unittest.cc
index 40437a34074..4a1afc8dbfc 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_metrics_unittest.cc
@@ -4,14 +4,15 @@
#include "content/browser/service_worker/service_worker_metrics.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/test/test_content_browser_client.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
-namespace {
+namespace service_worker_metrics_unittest {
const std::string kNavigationPreloadSuffix = "_NavigationPreloadEnabled";
const std::string kStartWorkerDuringStartupSuffix = "_StartWorkerDuringStartup";
const std::string kWorkerStartOccurred = "_WorkerStartOccurred";
@@ -65,7 +66,10 @@ void ExpectNoNavPreloadWorkerStartOccurredUMA(
0);
}
-} // namespace
+base::TimeTicks AdvanceTime(base::TimeTicks* time, int milliseconds) {
+ *time += base::TimeDelta::FromMilliseconds(milliseconds);
+ return *time;
+}
using CrossProcessTimeDelta = ServiceWorkerMetrics::CrossProcessTimeDelta;
using StartSituation = ServiceWorkerMetrics::StartSituation;
@@ -93,11 +97,15 @@ TEST(ServiceWorkerMetricsTest, ActivatedWorkerPreparation) {
kPreparationType, static_cast<int>(WorkerPreparationType::STARTING), 1);
histogram_tester.ExpectTotalCount(
kPreparationType + kNavigationPreloadSuffix, 0);
- histogram_tester.ExpectTimeBucketCount(kPreparationTime, time, 1);
- histogram_tester.ExpectTimeBucketCount(kPreparationTime + "_StartingWorker",
- time, 1);
- histogram_tester.ExpectTotalCount(
- kPreparationTime + kNavigationPreloadSuffix, 0);
+
+ // We don't record .Time histograms when S13nServiceWorker is enabled.
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ histogram_tester.ExpectTimeBucketCount(kPreparationTime, time, 1);
+ histogram_tester.ExpectTimeBucketCount(
+ kPreparationTime + "_StartingWorker", time, 1);
+ histogram_tester.ExpectTotalCount(
+ kPreparationTime + kNavigationPreloadSuffix, 0);
+ }
}
{
@@ -112,11 +120,16 @@ TEST(ServiceWorkerMetricsTest, ActivatedWorkerPreparation) {
histogram_tester.ExpectUniqueSample(
kPreparationType + kNavigationPreloadSuffix,
static_cast<int>(WorkerPreparationType::START_DURING_STARTUP), 1);
- histogram_tester.ExpectTimeBucketCount(kPreparationTime, time, 1);
- histogram_tester.ExpectTimeBucketCount(
- kPreparationTime + kNavigationPreloadSuffix, time, 1);
- histogram_tester.ExpectTotalCount(
- kPreparationTime + kWorkerStartOccurred + kNavigationPreloadSuffix, 1);
+
+ // We don't record .Time histograms when S13nServiceWorker is enabled.
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ histogram_tester.ExpectTimeBucketCount(kPreparationTime, time, 1);
+ histogram_tester.ExpectTimeBucketCount(
+ kPreparationTime + kNavigationPreloadSuffix, time, 1);
+ histogram_tester.ExpectTotalCount(
+ kPreparationTime + kWorkerStartOccurred + kNavigationPreloadSuffix,
+ 1);
+ }
}
{
@@ -136,12 +149,16 @@ TEST(ServiceWorkerMetricsTest, ActivatedWorkerPreparation) {
static_cast<int>(
WorkerPreparationType::START_IN_EXISTING_READY_PROCESS),
1);
- histogram_tester.ExpectTimeBucketCount(kPreparationTime, time, 1);
- histogram_tester.ExpectTimeBucketCount(
- kPreparationTime + kNavigationPreloadSuffix, time, 1);
- histogram_tester.ExpectTimeBucketCount(
- kPreparationTime + kWorkerStartOccurred + kNavigationPreloadSuffix,
- time, 1);
+
+ // We don't record .Time histograms when S13nServiceWorker is enabled.
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ histogram_tester.ExpectTimeBucketCount(kPreparationTime, time, 1);
+ histogram_tester.ExpectTimeBucketCount(
+ kPreparationTime + kNavigationPreloadSuffix, time, 1);
+ histogram_tester.ExpectTimeBucketCount(
+ kPreparationTime + kWorkerStartOccurred + kNavigationPreloadSuffix,
+ time, 1);
+ }
}
// Suffixed metric test.
@@ -391,106 +408,152 @@ TEST(ServiceWorkerMetricsTest, NavigationPreloadResponse_BrowserStartup) {
}
TEST(ServiceWorkerMetricsTest, EmbeddedWorkerStartTiming) {
- base::TimeTicks start_worker_sent_time = base::TimeTicks::Now();
- const base::TimeDelta latency = base::TimeDelta::FromMilliseconds(33);
- auto start_timing = mojom::EmbeddedWorkerStartTiming::New();
- start_timing->blink_initialized_time = start_worker_sent_time;
- start_timing->start_worker_received_time = start_worker_sent_time + latency;
+ ServiceWorkerMetrics::StartTimes times;
+ auto current = base::TimeTicks::Now();
+ times.local_start = current;
+ times.local_start_worker_sent = AdvanceTime(&current, 11);
+ times.remote_start_worker_received = AdvanceTime(&current, 33);
+ times.remote_script_evaluation_start = AdvanceTime(&current, 55);
+ times.remote_script_evaluation_end = AdvanceTime(&current, 77);
+ times.local_end = AdvanceTime(&current, 22);
+
StartSituation start_situation = StartSituation::EXISTING_READY_PROCESS;
base::HistogramTester histogram_tester;
- ServiceWorkerMetrics::RecordEmbeddedWorkerStartTiming(
- std::move(start_timing), start_worker_sent_time, start_situation);
- histogram_tester.ExpectUniqueSample(
- "EmbeddedWorkerInstance.Start.StartMessageLatency.Type",
- static_cast<int>(CrossProcessTimeDelta::NORMAL), 1);
+ ServiceWorkerMetrics::RecordStartWorkerTiming(times, start_situation);
+
+ // Total duration.
+ histogram_tester.ExpectTimeBucketCount("ServiceWorker.StartTiming.Duration",
+ times.local_end - times.local_start,
+ 1);
histogram_tester.ExpectTimeBucketCount(
- "EmbeddedWorkerInstance.Start.StartMessageLatency", latency, 1);
+ "ServiceWorker.StartTiming.Duration.ExistingReadyProcess",
+ times.local_end - times.local_start, 1);
+
+ // SentStartWorker milestone.
histogram_tester.ExpectTimeBucketCount(
- "EmbeddedWorkerInstance.Start.StartMessageLatency_ExistingReadyProcess",
- latency, 1);
+ "ServiceWorker.StartTiming.StartToSentStartWorker",
+ times.local_start_worker_sent - times.local_start, 1);
+
+ // ReceivedStartWorker milestone.
+ histogram_tester.ExpectTimeBucketCount(
+ "ServiceWorker.StartTiming.StartToReceivedStartWorker",
+ times.remote_start_worker_received - times.local_start, 1);
+ histogram_tester.ExpectTimeBucketCount(
+ "ServiceWorker.StartTiming.SentStartWorkerToReceivedStartWorker",
+ times.remote_start_worker_received - times.local_start_worker_sent, 1);
+
+ // ScriptEvaluationStart milestone.
+ histogram_tester.ExpectTimeBucketCount(
+ "ServiceWorker.StartTiming.StartToScriptEvaluationStart",
+ times.remote_script_evaluation_start - times.local_start, 1);
+ histogram_tester.ExpectTimeBucketCount(
+ "ServiceWorker.StartTiming.ReceivedStartWorkerToScriptEvaluationStart",
+ times.remote_script_evaluation_start - times.remote_start_worker_received,
+ 1);
+
+ // ScriptEvaluationEnd milestone.
+ histogram_tester.ExpectTimeBucketCount(
+ "ServiceWorker.StartTiming.StartToScriptEvaluationEnd",
+ times.remote_script_evaluation_end - times.local_start, 1);
+ histogram_tester.ExpectTimeBucketCount(
+ "ServiceWorker.StartTiming.ScriptEvaluationStartToScriptEvaluationEnd",
+ times.remote_script_evaluation_end - times.remote_script_evaluation_start,
+ 1);
+
+ // End milestone.
+ histogram_tester.ExpectTimeBucketCount(
+ "ServiceWorker.StartTiming.ScriptEvaluationEndToEnd",
+ times.local_end - times.remote_script_evaluation_end, 1);
+
+ // Clock consistency.
histogram_tester.ExpectUniqueSample(
- "EmbeddedWorkerInstance.Start.WaitedForRendererSetup", false, 1);
- histogram_tester.ExpectTotalCount(
- "EmbeddedWorkerInstance.Start.WaitedForRendererSetup.Time", 0);
+ "ServiceWorker.StartTiming.ClockConsistency",
+ CrossProcessTimeDelta::NORMAL, 1);
}
TEST(ServiceWorkerMetricsTest, EmbeddedWorkerStartTiming_BrowserStartup) {
- base::TimeTicks start_worker_sent_time = base::TimeTicks::Now();
- const base::TimeDelta latency = base::TimeDelta::FromMilliseconds(66);
- auto start_timing = mojom::EmbeddedWorkerStartTiming::New();
- start_timing->blink_initialized_time = start_worker_sent_time;
- start_timing->start_worker_received_time = start_worker_sent_time + latency;
+ ServiceWorkerMetrics::StartTimes times;
+ auto current = base::TimeTicks::Now();
+ times.local_start = current;
+ times.local_start_worker_sent = AdvanceTime(&current, 11);
+ times.remote_start_worker_received = AdvanceTime(&current, 66);
+ times.remote_script_evaluation_start = AdvanceTime(&current, 55);
+ times.remote_script_evaluation_end = AdvanceTime(&current, 77);
+ times.local_end = AdvanceTime(&current, 22);
+
StartSituation start_situation = StartSituation::DURING_STARTUP;
base::HistogramTester histogram_tester;
- ServiceWorkerMetrics::RecordEmbeddedWorkerStartTiming(
- std::move(start_timing), start_worker_sent_time, start_situation);
- histogram_tester.ExpectUniqueSample(
- "EmbeddedWorkerInstance.Start.StartMessageLatency.Type",
- static_cast<int>(CrossProcessTimeDelta::NORMAL), 1);
- histogram_tester.ExpectTimeBucketCount(
- "EmbeddedWorkerInstance.Start.StartMessageLatency", latency, 1);
+ ServiceWorkerMetrics::RecordStartWorkerTiming(times, start_situation);
+
+ // Total duration.
+ histogram_tester.ExpectTimeBucketCount("ServiceWorker.StartTiming.Duration",
+ times.local_end - times.local_start,
+ 1);
histogram_tester.ExpectTimeBucketCount(
- "EmbeddedWorkerInstance.Start.StartMessageLatency_DuringStartup", latency,
- 1);
- histogram_tester.ExpectUniqueSample(
- "EmbeddedWorkerInstance.Start.WaitedForRendererSetup", false, 1);
- histogram_tester.ExpectTotalCount(
- "EmbeddedWorkerInstance.Start.WaitedForRendererSetup.Time", 0);
+ "ServiceWorker.StartTiming.Duration.DuringStartup",
+ times.local_end - times.local_start, 1);
}
-TEST(ServiceWorkerMetricsTest, EmbeddedWorkerStartTiming_WaitForRenderer) {
- base::TimeTicks start_worker_sent_time = base::TimeTicks::Now();
- const base::TimeDelta latency = base::TimeDelta::FromMilliseconds(777);
- const base::TimeDelta renderer_setup = base::TimeDelta::FromMilliseconds(333);
- auto start_timing = mojom::EmbeddedWorkerStartTiming::New();
- start_timing->blink_initialized_time =
- start_worker_sent_time + renderer_setup;
- start_timing->start_worker_received_time = start_worker_sent_time + latency;
- StartSituation start_situation = StartSituation::NEW_PROCESS;
+TEST(ServiceWorkerMetricsTest,
+ EmbeddedWorkerStartTiming_NegativeLatencyForStartIPC) {
+ ServiceWorkerMetrics::StartTimes times;
+ auto current = base::TimeTicks::Now();
+ times.local_start = current;
+ times.local_start_worker_sent = AdvanceTime(&current, 11);
+ // Go back in time.
+ times.remote_start_worker_received = AdvanceTime(&current, -777);
+ times.remote_script_evaluation_start = AdvanceTime(&current, 55);
+ times.remote_script_evaluation_end = AdvanceTime(&current, 77);
+ times.local_end = AdvanceTime(&current, 22);
+
+ StartSituation start_situation = StartSituation::EXISTING_READY_PROCESS;
base::HistogramTester histogram_tester;
- ServiceWorkerMetrics::RecordEmbeddedWorkerStartTiming(
- std::move(start_timing), start_worker_sent_time, start_situation);
- histogram_tester.ExpectUniqueSample(
- "EmbeddedWorkerInstance.Start.StartMessageLatency.Type",
- static_cast<int>(CrossProcessTimeDelta::NORMAL), 1);
- histogram_tester.ExpectTimeBucketCount(
- "EmbeddedWorkerInstance.Start.StartMessageLatency", latency, 1);
- histogram_tester.ExpectTimeBucketCount(
- "EmbeddedWorkerInstance.Start.StartMessageLatency_NewProcess", latency,
- 1);
+ ServiceWorkerMetrics::RecordStartWorkerTiming(times, start_situation);
+
+ // Duration and breakdowns should not be logged.
+ histogram_tester.ExpectTotalCount("ServiceWorker.StartTiming.Duration", 0);
+ // Just test one arbitrarily chosen breakdown metric.
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.StartTiming.StartToScriptEvaluationStart", 0);
+
+ // Clock consistency.
histogram_tester.ExpectUniqueSample(
- "EmbeddedWorkerInstance.Start.WaitedForRendererSetup", true, 1);
- histogram_tester.ExpectTimeBucketCount(
- "EmbeddedWorkerInstance.Start.WaitedForRendererSetup.Time",
- renderer_setup, 1);
+ "ServiceWorker.StartTiming.ClockConsistency",
+ CrossProcessTimeDelta::NEGATIVE, 1);
}
-TEST(ServiceWorkerMetricsTest, EmbeddedWorkerStartTiming_NegativeLatency) {
- base::TimeTicks start_worker_sent_time = base::TimeTicks::Now();
- const base::TimeDelta latency = base::TimeDelta::FromMilliseconds(777);
- auto start_timing = mojom::EmbeddedWorkerStartTiming::New();
- start_timing->blink_initialized_time = start_worker_sent_time;
- start_timing->start_worker_received_time = start_worker_sent_time - latency;
+TEST(ServiceWorkerMetricsTest,
+ EmbeddedWorkerStartTiming_NegativeLatencyForStartedIPC) {
+ ServiceWorkerMetrics::StartTimes times;
+ auto current = base::TimeTicks::Now();
+ times.local_start = current;
+ times.local_start_worker_sent = AdvanceTime(&current, 11);
+ times.remote_start_worker_received = AdvanceTime(&current, 777);
+ times.remote_script_evaluation_start = AdvanceTime(&current, 55);
+ times.remote_script_evaluation_end = AdvanceTime(&current, 77);
+ // Go back in time.
+ times.local_end = AdvanceTime(&current, -123);
+
StartSituation start_situation = StartSituation::EXISTING_READY_PROCESS;
base::HistogramTester histogram_tester;
- ServiceWorkerMetrics::RecordEmbeddedWorkerStartTiming(
- std::move(start_timing), start_worker_sent_time, start_situation);
- histogram_tester.ExpectUniqueSample(
- "EmbeddedWorkerInstance.Start.StartMessageLatency.Type",
- static_cast<int>(CrossProcessTimeDelta::NEGATIVE), 1);
- histogram_tester.ExpectTotalCount(
- "EmbeddedWorkerInstance.Start.StartMessageLatency", 0);
+ ServiceWorkerMetrics::RecordStartWorkerTiming(times, start_situation);
+
+ // Duration and breakdowns should not be logged.
+ histogram_tester.ExpectTotalCount("ServiceWorker.StartTiming.Duration", 0);
+ // Just test one arbitrarily chosen breakdown metric.
histogram_tester.ExpectTotalCount(
- "EmbeddedWorkerInstance.Start.StartMessageLatency_ExistingReadyProcess",
+ "ServiceWorker.StartTiming.ScriptEvaluationStartToScriptEvaluationEnd",
0);
- histogram_tester.ExpectTotalCount(
- "EmbeddedWorkerInstance.Start.WaitedForRendererSetup", 0);
- histogram_tester.ExpectTotalCount(
- "EmbeddedWorkerInstance.Start.WaitedForRendererSetup.Time", 0);
+
+ // Clock consistency.
+ histogram_tester.ExpectUniqueSample(
+ "ServiceWorker.StartTiming.ClockConsistency",
+ CrossProcessTimeDelta::NEGATIVE, 1);
}
+} // namespace service_worker_metrics_unittest
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc b/chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc
index 686fa1312a9..c27a6b691bd 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc
@@ -31,13 +31,21 @@ ServiceWorkerNavigationHandleCore::~ServiceWorkerNavigationHandleCore() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (provider_id_ == kInvalidServiceWorkerProviderId)
return;
- // Remove the provider host if it was never completed (navigation failed).
ServiceWorkerContextCore* context = context_wrapper_->context();
- if (!context || !context->GetProviderHost(ChildProcessHost::kInvalidUniqueID,
- provider_id_)) {
+ if (!context)
+ return;
+ ServiceWorkerProviderHost* host = context->GetProviderHost(
+ ChildProcessHost::kInvalidUniqueID, provider_id_);
+ if (!host)
return;
- }
- context->RemoveProviderHost(ChildProcessHost::kInvalidUniqueID, provider_id_);
+ // Remove the provider host if it was never completed (navigation failed).
+ // TODO(falken): ServiceWorkerNavigationHandleCore should just own a Mojo
+ // pointer tied to the lifetime of ServiceWorkerProviderHost, and send the
+ // Mojo pointer to the renderer on navigation commit. If the handle core dies
+ // before that, the provider host would be destroyed by Mojo connection error.
+ if (!host->is_execution_ready())
+ context->RemoveProviderHost(ChildProcessHost::kInvalidUniqueID,
+ provider_id_);
}
void ServiceWorkerNavigationHandleCore::DidPreCreateProviderHost(
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_loader.cc b/chromium/content/browser/service_worker/service_worker_navigation_loader.cc
index a5e6d0f8e73..24fa5a697bc 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/chromium/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -4,9 +4,11 @@
#include "content/browser/service_worker/service_worker_navigation_loader.h"
+#include <sstream>
#include <utility>
#include "base/optional.h"
+#include "base/trace_event/trace_event.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/service_worker_loader_helpers.h"
@@ -21,6 +23,17 @@ namespace content {
namespace {
+std::string ComposeFetchEventResultString(
+ ServiceWorkerFetchDispatcher::FetchEventResult result,
+ const ServiceWorkerResponse& response) {
+ if (result == ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback)
+ return "Fallback to network";
+ std::stringstream stream;
+ stream << "Got response (status_code: " << response.status_code
+ << " status_text: '" << response.status_text << "')";
+ return stream.str();
+}
+
bool BodyHasNoDataPipeGetters(const network::ResourceRequestBody* body) {
if (!body)
return true;
@@ -81,6 +94,11 @@ ServiceWorkerNavigationLoader::ServiceWorkerNavigationLoader(
url_loader_factory_getter_(std::move(url_loader_factory_getter)),
binding_(this),
weak_factory_(this) {
+ TRACE_EVENT_WITH_FLOW1(
+ "ServiceWorker",
+ "ServiceWorkerNavigationLoader::ServiceWorkerNavigationloader", this,
+ TRACE_EVENT_FLAG_FLOW_OUT, "url", resource_request_.url.spec());
+
DCHECK(ServiceWorkerUtils::IsMainResourceType(
static_cast<ResourceType>(resource_request.resource_type)));
@@ -88,10 +106,21 @@ ServiceWorkerNavigationLoader::ServiceWorkerNavigationLoader(
response_head_.load_timing.request_start_time = base::Time::Now();
}
-ServiceWorkerNavigationLoader::~ServiceWorkerNavigationLoader() = default;
+ServiceWorkerNavigationLoader::~ServiceWorkerNavigationLoader() {
+ TRACE_EVENT_WITH_FLOW0(
+ "ServiceWorker",
+ "ServiceWorkerNavigationLoader::~ServiceWorkerNavigationloader", this,
+ TRACE_EVENT_FLAG_FLOW_IN);
+};
void ServiceWorkerNavigationLoader::FallbackToNetwork() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT_WITH_FLOW0(
+ "ServiceWorker", "ServiceWorkerNavigationLoader::FallbackToNetwork", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+
response_type_ = ResponseType::FALLBACK_TO_NETWORK;
+ status_ = Status::kCompleted;
// This could be called multiple times in some cases because we simply
// call this synchronously here and don't wait for a separate async
// StartRequest cue like what URLRequestJob case does.
@@ -100,12 +129,10 @@ void ServiceWorkerNavigationLoader::FallbackToNetwork() {
std::move(loader_callback_).Run({});
}
-void ServiceWorkerNavigationLoader::FallbackToNetworkOrRenderer() {
- // TODO(kinuko): Implement this. Now we always fallback to network.
- FallbackToNetwork();
-}
-
void ServiceWorkerNavigationLoader::ForwardToServiceWorker() {
+ TRACE_EVENT_WITH_FLOW0(
+ "ServiceWorker", "ServiceWorkerNavigationLoader::ForwardToServiceWorker",
+ this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
response_type_ = ResponseType::FORWARD_TO_SERVICE_WORKER;
StartRequest();
}
@@ -114,22 +141,6 @@ bool ServiceWorkerNavigationLoader::ShouldFallbackToNetwork() {
return response_type_ == ResponseType::FALLBACK_TO_NETWORK;
}
-void ServiceWorkerNavigationLoader::FailDueToLostController() {
- NOTIMPLEMENTED();
-}
-
-void ServiceWorkerNavigationLoader::Cancel() {
- status_ = Status::kCancelled;
- weak_factory_.InvalidateWeakPtrs();
- fetch_dispatcher_.reset();
- stream_waiter_.reset();
-
- url_loader_client_->OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_ABORTED));
- url_loader_client_.reset();
- DeleteIfNeeded();
-}
-
bool ServiceWorkerNavigationLoader::WasCanceled() const {
return status_ == Status::kCancelled;
}
@@ -139,11 +150,20 @@ void ServiceWorkerNavigationLoader::DetachedFromRequest() {
DeleteIfNeeded();
}
+base::WeakPtr<ServiceWorkerNavigationLoader>
+ServiceWorkerNavigationLoader::AsWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
void ServiceWorkerNavigationLoader::StartRequest() {
DCHECK_EQ(ResponseType::FORWARD_TO_SERVICE_WORKER, response_type_);
DCHECK_EQ(Status::kNotStarted, status_);
status_ = Status::kStarted;
+ TRACE_EVENT_WITH_FLOW0("ServiceWorker",
+ "ServiceWorkerNavigationLoader::StartRequest", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+
ServiceWorkerMetrics::URLRequestJobResult result =
ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE;
ServiceWorkerVersion* active_worker =
@@ -176,7 +196,8 @@ void ServiceWorkerNavigationLoader::StartRequest() {
net::NetLogWithSource() /* TODO(scottmg): net log? */,
base::BindOnce(&ServiceWorkerNavigationLoader::DidPrepareFetchEvent,
weak_factory_.GetWeakPtr(),
- base::WrapRefCounted(active_worker)),
+ base::WrapRefCounted(active_worker),
+ active_worker->running_status()),
base::BindOnce(&ServiceWorkerNavigationLoader::DidDispatchFetchEvent,
weak_factory_.GetWeakPtr()));
did_navigation_preload_ =
@@ -192,12 +213,21 @@ void ServiceWorkerNavigationLoader::StartRequest() {
void ServiceWorkerNavigationLoader::CommitResponseHeaders() {
DCHECK_EQ(Status::kStarted, status_);
DCHECK(url_loader_client_.is_bound());
+ TRACE_EVENT_WITH_FLOW2(
+ "ServiceWorker", "ServiceWorkerNavigationLoader::CommitResponseHeaders",
+ this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+ "response_code", response_head_.headers->response_code(), "status_text",
+ response_head_.headers->GetStatusText());
status_ = Status::kSentHeader;
- url_loader_client_->OnReceiveResponse(response_head_,
- nullptr /* downloaded_file */);
+ url_loader_client_->OnReceiveResponse(response_head_);
}
void ServiceWorkerNavigationLoader::CommitCompleted(int error_code) {
+ TRACE_EVENT_WITH_FLOW1("ServiceWorker",
+ "ServiceWorkerNavigationLoader::CommitCompleted", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+ "error_code", net::ErrorToString(error_code));
+
DCHECK_LT(status_, Status::kCompleted);
DCHECK(url_loader_client_.is_bound());
status_ = Status::kCompleted;
@@ -210,6 +240,11 @@ void ServiceWorkerNavigationLoader::CommitCompleted(int error_code) {
}
void ServiceWorkerNavigationLoader::ReturnNetworkError() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT_WITH_FLOW0(
+ "ServiceWorker", "ServiceWorkerNavigationLoader::ReturnNetworkError",
+ this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+
DCHECK(!url_loader_client_.is_bound());
DCHECK(loader_callback_);
std::move(loader_callback_)
@@ -218,17 +253,44 @@ void ServiceWorkerNavigationLoader::ReturnNetworkError() {
}
void ServiceWorkerNavigationLoader::DidPrepareFetchEvent(
- scoped_refptr<ServiceWorkerVersion> version) {
+ scoped_refptr<ServiceWorkerVersion> version,
+ EmbeddedWorkerStatus initial_worker_status) {
+ TRACE_EVENT_WITH_FLOW1(
+ "ServiceWorker", "ServiceWorkerNavigationLoader::DidPrepareFetchEvent",
+ this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+ "initial_worker_status",
+ EmbeddedWorkerInstance::StatusToString(initial_worker_status));
+
response_head_.service_worker_ready_time = base::TimeTicks::Now();
+
+ // Note that we don't record worker preparation time in S13nServiceWorker
+ // path for now. If we want to measure worker preparation time we can
+ // calculate it from response_head_.service_worker_ready_time and
+ // response_head_.load_timing.request_start.
+ // https://crbug.com/852664
+ ServiceWorkerMetrics::RecordActivatedWorkerPreparationForMainFrame(
+ base::TimeDelta(), initial_worker_status,
+ version->embedded_worker()->start_situation(), did_navigation_preload_,
+ resource_request_.url);
}
void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
blink::mojom::BlobPtr body_as_blob,
scoped_refptr<ServiceWorkerVersion> version) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ TRACE_EVENT_WITH_FLOW2(
+ "ServiceWorker", "ServiceWorkerNavigationLoader::DidDispatchFetchEvent",
+ this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "status",
+ blink::ServiceWorkerStatusToString(status), "result",
+ ComposeFetchEventResultString(fetch_result, response));
+ ServiceWorkerMetrics::RecordFetchEventStatus(true /* is_main_resource */,
+ status);
+
ServiceWorkerMetrics::URLRequestJobResult result =
ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE;
if (!delegate_->RequestStillValid(&result)) {
@@ -236,7 +298,7 @@ void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
return;
}
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
delegate_->MainResourceLoadFailed();
FallbackToNetwork();
return;
@@ -244,7 +306,6 @@ void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
if (fetch_result ==
ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback) {
- // TODO(kinuko): Check if this needs to fallback to the renderer.
FallbackToNetwork();
return;
}
@@ -259,15 +320,6 @@ void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
return;
}
- // Get SSLInfo from the ServiceWorker script's HttpResponseInfo to show HTTPS
- // padlock.
- // TODO(horo): When we support mixed-content (HTTP) no-cors requests from a
- // ServiceWorker, we have to check the security level of the responses.
- const net::HttpResponseInfo* main_script_http_info =
- version->GetMainScriptHttpResponseInfo();
- DCHECK(main_script_http_info);
- ssl_info_ = main_script_http_info->ssl_info;
-
std::move(loader_callback_)
.Run(base::BindOnce(&ServiceWorkerNavigationLoader::StartResponse,
weak_factory_.GetWeakPtr(), response, version,
@@ -284,8 +336,9 @@ void ServiceWorkerNavigationLoader::StartResponse(
DCHECK(!binding_.is_bound());
DCHECK(!url_loader_client_.is_bound());
binding_.Bind(std::move(request));
- binding_.set_connection_error_handler(base::BindOnce(
- &ServiceWorkerNavigationLoader::Cancel, base::Unretained(this)));
+ binding_.set_connection_error_handler(
+ base::BindOnce(&ServiceWorkerNavigationLoader::OnConnectionClosed,
+ base::Unretained(this)));
url_loader_client_ = std::move(client);
ServiceWorkerLoaderHelpers::SaveResponseInfo(response, &response_head_);
@@ -296,15 +349,26 @@ void ServiceWorkerNavigationLoader::StartResponse(
response_head_.did_service_worker_navigation_preload =
did_navigation_preload_;
response_head_.load_timing.receive_headers_end = base::TimeTicks::Now();
- response_head_.ssl_info = ssl_info_;
+
+ // Make the navigated page inherit the SSLInfo from its controller service
+ // worker's script. This affects the HTTPS padlock, etc, shown by the
+ // browser. See https://crbug.com/392409 for details about this design.
+ // TODO(horo): When we support mixed-content (HTTP) no-cors requests from a
+ // ServiceWorker, we have to check the security level of the responses.
+ response_head_.ssl_info = version->GetMainScriptHttpResponseInfo()->ssl_info;
// Handle a redirect response. ComputeRedirectInfo returns non-null redirect
// info if the given response is a redirect.
base::Optional<net::RedirectInfo> redirect_info =
ServiceWorkerLoaderHelpers::ComputeRedirectInfo(
resource_request_, response_head_,
- ssl_info_ && ssl_info_->token_binding_negotiated);
+ response_head_.ssl_info->token_binding_negotiated);
if (redirect_info) {
+ TRACE_EVENT_WITH_FLOW2(
+ "ServiceWorker", "ServiceWorkerNavigationLoader::StartResponse", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "result",
+ "redirect", "redirect url", redirect_info->new_url.spec());
+
response_head_.encoded_data_length = 0;
url_loader_client_->OnReceiveRedirect(*redirect_info, response_head_);
// Our client is the navigation loader, which will start a new URLLoader for
@@ -318,6 +382,10 @@ void ServiceWorkerNavigationLoader::StartResponse(
// Handle a stream response body.
if (!body_as_stream.is_null() && body_as_stream->stream.is_valid()) {
+ TRACE_EVENT_WITH_FLOW1("ServiceWorker",
+ "ServiceWorkerNavigationLoader::StartResponse", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+ "result", "stream response");
stream_waiter_ = std::make_unique<StreamWaiter>(
this, std::move(version), std::move(body_as_stream->callback_request));
url_loader_client_->OnStartLoadingResponseBody(
@@ -339,11 +407,21 @@ void ServiceWorkerNavigationLoader::StartResponse(
CommitCompleted(error);
return;
}
+ TRACE_EVENT_WITH_FLOW1("ServiceWorker",
+ "ServiceWorkerNavigationLoader::StartResponse", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+ "result", "blob response");
+
url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe));
// We continue in OnBlobReadingComplete().
return;
}
+ TRACE_EVENT_WITH_FLOW1("ServiceWorker",
+ "ServiceWorkerNavigationLoader::StartResponse", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+ "result", "no body");
+
// The response has no body.
CommitCompleted(net::OK);
}
@@ -360,6 +438,8 @@ void ServiceWorkerNavigationLoader::StartErrorResponse(
// URLLoader implementation----------------------------------------
void ServiceWorkerNavigationLoader::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
NOTIMPLEMENTED();
}
@@ -384,6 +464,23 @@ void ServiceWorkerNavigationLoader::OnBlobReadingComplete(int net_error) {
body_as_blob_.reset();
}
+void ServiceWorkerNavigationLoader::OnConnectionClosed() {
+ weak_factory_.InvalidateWeakPtrs();
+ fetch_dispatcher_.reset();
+ stream_waiter_.reset();
+ binding_.Close();
+
+ // Cancel the request if this loader hasn't yet responded to it.
+ if (status_ != Status::kCompleted && status_ != Status::kCancelled) {
+ status_ = Status::kCancelled;
+ url_loader_client_->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_ABORTED));
+ }
+ url_loader_client_.reset();
+
+ DeleteIfNeeded();
+}
+
void ServiceWorkerNavigationLoader::DeleteIfNeeded() {
if (!binding_.is_bound() && detached_from_request_)
delete this;
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_loader.h b/chromium/content/browser/service_worker/service_worker_navigation_loader.h
index 3aef0461d18..b39480174a3 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_loader.h
+++ b/chromium/content/browser/service_worker/service_worker_navigation_loader.h
@@ -11,16 +11,17 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_response_type.h"
#include "content/browser/service_worker/service_worker_url_job_wrapper.h"
#include "content/browser/url_loader_factory_getter.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "services/network/public/mojom/url_loader.mojom.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_stream_handle.mojom.h"
@@ -84,11 +85,8 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
// Called via URLJobWrapper.
void FallbackToNetwork();
- void FallbackToNetworkOrRenderer();
void ForwardToServiceWorker();
bool ShouldFallbackToNetwork();
- void FailDueToLostController();
- void Cancel();
bool WasCanceled() const;
// The navigation request that was holding this job is
@@ -98,14 +96,17 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
// endpoint is held by the client.
void DetachedFromRequest();
+ base::WeakPtr<ServiceWorkerNavigationLoader> AsWeakPtr();
+
private:
class StreamWaiter;
// For FORWARD_TO_SERVICE_WORKER case.
void StartRequest();
- void DidPrepareFetchEvent(scoped_refptr<ServiceWorkerVersion> version);
+ void DidPrepareFetchEvent(scoped_refptr<ServiceWorkerVersion> version,
+ EmbeddedWorkerStatus initial_worker_status);
void DidDispatchFetchEvent(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
@@ -139,7 +140,9 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
void ReturnNetworkError();
// network::mojom::URLLoader:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
@@ -149,6 +152,7 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
void OnBlobReadingComplete(int net_error);
+ void OnConnectionClosed();
void DeleteIfNeeded();
ResponseType response_type_ = ResponseType::NOT_DETERMINED;
@@ -164,7 +168,6 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
bool did_navigation_preload_ = false;
network::ResourceResponseHead response_head_;
- base::Optional<net::SSLInfo> ssl_info_;
// Pointer to the URLLoaderClient (i.e. NavigationURLLoader).
network::mojom::URLLoaderClientPtr url_loader_client_;
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc b/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
index 362281ad037..3b22bc42d71 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
@@ -5,6 +5,7 @@
#include "content/browser/service_worker/service_worker_navigation_loader.h"
#include "base/run_loop.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
@@ -12,13 +13,13 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/common/single_request_url_loader_factory.h"
+#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
-#include "net/http/http_util.h"
#include "net/ssl/ssl_info.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
@@ -53,7 +54,8 @@ void ReceiveRequestHandler(
// 1. ServiceWorkerNavigationLoader asks ServiceWorkerFetchDispatcher to start
// navigation preload.
// 2. ServiceWorkerFetchDispatcher starts the network request which is mocked
-// by MockNetworkURLLoaderFactory. The response is sent to
+// by EmbeddedWorkerTestHelper's default network loader factory. The
+// response is sent to
// ServiceWorkerFetchDispatcher::DelegatingURLLoaderClient.
// 3. DelegatingURLLoaderClient sends the response to the |preload_handle|
// that was passed to Helper::OnFetchEvent().
@@ -68,10 +70,9 @@ class NavigationPreloadLoaderClient final
: public network::mojom::URLLoaderClient {
public:
NavigationPreloadLoaderClient(
- mojom::FetchEventPreloadHandlePtr preload_handle,
+ blink::mojom::FetchEventPreloadHandlePtr preload_handle,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback)
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
: url_loader_(std::move(preload_handle->url_loader)),
binding_(this, std::move(preload_handle->url_loader_client_request)),
response_callback_(std::move(response_callback)),
@@ -84,8 +85,7 @@ class NavigationPreloadLoaderClient final
// network::mojom::URLLoaderClient implementation
void OnReceiveResponse(
- const network::ResourceResponseHead& response_head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override {
+ const network::ResourceResponseHead& response_head) override {
response_head_ = response_head;
}
void OnStartLoadingResponseBody(
@@ -126,8 +126,6 @@ class NavigationPreloadLoaderClient final
void OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head) override {}
- void OnDataDownloaded(int64_t data_length,
- int64_t encoded_data_length) override {}
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override {}
@@ -145,72 +143,16 @@ class NavigationPreloadLoaderClient final
// Callbacks that complete Helper::OnFetchEvent().
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_;
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback_;
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback_;
DISALLOW_COPY_AND_ASSIGN(NavigationPreloadLoaderClient);
};
-// A URLLoaderFactory that returns 200 OK with a simple body to any request.
-//
-// ServiceWorkerNavigationLoaderTest sets the network factory for
-// ServiceWorkerContextCore to MockNetworkURLLoaderFactory. So far, it's only
-// used for navigation preload in these tests.
-class MockNetworkURLLoaderFactory final
- : public network::mojom::URLLoaderFactory {
- public:
- MockNetworkURLLoaderFactory() = default;
-
- // network::mojom::URLLoaderFactory implementation.
- void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- const network::ResourceRequest& url_request,
- network::mojom::URLLoaderClientPtr client,
- const net::MutableNetworkTrafficAnnotationTag&
- traffic_annotation) override {
- std::string headers = "HTTP/1.1 200 OK\n\n";
- net::HttpResponseInfo info;
- info.headers = new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
- network::ResourceResponseHead response;
- response.headers = info.headers;
- response.headers->GetMimeType(&response.mime_type);
- client->OnReceiveResponse(response, nullptr);
-
- std::string body = "this body came from the network";
- uint32_t bytes_written = body.size();
- mojo::DataPipe data_pipe;
- data_pipe.producer_handle->WriteData(body.data(), &bytes_written,
- MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
- client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
-
- network::URLLoaderCompletionStatus status;
- status.error_code = net::OK;
- client->OnComplete(status);
- }
-
- void Clone(network::mojom::URLLoaderFactoryRequest request) override {
- bindings_.AddBinding(this, std::move(request));
- }
-
- private:
- mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
- DISALLOW_COPY_AND_ASSIGN(MockNetworkURLLoaderFactory);
-};
-
// Helper simulates a service worker handling fetch events. The response can be
// customized via RespondWith* functions.
class Helper : public EmbeddedWorkerTestHelper {
public:
- Helper()
- : EmbeddedWorkerTestHelper(
- base::FilePath(),
- base::MakeRefCounted<URLLoaderFactoryGetter>()) {
- url_loader_factory_getter()->SetNetworkFactoryForTesting(
- &mock_url_loader_factory_);
- }
+ Helper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
~Helper() override = default;
// Tells this helper to respond to fetch events with the specified blob.
@@ -287,10 +229,10 @@ class Helper : public EmbeddedWorkerTestHelper {
void OnFetchEvent(
int embedded_worker_id,
const network::ResourceRequest& request,
- mojom::FetchEventPreloadHandlePtr preload_handle,
+ blink::mojom::FetchEventPreloadHandlePtr preload_handle,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback) override {
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
+ override {
// Basic checks on DispatchFetchEvent parameters.
EXPECT_TRUE(ServiceWorkerUtils::IsMainResourceType(
static_cast<ResourceType>(request.resource_type)));
@@ -375,7 +317,7 @@ class Helper : public EmbeddedWorkerTestHelper {
SimulateWorkerStopped(embedded_worker_id);
// Finish the event by calling |finish_callback|.
// This is the Mojo callback for
- // mojom::ServiceWorkerEventDispatcher::DispatchFetchEvent().
+ // mojom::ServiceWorker::DispatchFetchEvent().
// If this is not called, Mojo will complain. In production code,
// ServiceWorkerContextClient would call this when it aborts all
// callbacks after an unexpected stop.
@@ -444,13 +386,11 @@ class Helper : public EmbeddedWorkerTestHelper {
blink::mojom::ServiceWorkerStreamHandlePtr stream_handle_;
// For ResponseMode::kEarlyResponse.
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback_;
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback_;
// For ResponseMode::kRedirect.
GURL redirected_url_;
- MockNetworkURLLoaderFactory mock_url_loader_factory_;
DISALLOW_COPY_AND_ASSIGN(Helper);
};
@@ -471,6 +411,9 @@ CreateResponseInfoFromServiceWorker() {
return head;
}
+const char kHistogramMainResourceFetchEvent[] =
+ "ServiceWorker.FetchEvent.MainResource.Status";
+
// ServiceWorkerNavigationLoaderTest is for testing the handling of requests
// by a service worker via ServiceWorkerNavigationLoader.
//
@@ -487,12 +430,12 @@ class ServiceWorkerNavigationLoaderTest
public ServiceWorkerNavigationLoader::Delegate {
public:
ServiceWorkerNavigationLoaderTest()
- : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
- helper_(std::make_unique<Helper>()) {}
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
~ServiceWorkerNavigationLoaderTest() override = default;
void SetUp() override {
feature_list_.InitAndEnableFeature(network::features::kNetworkService);
+ helper_ = std::make_unique<Helper>();
// Create an active service worker.
storage()->LazyInitializeForTest(base::DoNothing());
@@ -517,11 +460,11 @@ class ServiceWorkerNavigationLoaderTest
// Make the registration findable via storage functions.
registration_->set_last_update_check(base::Time::Now());
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
storage()->StoreRegistration(registration_.get(), version_.get(),
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(SERVICE_WORKER_OK, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
}
ServiceWorkerStorage* storage() { return helper_->context()->storage(); }
@@ -620,6 +563,8 @@ class ServiceWorkerNavigationLoaderTest
};
TEST_F(ServiceWorkerNavigationLoaderTest, Basic) {
+ base::HistogramTester histogram_tester;
+
// Perform the request
LoaderResult result = StartRequest(CreateRequest());
EXPECT_EQ(LoaderResult::kHandledRequest, result);
@@ -629,9 +574,14 @@ TEST_F(ServiceWorkerNavigationLoaderTest, Basic) {
const network::ResourceResponseHead& info = client_.response_head();
EXPECT_EQ(200, info.headers->response_code());
ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker());
+
+ histogram_tester.ExpectUniqueSample(kHistogramMainResourceFetchEvent,
+ blink::ServiceWorkerStatusCode::kOk, 1);
}
TEST_F(ServiceWorkerNavigationLoaderTest, NoActiveWorker) {
+ base::HistogramTester histogram_tester;
+
// Clear |version_| to make GetServiceWorkerVersion() return null.
version_ = nullptr;
@@ -641,6 +591,9 @@ TEST_F(ServiceWorkerNavigationLoaderTest, NoActiveWorker) {
client_.RunUntilComplete();
EXPECT_EQ(net::ERR_FAILED, client_.completion_status().error_code);
+
+ // No fetch event was dispatched.
+ histogram_tester.ExpectTotalCount(kHistogramMainResourceFetchEvent, 0);
}
// Test that the request body is passed to the fetch event.
@@ -829,7 +782,8 @@ TEST_F(ServiceWorkerNavigationLoaderTest, StreamResponseAndCancel) {
EXPECT_TRUE(data_pipe.producer_handle.is_valid());
EXPECT_FALSE(loader_->WasCanceled());
EXPECT_TRUE(version_->HasWorkInBrowser());
- loader_->Cancel();
+ loader_ptr_.reset();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(loader_->WasCanceled());
EXPECT_FALSE(version_->HasWorkInBrowser());
@@ -850,6 +804,7 @@ TEST_F(ServiceWorkerNavigationLoaderTest, StreamResponseAndCancel) {
// Test when the service worker responds with network fallback.
// i.e., does not call respondWith().
TEST_F(ServiceWorkerNavigationLoaderTest, FallbackResponse) {
+ base::HistogramTester histogram_tester;
helper_->RespondWithFallback();
// Perform the request.
@@ -859,10 +814,13 @@ TEST_F(ServiceWorkerNavigationLoaderTest, FallbackResponse) {
// The request should not be handled by the loader, but it shouldn't be a
// failure.
EXPECT_FALSE(was_main_resource_load_failed_called_);
+ histogram_tester.ExpectUniqueSample(kHistogramMainResourceFetchEvent,
+ blink::ServiceWorkerStatusCode::kOk, 1);
}
// Test when the service worker rejects the FetchEvent.
TEST_F(ServiceWorkerNavigationLoaderTest, ErrorResponse) {
+ base::HistogramTester histogram_tester;
helper_->RespondWithError();
// Perform the request.
@@ -871,16 +829,24 @@ TEST_F(ServiceWorkerNavigationLoaderTest, ErrorResponse) {
client_.RunUntilComplete();
EXPECT_EQ(net::ERR_FAILED, client_.completion_status().error_code);
+
+ // Event dispatch still succeeded.
+ histogram_tester.ExpectUniqueSample(kHistogramMainResourceFetchEvent,
+ blink::ServiceWorkerStatusCode::kOk, 1);
}
// Test when dispatching the fetch event to the service worker failed.
TEST_F(ServiceWorkerNavigationLoaderTest, FailFetchDispatch) {
+ base::HistogramTester histogram_tester;
helper_->FailToDispatchFetchEvent();
// Perform the request.
LoaderResult result = StartRequest(CreateRequest());
EXPECT_EQ(LoaderResult::kDidNotHandleRequest, result);
EXPECT_TRUE(was_main_resource_load_failed_called_);
+ histogram_tester.ExpectUniqueSample(
+ kHistogramMainResourceFetchEvent,
+ blink::ServiceWorkerStatusCode::kErrorFailed, 1);
}
// Test when the respondWith() promise resolves before the waitUntil() promise
@@ -908,6 +874,8 @@ TEST_F(ServiceWorkerNavigationLoaderTest, EarlyResponse) {
// happens when there is no active service worker for the URL, or it must be
// skipped, etc.
TEST_F(ServiceWorkerNavigationLoaderTest, FallbackToNetwork) {
+ base::HistogramTester histogram_tester;
+
network::ResourceRequest request;
request.url = GURL("https://www.example.com/");
request.method = "GET";
@@ -926,6 +894,9 @@ TEST_F(ServiceWorkerNavigationLoaderTest, FallbackToNetwork) {
loader->FallbackToNetwork();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(handler);
+
+ // No fetch event was dispatched.
+ histogram_tester.ExpectTotalCount(kHistogramMainResourceFetchEvent, 0);
}
// Test responding to the fetch event with the navigation preload response.
@@ -956,6 +927,7 @@ TEST_F(ServiceWorkerNavigationLoaderTest, NavigationPreload) {
// Test responding to the fetch event with a redirect response.
TEST_F(ServiceWorkerNavigationLoaderTest, Redirect) {
+ base::HistogramTester histogram_tester;
GURL new_url("https://example.com/redirected");
helper_->RespondWithRedirectResponse(new_url);
@@ -972,6 +944,60 @@ TEST_F(ServiceWorkerNavigationLoaderTest, Redirect) {
EXPECT_EQ(301, redirect_info.status_code);
EXPECT_EQ("GET", redirect_info.new_method);
EXPECT_EQ(new_url, redirect_info.new_url);
+
+ histogram_tester.ExpectUniqueSample(kHistogramMainResourceFetchEvent,
+ blink::ServiceWorkerStatusCode::kOk, 1);
+}
+
+TEST_F(ServiceWorkerNavigationLoaderTest, LifetimeAfterForwardToServiceWorker) {
+ LoaderResult result = StartRequest(CreateRequest());
+ EXPECT_EQ(LoaderResult::kHandledRequest, result);
+ base::WeakPtr<ServiceWorkerNavigationLoader> loader = loader_->AsWeakPtr();
+ ASSERT_TRUE(loader);
+
+ client_.RunUntilComplete();
+ EXPECT_TRUE(loader);
+
+ // Even after calling DetachedFromRequest(), |loader_| should be alive until
+ // the Mojo connection to the loader is disconnected.
+ loader_.release()->DetachedFromRequest();
+ EXPECT_TRUE(loader);
+
+ // When the interface pointer to |loader_| is disconnected, its weak pointers
+ // (|loader|) are invalidated.
+ loader_ptr_.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(loader);
+
+ // |loader_| is deleted here. LSan test will alert if it leaks.
+}
+
+TEST_F(ServiceWorkerNavigationLoaderTest, LifetimeAfterFallbackToNetwork) {
+ network::ResourceRequest request;
+ request.url = GURL("https://www.example.com/");
+ request.method = "GET";
+ request.fetch_request_mode = network::mojom::FetchRequestMode::kNavigate;
+ request.fetch_credentials_mode =
+ network::mojom::FetchCredentialsMode::kInclude;
+ request.fetch_redirect_mode = network::mojom::FetchRedirectMode::kManual;
+
+ SingleRequestURLLoaderFactory::RequestHandler handler;
+ auto loader = std::make_unique<ServiceWorkerNavigationLoader>(
+ base::BindOnce(&ReceiveRequestHandler, &handler), this, request,
+ base::WrapRefCounted<URLLoaderFactoryGetter>(
+ helper_->context()->loader_factory_getter()));
+ base::WeakPtr<ServiceWorkerNavigationLoader> loader_weakptr =
+ loader->AsWeakPtr();
+ // Ask the loader to fallback to network. In production code,
+ // ServiceWorkerControlleeRequestHandler calls FallbackToNetwork() to do this.
+ loader->FallbackToNetwork();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(handler);
+ EXPECT_TRUE(loader_weakptr);
+
+ // DetachedFromRequest() deletes |loader_|.
+ loader.release()->DetachedFromRequest();
+ EXPECT_FALSE(loader_weakptr);
}
} // namespace service_worker_navigation_loader_unittest
diff --git a/chromium/content/browser/service_worker/service_worker_new_script_loader.cc b/chromium/content/browser/service_worker/service_worker_new_script_loader.cc
index 99d175d307f..369f7356f0d 100644
--- a/chromium/content/browser/service_worker/service_worker_new_script_loader.cc
+++ b/chromium/content/browser/service_worker/service_worker_new_script_loader.cc
@@ -46,6 +46,7 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
base::SequencedTaskRunnerHandle::Get()),
loader_factory_(std::move(loader_factory)),
client_(std::move(client)),
+ original_options_(options),
weak_factory_(this) {
network::ResourceRequest resource_request(original_request);
@@ -85,11 +86,24 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
incumbent_cache_resource_id =
stored_version->script_cache_map()->LookupResourceId(request_url_);
}
+ // Request SSLInfo. It will be persisted in service worker storage and
+ // may be used by ServiceWorkerNavigationLoader for navigations handled
+ // by this service worker.
+ options |= network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
}
+ // Bypass the browser cache if needed, e.g., updateViaCache demands it or 24
+ // hours passed since the last update check that hit network.
+ base::TimeDelta time_since_last_check =
+ base::Time::Now() - registration->last_update_check();
if (ServiceWorkerUtils::ShouldBypassCacheDueToUpdateViaCache(
- is_main_script, registration->update_via_cache()))
+ is_main_script, registration->update_via_cache()) ||
+ time_since_last_check > kServiceWorkerScriptMaxCacheAge ||
+ version_->force_bypass_cache_for_scripts()) {
resource_request.load_flags |= net::LOAD_BYPASS_CACHE;
+ }
+
+ resource_request.headers.SetHeader("Service-Worker", "script");
// Create response readers only when we have to do the byte-for-byte check.
std::unique_ptr<ServiceWorkerResponseReader> compare_reader;
@@ -105,7 +119,6 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
version_->script_cache_map()->NotifyStartedCaching(request_url_,
cache_resource_id);
- AdvanceState(State::kStarted);
// Disable MIME sniffing. The spec requires the header list to have a
// JavaScript MIME type. Therefore, no sniffing is needed.
@@ -116,11 +129,15 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
loader_factory_->CreateLoaderAndStart(
mojo::MakeRequest(&network_loader_), routing_id, request_id, options,
resource_request, std::move(network_client), traffic_annotation);
+ DCHECK_EQ(NetworkLoaderState::kNotStarted, network_loader_state_);
+ network_loader_state_ = NetworkLoaderState::kLoadingHeader;
}
ServiceWorkerNewScriptLoader::~ServiceWorkerNewScriptLoader() = default;
void ServiceWorkerNewScriptLoader::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
// Resource requests for service worker scripts should not follow redirects.
// See comments in OnReceiveRedirect().
@@ -147,8 +164,8 @@ void ServiceWorkerNewScriptLoader::ResumeReadingBodyFromNet() {
// URLLoaderClient for network loader ------------------------------------------
void ServiceWorkerNewScriptLoader::OnReceiveResponse(
- const network::ResourceResponseHead& response_head,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
+ const network::ResourceResponseHead& response_head) {
+ DCHECK_EQ(NetworkLoaderState::kLoadingHeader, network_loader_state_);
if (!version_->context() || version_->is_redundant()) {
CommitCompleted(network::URLLoaderCompletionStatus(net::ERR_FAILED),
kServiceWorkerFetchScriptError);
@@ -170,6 +187,9 @@ void ServiceWorkerNewScriptLoader::OnReceiveResponse(
// The following sequence is equivalent to
// ServiceWorkerWriteToCacheJob::OnResponseStarted.
+ // TODO(falken): Make these steps be in the same order as the spec. Right now
+ // there are slight differences, like we only bump last update check time on
+ // OK status.
if (response_head.headers->response_code() / 100 != 2) {
// Non-2XX HTTP status code is handled as an error.
@@ -221,13 +241,28 @@ void ServiceWorkerNewScriptLoader::OnReceiveResponse(
return;
}
+ if (response_head.network_accessed)
+ version_->embedded_worker()->OnNetworkAccessedForScriptLoad();
+
version_->SetMainScriptHttpResponseInfo(*response_info);
}
WriteHeaders(
base::MakeRefCounted<HttpResponseInfoIOBuffer>(response_info.release()));
- client_->OnReceiveResponse(response_head, std::move(downloaded_file));
+ // Don't pass SSLInfo to the client when the original request doesn't ask
+ // to send it.
+ if (response_head.ssl_info.has_value() &&
+ !(original_options_ &
+ network::mojom::kURLLoadOptionSendSSLInfoWithResponse)) {
+ network::ResourceResponseHead new_response_head = response_head;
+ new_response_head.ssl_info.reset();
+ client_->OnReceiveResponse(new_response_head);
+ } else {
+ client_->OnReceiveResponse(response_head);
+ }
+
+ network_loader_state_ = NetworkLoaderState::kWaitingForBody;
}
void ServiceWorkerNewScriptLoader::OnReceiveRedirect(
@@ -241,11 +276,6 @@ void ServiceWorkerNewScriptLoader::OnReceiveRedirect(
kServiceWorkerRedirectError);
}
-void ServiceWorkerNewScriptLoader::OnDataDownloaded(int64_t data_len,
- int64_t encoded_data_len) {
- client_->OnDataDownloaded(data_len, encoded_data_len);
-}
-
void ServiceWorkerNewScriptLoader::OnUploadProgress(
int64_t current_position,
int64_t total_size,
@@ -266,6 +296,7 @@ void ServiceWorkerNewScriptLoader::OnTransferSizeUpdated(
void ServiceWorkerNewScriptLoader::OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle consumer) {
+ DCHECK_EQ(NetworkLoaderState::kWaitingForBody, network_loader_state_);
// Create a pair of the consumer and producer for responding to the client.
mojo::ScopedDataPipeConsumerHandle client_consumer;
if (mojo::CreateDataPipe(nullptr, &client_producer_, &client_consumer) !=
@@ -279,61 +310,75 @@ void ServiceWorkerNewScriptLoader::OnStartLoadingResponseBody(
client_->OnStartLoadingResponseBody(std::move(client_consumer));
network_consumer_ = std::move(consumer);
+ network_loader_state_ = NetworkLoaderState::kLoadingBody;
MaybeStartNetworkConsumerHandleWatcher();
}
void ServiceWorkerNewScriptLoader::OnComplete(
const network::URLLoaderCompletionStatus& status) {
+ DCHECK(network_loader_state_ == NetworkLoaderState::kWaitingForBody ||
+ network_loader_state_ == NetworkLoaderState::kLoadingBody);
+ NetworkLoaderState previous_state = network_loader_state_;
+ network_loader_state_ = NetworkLoaderState::kCompleted;
if (status.error_code != net::OK) {
CommitCompleted(status, kServiceWorkerFetchScriptError);
return;
}
- network_load_completed_ = true;
- switch (state_) {
- case State::kNotStarted:
- case State::kCompleted:
- break;
- case State::kStarted:
- case State::kWroteHeaders:
- // CommitCompleted() will be called after the data is written in the
- // storage.
- return;
- case State::kWroteData:
- CommitCompleted(network::URLLoaderCompletionStatus(net::OK),
- std::string() /* status_message */);
- return;
+ // Response body is empty.
+ if (previous_state == NetworkLoaderState::kWaitingForBody) {
+ DCHECK_EQ(WriterState::kNotStarted, body_writer_state_);
+ body_writer_state_ = WriterState::kCompleted;
+ switch (header_writer_state_) {
+ case WriterState::kNotStarted:
+ NOTREACHED()
+ << "Response header should be received before OnComplete()";
+ break;
+ case WriterState::kWriting:
+ // Wait until it's written. OnWriteHeadersComplete() will call
+ // CommitCompleted().
+ return;
+ case WriterState::kCompleted:
+ DCHECK(!network_consumer_.is_valid());
+ CommitCompleted(network::URLLoaderCompletionStatus(net::OK),
+ std::string() /* status_message */);
+ return;
+ }
+ NOTREACHED();
}
- NOTREACHED() << static_cast<int>(state_);
-}
-
-// End of URLLoaderClient ------------------------------------------------------
-void ServiceWorkerNewScriptLoader::AdvanceState(State new_state) {
- switch (state_) {
- case State::kNotStarted:
- DCHECK_EQ(State::kStarted, new_state);
- break;
- case State::kStarted:
- DCHECK(new_state == State::kWroteHeaders ||
- new_state == State::kCompleted);
- break;
- case State::kWroteHeaders:
- DCHECK(new_state == State::kWroteData || new_state == State::kCompleted);
- break;
- case State::kWroteData:
- DCHECK_EQ(State::kCompleted, new_state);
- break;
- case State::kCompleted:
- // This is the end state.
- NOTREACHED();
- break;
+ // Response body exists.
+ if (previous_state == NetworkLoaderState::kLoadingBody) {
+ switch (body_writer_state_) {
+ case WriterState::kNotStarted:
+ // Wait until it's written. OnNetworkDataAvailable() will call
+ // CommitCompleted() after all data from |network_consumer_| is
+ // consumed.
+ DCHECK_EQ(WriterState::kWriting, header_writer_state_);
+ return;
+ case WriterState::kWriting:
+ // Wait until it's written. OnNetworkDataAvailable() will call
+ // CommitCompleted() after all data from |network_consumer_| is
+ // consumed.
+ DCHECK_EQ(WriterState::kCompleted, header_writer_state_);
+ return;
+ case WriterState::kCompleted:
+ DCHECK_EQ(WriterState::kCompleted, header_writer_state_);
+ CommitCompleted(network::URLLoaderCompletionStatus(net::OK),
+ std::string() /* status_message */);
+ return;
+ }
+ NOTREACHED();
}
- state_ = new_state;
+
+ NOTREACHED();
}
+// End of URLLoaderClient ------------------------------------------------------
void ServiceWorkerNewScriptLoader::WriteHeaders(
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer) {
+ DCHECK_EQ(WriterState::kNotStarted, header_writer_state_);
+ header_writer_state_ = WriterState::kWriting;
net::Error error = cache_writer_->MaybeWriteHeaders(
info_buffer.get(),
base::BindOnce(&ServiceWorkerNewScriptLoader::OnWriteHeadersComplete,
@@ -348,28 +393,43 @@ void ServiceWorkerNewScriptLoader::WriteHeaders(
}
void ServiceWorkerNewScriptLoader::OnWriteHeadersComplete(net::Error error) {
+ DCHECK_EQ(WriterState::kWriting, header_writer_state_);
DCHECK_NE(net::ERR_IO_PENDING, error);
if (error != net::OK) {
+ ServiceWorkerMetrics::CountWriteResponseResult(
+ ServiceWorkerMetrics::WRITE_HEADERS_ERROR);
CommitCompleted(network::URLLoaderCompletionStatus(error),
kServiceWorkerFetchScriptError);
return;
}
- AdvanceState(State::kWroteHeaders);
+ header_writer_state_ = WriterState::kCompleted;
+
+ // If all other states are kCompleted the response body is empty, we can
+ // finish now.
+ if (network_loader_state_ == NetworkLoaderState::kCompleted &&
+ body_writer_state_ == WriterState::kCompleted) {
+ CommitCompleted(network::URLLoaderCompletionStatus(net::OK),
+ std::string() /* status_message */);
+ return;
+ }
+
MaybeStartNetworkConsumerHandleWatcher();
}
void ServiceWorkerNewScriptLoader::MaybeStartNetworkConsumerHandleWatcher() {
- if (!network_consumer_.is_valid()) {
- // Wait until the network consumer handle is ready to read.
- // OnStartLoadingResponseBody() will continue the sequence.
+ if (network_loader_state_ == NetworkLoaderState::kWaitingForBody) {
+ // OnStartLoadingResponseBody() or OnComplete() will continue the sequence.
return;
}
- if (state_ != State::kWroteHeaders) {
- // Wait until the headers are written in the script storage because the
- // cache writer cannot write the headers and data in parallel.
+ if (header_writer_state_ != WriterState::kCompleted) {
+ DCHECK_EQ(WriterState::kWriting, header_writer_state_);
// OnWriteHeadersComplete() will continue the sequence.
return;
}
+
+ DCHECK_EQ(WriterState::kNotStarted, body_writer_state_);
+ body_writer_state_ = WriterState::kWriting;
+
network_watcher_.Watch(
network_consumer_.get(),
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
@@ -379,6 +439,8 @@ void ServiceWorkerNewScriptLoader::MaybeStartNetworkConsumerHandleWatcher() {
}
void ServiceWorkerNewScriptLoader::OnNetworkDataAvailable(MojoResult) {
+ DCHECK_EQ(WriterState::kCompleted, header_writer_state_);
+ DCHECK_EQ(WriterState::kWriting, body_writer_state_);
DCHECK(network_consumer_.is_valid());
scoped_refptr<network::MojoToNetPendingBuffer> pending_buffer;
uint32_t bytes_available = 0;
@@ -392,10 +454,11 @@ void ServiceWorkerNewScriptLoader::OnNetworkDataAvailable(MojoResult) {
// Closed by peer. This indicates all the data from the network service
// are read or there is an error. In the error case, the reason is
// notified via OnComplete().
- AdvanceState(State::kWroteData);
- if (network_load_completed_)
+ body_writer_state_ = WriterState::kCompleted;
+ if (network_loader_state_ == NetworkLoaderState::kCompleted) {
CommitCompleted(network::URLLoaderCompletionStatus(net::OK),
std::string() /* status_message */);
+ }
return;
case MOJO_RESULT_SHOULD_WAIT:
network_watcher_.ArmOrNotify();
@@ -419,6 +482,8 @@ void ServiceWorkerNewScriptLoader::WriteData(
case MOJO_RESULT_OK:
break;
case MOJO_RESULT_FAILED_PRECONDITION:
+ ServiceWorkerMetrics::CountWriteResponseResult(
+ ServiceWorkerMetrics::WRITE_DATA_ERROR);
CommitCompleted(network::URLLoaderCompletionStatus(net::ERR_FAILED),
kServiceWorkerFetchScriptError);
return;
@@ -457,11 +522,15 @@ void ServiceWorkerNewScriptLoader::OnWriteDataComplete(
net::Error error) {
DCHECK_NE(net::ERR_IO_PENDING, error);
if (error != net::OK) {
+ ServiceWorkerMetrics::CountWriteResponseResult(
+ ServiceWorkerMetrics::WRITE_DATA_ERROR);
CommitCompleted(network::URLLoaderCompletionStatus(error),
kServiceWorkerFetchScriptError);
return;
}
DCHECK(pending_buffer);
+ ServiceWorkerMetrics::CountWriteResponseResult(
+ ServiceWorkerMetrics::WRITE_OK);
pending_buffer->CompleteRead(bytes_written);
// Get the consumer handle from a previous read operation if we have one.
network_consumer_ = pending_buffer->ReleaseHandle();
@@ -471,15 +540,18 @@ void ServiceWorkerNewScriptLoader::OnWriteDataComplete(
void ServiceWorkerNewScriptLoader::CommitCompleted(
const network::URLLoaderCompletionStatus& status,
const std::string& status_message) {
- AdvanceState(State::kCompleted);
net::Error error_code = static_cast<net::Error>(status.error_code);
int bytes_written = -1;
if (error_code == net::OK) {
+ DCHECK_EQ(NetworkLoaderState::kCompleted, network_loader_state_);
+ DCHECK_EQ(WriterState::kCompleted, header_writer_state_);
+ DCHECK_EQ(WriterState::kCompleted, body_writer_state_);
// If all the calls to WriteHeaders/WriteData succeeded, but the incumbent
// entry wasn't actually replaced because the new entry was equivalent, the
// new version didn't actually install because it already exists.
if (!cache_writer_->did_replace()) {
- version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS);
+ version_->SetStartWorkerStatusCode(
+ blink::ServiceWorkerStatusCode::kErrorExists);
error_code = ServiceWorkerWriteToCacheJob::kIdenticalScriptError;
}
bytes_written = cache_writer_->bytes_written();
@@ -494,8 +566,6 @@ void ServiceWorkerNewScriptLoader::CommitCompleted(
version_->script_cache_map()->NotifyFinishedCaching(
request_url_, bytes_written, error_code, status_message);
- // TODO(nhiroki): Record ServiceWorkerMetrics::CountWriteResponseResult().
- // (https://crbug.com/762357)
client_->OnComplete(status);
client_producer_.reset();
@@ -504,6 +574,9 @@ void ServiceWorkerNewScriptLoader::CommitCompleted(
network_consumer_.reset();
network_watcher_.Cancel();
cache_writer_.reset();
+ network_loader_state_ = NetworkLoaderState::kCompleted;
+ header_writer_state_ = WriterState::kCompleted;
+ body_writer_state_ = WriterState::kCompleted;
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_new_script_loader.h b/chromium/content/browser/service_worker/service_worker_new_script_loader.h
index c26100f4ca9..d9d94245903 100644
--- a/chromium/content/browser/service_worker/service_worker_new_script_loader.h
+++ b/chromium/content/browser/service_worker/service_worker_new_script_loader.h
@@ -27,7 +27,7 @@ struct HttpResponseInfoIOBuffer;
// network, and returns the response to |client|, while also writing the
// response into the service worker script storage.
//
-// This works as follows:
+// In the common case, this works as follows:
// 1. Makes a network request.
// 2. OnReceiveResponse() is called, writes the response headers to the
// service worker script storage and responds with them to the |client|
@@ -38,6 +38,14 @@ struct HttpResponseInfoIOBuffer;
// 4. OnComplete() for the network load and OnWriteDataComplete() are called,
// calls CommitCompleted() and closes the connections with the network
// service and the renderer process.
+// In an uncommon case, the response body is empty so
+// OnStartLoadingResponseBody() is not called.
+//
+// A set of |network_loader_state_|, |header_writer_state_|, and
+// |body_writer_state_| is the state of this loader. Each of them is changed
+// independently, while some state changes have dependency to other state
+// changes. See the comment for each field below to see exactly when their
+// state changes happen.
//
// In case there is already an installed service worker for this registration,
// this class also performs the "byte-for-byte" comparison for updating the
@@ -67,7 +75,9 @@ class CONTENT_EXPORT ServiceWorkerNewScriptLoader
~ServiceWorkerNewScriptLoader() override;
// network::mojom::URLLoader:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
@@ -77,12 +87,10 @@ class CONTENT_EXPORT ServiceWorkerNewScriptLoader
// network::mojom::URLLoaderClient for the network load:
void OnReceiveResponse(
- const network::ResourceResponseHead& response_head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override;
+ const network::ResourceResponseHead& response_head) override;
void OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head) override;
- void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
@@ -96,14 +104,15 @@ class CONTENT_EXPORT ServiceWorkerNewScriptLoader
const static uint32_t kReadBufferSize;
private:
- enum class State {
+ enum class NetworkLoaderState {
kNotStarted,
- kStarted,
- kWroteHeaders,
- kWroteData,
+ kLoadingHeader,
+ kWaitingForBody,
+ kLoadingBody,
kCompleted,
};
- void AdvanceState(State new_state);
+
+ enum class WriterState { kNotStarted, kWriting, kCompleted };
// Writes the given headers into the service worker script storage.
void WriteHeaders(scoped_refptr<HttpResponseInfoIOBuffer> info_buffer);
@@ -146,14 +155,50 @@ class CONTENT_EXPORT ServiceWorkerNewScriptLoader
mojo::Binding<network::mojom::URLLoaderClient> network_client_binding_;
mojo::ScopedDataPipeConsumerHandle network_consumer_;
mojo::SimpleWatcher network_watcher_;
- bool network_load_completed_ = false;
scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
// Used for responding with the fetched script to this loader's client.
network::mojom::URLLoaderClientPtr client_;
mojo::ScopedDataPipeProducerHandle client_producer_;
- State state_ = State::kNotStarted;
+ // Represents the state of |network_loader_|.
+ // Corresponds to the steps described in the class comments.
+ //
+ // When response body exists:
+ // CreateLoaderAndStart(): kNotStarted -> kLoadingHeader
+ // OnReceiveResponse(): kLoadingHeader -> kWaitingForBody
+ // OnStartLoadingResponseBody(): kWaitingForBody -> kLoadingBody
+ // OnComplete(): kLoadingBody -> kCompleted
+ //
+ // When response body is empty:
+ // CreateLoaderAndStart(): kNotStarted -> kLoadingHeader
+ // OnReceiveResponse(): kLoadingHeader -> kWaitingForBody
+ // OnComplete(): kWaitingForBody -> kCompleted
+ NetworkLoaderState network_loader_state_ = NetworkLoaderState::kNotStarted;
+
+ // Represents the state of |cache_writer_|.
+ // Set to kWriting when it starts to write the header, and set to kCompleted
+ // when the header has been written.
+ //
+ // OnReceiveResponse(): kNotStarted -> kWriting (in WriteHeaders())
+ // OnWriteHeadersComplete(): kWriting -> kCompleted
+ WriterState header_writer_state_ = WriterState::kNotStarted;
+
+ // Represents the state of |cache_writer_| and |network_consumer_|.
+ // Set to kWriting when |this| starts watching |network_consumer_|, and set to
+ // kCompleted when all data has been written to |cache_writer_|.
+ //
+ // When response body exists:
+ // OnStartLoadingResponseBody() && OnWriteHeadersComplete():
+ // kNotStarted -> kWriting
+ // OnNetworkDataAvailable() && MOJO_RESULT_FAILED_PRECONDITION:
+ // kWriting -> kCompleted
+ //
+ // When response body is empty:
+ // OnComplete(): kNotStarted -> kCompleted
+ WriterState body_writer_state_ = WriterState::kNotStarted;
+
+ const uint32_t original_options_;
base::WeakPtrFactory<ServiceWorkerNewScriptLoader> weak_factory_;
diff --git a/chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc b/chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
index 100e0c71be4..7494702698a 100644
--- a/chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
@@ -5,9 +5,12 @@
#include "content/browser/service_worker/service_worker_new_script_loader.h"
#include <map>
+#include <memory>
+#include <string>
#include <utility>
#include "base/run_loop.h"
#include "base/strings/string_util.h"
+#include "base/test/metrics/histogram_tester.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_disk_cache.h"
@@ -15,6 +18,7 @@
#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
+#include "net/base/load_flags.h"
#include "net/base/test_completion_callback.h"
#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
@@ -26,10 +30,13 @@
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace content {
-
-namespace {
+namespace service_worker_new_script_loader_unittest {
const char kNormalScriptURL[] = "https://example.com/normal.js";
+const char kNormalImportedScriptURL[] =
+ "https://my-awesome-cdn.com/import_script.js";
+const char kHistogramWriteResponseResult[] =
+ "ServiceWorker.DiskCache.WriteResponseResult";
// MockHTTPServer is a utility to provide mocked responses for
// ServiceWorkerNewScriptLoader.
@@ -60,11 +67,6 @@ class MockHTTPServer {
};
// A URLLoaderFactory that returns a mocked response provided by MockHTTPServer.
-//
-// TODO(nhiroki): We copied this from
-// service_worker_navigation_loader_unittest.cc instead of making it a common
-// test helper because we might want to customize the mock factory to add more
-// tests later. Merge this and that if we're convinced it's better.
class MockNetworkURLLoaderFactory final
: public network::mojom::URLLoaderFactory {
public:
@@ -80,6 +82,7 @@ class MockNetworkURLLoaderFactory final
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override {
+ last_request_ = url_request;
const MockHTTPServer::Response& response =
mock_server_->Get(url_request.url);
@@ -91,6 +94,7 @@ class MockNetworkURLLoaderFactory final
network::ResourceResponseHead response_head;
response_head.headers = info.headers;
response_head.headers->GetMimeType(&response_head.mime_type);
+ response_head.network_accessed = access_network_;
if (response.has_certificate_error) {
response_head.cert_status = net::CERT_STATUS_DATE_INVALID;
}
@@ -99,34 +103,46 @@ class MockNetworkURLLoaderFactory final
client->OnReceiveRedirect(net::RedirectInfo(), response_head);
return;
}
- client->OnReceiveResponse(response_head, nullptr /* downloaded_file */);
+ client->OnReceiveResponse(response_head);
// Pass the response body to the client.
- uint32_t bytes_written = response.body.size();
- mojo::DataPipe data_pipe;
- MojoResult result = data_pipe.producer_handle->WriteData(
- response.body.data(), &bytes_written, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
- ASSERT_EQ(MOJO_RESULT_OK, result);
- client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
-
+ if (!response.body.empty()) {
+ uint32_t bytes_written = response.body.size();
+ mojo::DataPipe data_pipe;
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ response.body.data(), &bytes_written,
+ MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
+ }
network::URLLoaderCompletionStatus status;
status.error_code = net::OK;
client->OnComplete(status);
}
+ void set_to_access_network(bool access_network) {
+ access_network_ = access_network;
+ }
+
+ network::ResourceRequest last_request() const { return last_request_; }
+
void Clone(network::mojom::URLLoaderFactoryRequest factory) override {
NOTREACHED();
}
private:
- // This is owned by ServiceWorkerNewScriptLoaderTest.
+ // |mock_server_| is owned by ServiceWorkerNewScriptLoaderTest.
MockHTTPServer* mock_server_;
+ // The most recent request received by this factory.
+ network::ResourceRequest last_request_;
+
+ // Controls whether a load simulates accessing network or cache.
+ bool access_network_ = false;
+
DISALLOW_COPY_AND_ASSIGN(MockNetworkURLLoaderFactory);
};
-} // namespace
-
// ServiceWorkerNewScriptLoaderTest is for testing the handling of requests for
// installing service worker scripts via ServiceWorkerNewScriptLoader.
class ServiceWorkerNewScriptLoaderTest : public testing::Test {
@@ -139,8 +155,7 @@ class ServiceWorkerNewScriptLoaderTest : public testing::Test {
ServiceWorkerContextCore* context() { return helper_->context(); }
void SetUp() override {
- helper_ = std::make_unique<EmbeddedWorkerTestHelper>(
- base::FilePath(), base::MakeRefCounted<URLLoaderFactoryGetter>());
+ helper_ = std::make_unique<EmbeddedWorkerTestHelper>(base::FilePath());
InitializeStorage();
@@ -149,13 +164,19 @@ class ServiceWorkerNewScriptLoaderTest : public testing::Test {
std::string("HTTP/1.1 200 OK\n"
"Content-Type: text/javascript\n\n"),
std::string("this body came from the network")));
+ mock_server_->Set(
+ GURL(kNormalImportedScriptURL),
+ MockHTTPServer::Response(
+ std::string("HTTP/1.1 200 OK\n"
+ "Content-Type: text/javascript\n\n"),
+ std::string(
+ "this is an import script response body from the network")));
// Initialize URLLoaderFactory.
network::mojom::URLLoaderFactoryPtr test_loader_factory;
mock_url_loader_factory_ =
std::make_unique<MockNetworkURLLoaderFactory>(mock_server_.get());
- helper_->url_loader_factory_getter()->SetNetworkFactoryForTesting(
- mock_url_loader_factory_.get());
+ helper_->SetNetworkFactory(mock_url_loader_factory_.get());
}
void InitializeStorage() {
@@ -166,48 +187,47 @@ class ServiceWorkerNewScriptLoaderTest : public testing::Test {
// Sets up ServiceWorkerRegistration and ServiceWorkerVersion. This should be
// called before DoRequest().
- void SetUpRegistration(const GURL& script_url, const GURL& scope) {
+ void SetUpRegistration(const GURL& script_url) {
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = scope;
+ options.scope = script_url.GetWithoutFilename();
+ SetUpRegistrationWithOptions(script_url, options);
+ }
+ void SetUpRegistrationWithOptions(
+ const GURL& script_url,
+ blink::mojom::ServiceWorkerRegistrationOptions options) {
registration_ = base::MakeRefCounted<ServiceWorkerRegistration>(
options, context()->storage()->NewRegistrationId(),
context()->AsWeakPtr());
- version_ = base::MakeRefCounted<ServiceWorkerVersion>(
- registration_.get(), script_url, context()->storage()->NewVersionId(),
- helper_->context()->AsWeakPtr());
- version_->SetStatus(ServiceWorkerVersion::NEW);
- }
-
- // Sets up ServiceWorkerRegistration and ServiceWorkerVersion with the default
- // scope.
- void SetUpRegistration(const GURL& script_url) {
- SetUpRegistration(script_url, script_url.GetWithoutFilename());
+ SetUpVersion(script_url);
}
- // Creates an active worker in |registration_|. After this is called,
- // |version_| will be a new, uninstalled version. The next time DoRequest() is
- // called, |version_| will attempt to update, comparing against the active
- // worker.
- void SetUpActivatedWorker(const GURL& script_url) {
- DoRequest(script_url);
- client_->RunUntilComplete();
- EXPECT_EQ(net::OK, client_->completion_status().error_code);
- loader_.reset();
- client_.reset();
-
+ // Promotes |version_| to |registration_|'s active version, and then resets
+ // |version_| to null (as subsequent DoRequest() calls should not attempt to
+ // install or update |version_|).
+ void ActivateVersion() {
version_->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST);
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
registration_->SetActiveVersion(version_);
+ version_ = nullptr;
+ }
+ // After this is called, |version_| will be a new, uninstalled version. The
+ // next time DoRequest() is called, |version_| will attempt to install,
+ // possibly updating if registration has an installed worker.
+ void SetUpVersion(const GURL& script_url) {
version_ = base::MakeRefCounted<ServiceWorkerVersion>(
registration_.get(), script_url, context()->storage()->NewVersionId(),
context()->AsWeakPtr());
version_->SetStatus(ServiceWorkerVersion::NEW);
- version_->set_pause_after_download(true);
+
+ if (registration_->waiting_version() || registration_->active_version())
+ version_->SetToPauseAfterDownload(base::DoNothing());
}
- void DoRequest(const GURL& request_url) {
+ void DoRequest(const GURL& url,
+ std::unique_ptr<network::TestURLLoaderClient>* out_client,
+ std::unique_ptr<ServiceWorkerNewScriptLoader>* out_loader) {
DCHECK(registration_);
DCHECK(version_);
@@ -217,17 +237,17 @@ class ServiceWorkerNewScriptLoaderTest : public testing::Test {
uint32_t options = 0;
network::ResourceRequest request;
- request.url = version_->script_url();
+ request.url = url;
request.method = "GET";
- // TODO(nhiroki): Test importScripts() cases.
- request.resource_type = RESOURCE_TYPE_SERVICE_WORKER;
-
- DCHECK(!loader_);
- DCHECK(!client_);
- client_ = std::make_unique<network::TestURLLoaderClient>();
- loader_ = std::make_unique<ServiceWorkerNewScriptLoader>(
- routing_id, request_id, options, request, client_->CreateInterfacePtr(),
- version_, helper_->url_loader_factory_getter()->GetNetworkFactory(),
+ request.resource_type = (url == version_->script_url())
+ ? RESOURCE_TYPE_SERVICE_WORKER
+ : RESOURCE_TYPE_SCRIPT;
+
+ *out_client = std::make_unique<network::TestURLLoaderClient>();
+ *out_loader = std::make_unique<ServiceWorkerNewScriptLoader>(
+ routing_id, request_id, options, request,
+ (*out_client)->CreateInterfacePtr(), version_,
+ helper_->url_loader_factory_getter()->GetNetworkFactory(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
}
@@ -284,56 +304,67 @@ class ServiceWorkerNewScriptLoaderTest : public testing::Test {
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
- std::unique_ptr<ServiceWorkerNewScriptLoader> loader_;
std::unique_ptr<MockHTTPServer> mock_server_;
-
- std::unique_ptr<network::TestURLLoaderClient> client_;
};
TEST_F(ServiceWorkerNewScriptLoaderTest, Success) {
+ base::HistogramTester histogram_tester;
+
const GURL kScriptURL(kNormalScriptURL);
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
SetUpRegistration(kScriptURL);
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
- EXPECT_EQ(net::OK, client_->completion_status().error_code);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
// The client should have received the response.
- EXPECT_TRUE(client_->has_received_response());
- EXPECT_TRUE(client_->response_body().is_valid());
+ EXPECT_TRUE(client->has_received_response());
+ EXPECT_TRUE(client->response_body().is_valid());
std::string response;
EXPECT_TRUE(
- mojo::BlockingCopyToString(client_->response_body_release(), &response));
+ mojo::BlockingCopyToString(client->response_body_release(), &response));
EXPECT_EQ(mock_server_->Get(kScriptURL).body, response);
// The response should also be stored in the storage.
EXPECT_TRUE(VerifyStoredResponse(kScriptURL));
+ histogram_tester.ExpectUniqueSample(kHistogramWriteResponseResult,
+ ServiceWorkerMetrics::WRITE_OK, 1);
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Success_EmptyBody) {
+ base::HistogramTester histogram_tester;
+
const GURL kScriptURL("https://example.com/empty.js");
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
mock_server_->Set(
kScriptURL,
MockHTTPServer::Response(std::string("HTTP/1.1 200 OK\n"
"Content-Type: text/javascript\n\n"),
std::string()));
SetUpRegistration(kScriptURL);
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
- EXPECT_EQ(net::OK, client_->completion_status().error_code);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
// The client should have received the response.
- EXPECT_TRUE(client_->has_received_response());
- EXPECT_TRUE(client_->response_body().is_valid());
- std::string response;
- EXPECT_TRUE(
- mojo::BlockingCopyToString(client_->response_body_release(), &response));
- EXPECT_TRUE(response.empty());
+ EXPECT_TRUE(client->has_received_response());
+ EXPECT_FALSE(client->response_body().is_valid());
// The response should also be stored in the storage.
EXPECT_TRUE(VerifyStoredResponse(kScriptURL));
+ // We don't record write response result if body is empty.
+ histogram_tester.ExpectTotalCount(kHistogramWriteResponseResult, 0);
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Success_LargeBody) {
+ base::HistogramTester histogram_tester;
+
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
// Create a response that has a larger body than the script loader's buffer
// to test chunked data write. We chose this multiplier to avoid hitting the
// limit of mojo's data pipe buffer (it's about kReadBufferSize * 2 as of
@@ -347,58 +378,80 @@ TEST_F(ServiceWorkerNewScriptLoaderTest, Success_LargeBody) {
"Content-Type: text/javascript\n\n"),
std::string(kBodySize, 'a')));
SetUpRegistration(kScriptURL);
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
- EXPECT_EQ(net::OK, client_->completion_status().error_code);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
// The client should have received the response.
- EXPECT_TRUE(client_->has_received_response());
- EXPECT_TRUE(client_->response_body().is_valid());
+ EXPECT_TRUE(client->has_received_response());
+ EXPECT_TRUE(client->response_body().is_valid());
std::string response;
EXPECT_TRUE(
- mojo::BlockingCopyToString(client_->response_body_release(), &response));
+ mojo::BlockingCopyToString(client->response_body_release(), &response));
EXPECT_EQ(mock_server_->Get(kScriptURL).body, response);
// The response should also be stored in the storage.
EXPECT_TRUE(VerifyStoredResponse(kScriptURL));
+ // WRITE_OK should be recorded twice as we record every single write success.
+ histogram_tester.ExpectUniqueSample(kHistogramWriteResponseResult,
+ ServiceWorkerMetrics::WRITE_OK, 2);
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Error_404) {
+ base::HistogramTester histogram_tester;
+
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
const GURL kScriptURL("https://example.com/nonexistent.js");
mock_server_->Set(kScriptURL, MockHTTPServer::Response(
std::string("HTTP/1.1 404 Not Found\n\n"),
std::string()));
SetUpRegistration(kScriptURL);
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
// The request should be failed because of the 404 response.
- EXPECT_EQ(net::ERR_INVALID_RESPONSE, client_->completion_status().error_code);
- EXPECT_FALSE(client_->has_received_response());
+ EXPECT_EQ(net::ERR_INVALID_RESPONSE, client->completion_status().error_code);
+ EXPECT_FALSE(client->has_received_response());
// The response shouldn't be stored in the storage.
EXPECT_FALSE(VerifyStoredResponse(kScriptURL));
+ // No sample should be recorded since a write didn't occur.
+ histogram_tester.ExpectTotalCount(kHistogramWriteResponseResult, 0);
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Error_Redirect) {
+ base::HistogramTester histogram_tester;
+
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
const GURL kScriptURL("https://example.com/redirect.js");
mock_server_->Set(
kScriptURL,
MockHTTPServer::Response(
std::string("HTTP/1.1 307 Temporary Redirect\n\n"), std::string()));
SetUpRegistration(kScriptURL);
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
// The request should be failed because of the redirected response.
- EXPECT_EQ(net::ERR_UNSAFE_REDIRECT, client_->completion_status().error_code);
- EXPECT_FALSE(client_->has_received_response());
+ EXPECT_EQ(net::ERR_UNSAFE_REDIRECT, client->completion_status().error_code);
+ EXPECT_FALSE(client->has_received_response());
// The response shouldn't be stored in the storage.
EXPECT_FALSE(VerifyStoredResponse(kScriptURL));
+ // No sample should be recorded since a write didn't occur.
+ histogram_tester.ExpectTotalCount(kHistogramWriteResponseResult, 0);
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Error_CertificateError) {
+ base::HistogramTester histogram_tester;
+
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
// Serve a response with a certificate error.
const GURL kScriptURL("https://example.com/certificate-error.js");
MockHTTPServer::Response response(std::string("HTTP/1.1 200 OK\n\n"),
@@ -406,58 +459,76 @@ TEST_F(ServiceWorkerNewScriptLoaderTest, Error_CertificateError) {
response.has_certificate_error = true;
mock_server_->Set(kScriptURL, response);
SetUpRegistration(kScriptURL);
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
// The request should be failed because of the response with the certificate
// error.
- EXPECT_EQ(net::ERR_CERT_DATE_INVALID,
- client_->completion_status().error_code);
- EXPECT_FALSE(client_->has_received_response());
+ EXPECT_EQ(net::ERR_CERT_DATE_INVALID, client->completion_status().error_code);
+ EXPECT_FALSE(client->has_received_response());
// The response shouldn't be stored in the storage.
EXPECT_FALSE(VerifyStoredResponse(kScriptURL));
+ // No sample should be recorded since a write didn't occur.
+ histogram_tester.ExpectTotalCount(kHistogramWriteResponseResult, 0);
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Error_NoMimeType) {
+ base::HistogramTester histogram_tester;
+
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
const GURL kScriptURL("https://example.com/no-mime-type.js");
mock_server_->Set(kScriptURL, MockHTTPServer::Response(
std::string("HTTP/1.1 200 OK\n\n"),
std::string("body with no MIME type")));
SetUpRegistration(kScriptURL);
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
// The request should be failed because of the response with no MIME type.
- EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
- client_->completion_status().error_code);
- EXPECT_FALSE(client_->has_received_response());
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE, client->completion_status().error_code);
+ EXPECT_FALSE(client->has_received_response());
// The response shouldn't be stored in the storage.
EXPECT_FALSE(VerifyStoredResponse(kScriptURL));
+ // No sample should be recorded since a write didn't occur.
+ histogram_tester.ExpectTotalCount(kHistogramWriteResponseResult, 0);
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Error_BadMimeType) {
+ base::HistogramTester histogram_tester;
+
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
const GURL kScriptURL("https://example.com/bad-mime-type.js");
mock_server_->Set(kScriptURL, MockHTTPServer::Response(
std::string("HTTP/1.1 200 OK\n"
"Content-Type: text/css\n\n"),
std::string("body with bad MIME type")));
SetUpRegistration(kScriptURL);
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
// The request should be failed because of the response with the bad MIME
// type.
- EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
- client_->completion_status().error_code);
- EXPECT_FALSE(client_->has_received_response());
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE, client->completion_status().error_code);
+ EXPECT_FALSE(client->has_received_response());
// The response shouldn't be stored in the storage.
EXPECT_FALSE(VerifyStoredResponse(kScriptURL));
+ // No sample should be recorded since a write didn't occur.
+ histogram_tester.ExpectTotalCount(kHistogramWriteResponseResult, 0);
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Success_PathRestriction) {
+ base::HistogramTester histogram_tester;
+
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
// |kScope| is not under the default scope ("/out-of-scope/"), but the
// Service-Worker-Allowed header allows it.
const GURL kScriptURL("https://example.com/out-of-scope/normal.js");
@@ -467,25 +538,34 @@ TEST_F(ServiceWorkerNewScriptLoaderTest, Success_PathRestriction) {
std::string("HTTP/1.1 200 OK\n"
"Content-Type: text/javascript\n"
"Service-Worker-Allowed: /in-scope/\n\n"),
- std::string()));
- SetUpRegistration(kScriptURL, kScope);
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
- EXPECT_EQ(net::OK, client_->completion_status().error_code);
+ std::string("٩( ’ω’ )و I'm body!")));
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = kScope;
+ SetUpRegistrationWithOptions(kScriptURL, options);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
// The client should have received the response.
- EXPECT_TRUE(client_->has_received_response());
- EXPECT_TRUE(client_->response_body().is_valid());
+ EXPECT_TRUE(client->has_received_response());
+ EXPECT_TRUE(client->response_body().is_valid());
std::string response;
EXPECT_TRUE(
- mojo::BlockingCopyToString(client_->response_body_release(), &response));
+ mojo::BlockingCopyToString(client->response_body_release(), &response));
EXPECT_EQ(mock_server_->Get(kScriptURL).body, response);
// The response should also be stored in the storage.
EXPECT_TRUE(VerifyStoredResponse(kScriptURL));
+ histogram_tester.ExpectUniqueSample(kHistogramWriteResponseResult,
+ ServiceWorkerMetrics::WRITE_OK, 1);
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Error_PathRestriction) {
+ base::HistogramTester histogram_tester;
+
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
// |kScope| is not under the default scope ("/out-of-scope/") and the
// Service-Worker-Allowed header is not specified.
const GURL kScriptURL("https://example.com/out-of-scope/normal.js");
@@ -495,43 +575,59 @@ TEST_F(ServiceWorkerNewScriptLoaderTest, Error_PathRestriction) {
MockHTTPServer::Response(std::string("HTTP/1.1 200 OK\n"
"Content-Type: text/javascript\n\n"),
std::string()));
- SetUpRegistration(kScriptURL, kScope);
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = kScope;
+ SetUpRegistrationWithOptions(kScriptURL, options);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
// The request should be failed because the scope is not allowed.
- EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
- client_->completion_status().error_code);
- EXPECT_FALSE(client_->has_received_response());
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE, client->completion_status().error_code);
+ EXPECT_FALSE(client->has_received_response());
// The response shouldn't be stored in the storage.
EXPECT_FALSE(VerifyStoredResponse(kScriptURL));
+ // No sample should be recorded since a write didn't occur.
+ histogram_tester.ExpectTotalCount(kHistogramWriteResponseResult, 0);
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Error_RedundantWorker) {
+ base::HistogramTester histogram_tester;
+
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
const GURL kScriptURL(kNormalScriptURL);
SetUpRegistration(kScriptURL);
- DoRequest(kScriptURL);
+ DoRequest(kScriptURL, &client, &loader);
// Make the service worker redundant.
version_->Doom();
ASSERT_TRUE(version_->is_redundant());
- client_->RunUntilComplete();
+ client->RunUntilComplete();
// The request should be aborted.
- EXPECT_EQ(net::ERR_FAILED, client_->completion_status().error_code);
- EXPECT_FALSE(client_->has_received_response());
+ EXPECT_EQ(net::ERR_FAILED, client->completion_status().error_code);
+ EXPECT_FALSE(client->has_received_response());
// The response shouldn't be stored in the storage.
EXPECT_FALSE(VerifyStoredResponse(kScriptURL));
+ // No sample should be recorded since a write didn't occur.
+ histogram_tester.ExpectTotalCount(kHistogramWriteResponseResult, 0);
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Update) {
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
// Set up a registration with an incumbent.
const GURL kScriptURL(kNormalScriptURL);
SetUpRegistration(kScriptURL);
- SetUpActivatedWorker(kScriptURL);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
+ ActivateVersion();
// Change the script on the server.
mock_server_->Set(
@@ -541,26 +637,268 @@ TEST_F(ServiceWorkerNewScriptLoaderTest, Update) {
std::string("this is the updated body")));
// Attempt to update.
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
- EXPECT_EQ(net::OK, client_->completion_status().error_code);
+ SetUpVersion(kScriptURL);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
// |version_| should have installed.
EXPECT_EQ(1UL, version_->script_cache_map()->size());
}
TEST_F(ServiceWorkerNewScriptLoaderTest, Update_IdenticalScript) {
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
// Set up a registration with an incumbent.
const GURL kScriptURL(kNormalScriptURL);
SetUpRegistration(kScriptURL);
- SetUpActivatedWorker(kScriptURL);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
+ ActivateVersion();
// Attempt to update.
- DoRequest(kScriptURL);
- client_->RunUntilComplete();
- EXPECT_EQ(net::OK, client_->completion_status().error_code);
+ SetUpVersion(kScriptURL);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
// The byte-to-byte check should detect the identical script, so the
// |version_| should not have installed.
EXPECT_EQ(0UL, version_->script_cache_map()->size());
}
+// Tests cache bypassing behavior when updateViaCache is 'all'.
+TEST_F(ServiceWorkerNewScriptLoaderTest, UpdateViaCache_All) {
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+ const GURL kScriptURL(kNormalScriptURL);
+ const GURL kImportedScriptURL(kNormalImportedScriptURL);
+
+ // Set up a registration.
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = kScriptURL.GetWithoutFilename();
+ options.update_via_cache = blink::mojom::ServiceWorkerUpdateViaCache::kAll;
+ SetUpRegistrationWithOptions(kScriptURL, options);
+
+ // Install the main script and imported script. The cache should be bypassed
+ // since last update time is null.
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ network::ResourceRequest request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ DoRequest(kImportedScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ // Promote to active and prepare to update.
+ ActivateVersion();
+ registration_->set_last_update_check(base::Time::Now());
+
+ // Attempt to update. The requests should not bypass cache since the last
+ // update was recent.
+ SetUpVersion(kScriptURL);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_FALSE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ DoRequest(kImportedScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_FALSE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ // Set update check to far in the past and repeat. The requests should bypass
+ // cache.
+ registration_->set_last_update_check(base::Time::Now() -
+ base::TimeDelta::FromHours(24));
+
+ SetUpVersion(kScriptURL);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ DoRequest(kImportedScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+}
+
+// Tests cache bypassing behavior when updateViaCache is 'imports'.
+TEST_F(ServiceWorkerNewScriptLoaderTest, UpdateViaCache_Imports) {
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+ const GURL kScriptURL(kNormalScriptURL);
+ const GURL kImportedScriptURL(kNormalImportedScriptURL);
+
+ // Set up a registration.
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = kScriptURL.GetWithoutFilename();
+ options.update_via_cache =
+ blink::mojom::ServiceWorkerUpdateViaCache::kImports;
+ SetUpRegistrationWithOptions(kScriptURL, options);
+
+ // Install the main script and imported script. The cache should be bypassed
+ // since last update time is null.
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ network::ResourceRequest request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ DoRequest(kImportedScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ // Promote to active and prepare to update.
+ ActivateVersion();
+ registration_->set_last_update_check(base::Time::Now());
+
+ // Attempt to update. Only the imported script should bypass cache because
+ // kImports.
+ SetUpVersion(kScriptURL);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ DoRequest(kImportedScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_FALSE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ // Set the time to far in the past and repeat. The requests should bypass
+ // cache.
+ registration_->set_last_update_check(base::Time::Now() -
+ base::TimeDelta::FromHours(24));
+
+ SetUpVersion(kScriptURL);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ DoRequest(kImportedScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+}
+
+// Tests cache bypassing behavior when updateViaCache is 'none'.
+TEST_F(ServiceWorkerNewScriptLoaderTest, UpdateViaCache_None) {
+ const GURL kScriptURL(kNormalScriptURL);
+ const GURL kImportedScriptURL(kNormalImportedScriptURL);
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
+ // Set up a registration.
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = kScriptURL.GetWithoutFilename();
+ options.update_via_cache = blink::mojom::ServiceWorkerUpdateViaCache::kNone;
+ SetUpRegistrationWithOptions(kScriptURL, options);
+
+ // Install the main script and imported script. The cache should be bypassed
+ // since kNone (and the last update time is null anyway).
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ network::ResourceRequest request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ DoRequest(kImportedScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ // Promote to active and prepare to update.
+ ActivateVersion();
+ registration_->set_last_update_check(base::Time::Now());
+
+ // Attempt to update. The requests should bypass cache because KNone.
+ SetUpVersion(kScriptURL);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ DoRequest(kImportedScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+}
+
+// Tests respecting ServiceWorkerVersion's |force_bypass_cache_for_scripts|
+// flag.
+TEST_F(ServiceWorkerNewScriptLoaderTest, ForceBypassCache) {
+ const GURL kScriptURL(kNormalScriptURL);
+ const GURL kImportedScriptURL(kNormalImportedScriptURL);
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
+ // Set up a registration.
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = kScriptURL.GetWithoutFilename();
+ // Use kAll to contradict |force_bypass_cache_for_scripts|. The force flag
+ // should win.
+ options.update_via_cache = blink::mojom::ServiceWorkerUpdateViaCache::kAll;
+ SetUpRegistrationWithOptions(kScriptURL, options);
+ // Also set last_update_time to a recent time, so the 24 hour bypass doesn't
+ // kick in.
+ registration_->set_last_update_check(base::Time::Now());
+
+ version_->set_force_bypass_cache_for_scripts(true);
+
+ // Install the main script and imported script. The cache should be bypassed.
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ network::ResourceRequest request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+
+ DoRequest(kImportedScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ request = mock_url_loader_factory_->last_request();
+ EXPECT_TRUE(request.load_flags & net::LOAD_BYPASS_CACHE);
+}
+
+// Tests that EmbeddedWorkerInstance's |network_accessed_for_script_| flag is
+// set when the script loader accesses network. This flag is used to enforce the
+// 24 hour cache bypass.
+TEST_F(ServiceWorkerNewScriptLoaderTest, AccessedNetwork) {
+ const GURL kScriptURL(kNormalScriptURL);
+ const GURL kImportedScriptURL(kNormalImportedScriptURL);
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
+
+ SetUpRegistration(kScriptURL);
+
+ // Install the main script. The network accessed flag should be flipped on.
+ version_->embedded_worker()->network_accessed_for_script_ = false;
+ mock_url_loader_factory_->set_to_access_network(true);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
+ EXPECT_TRUE(version_->embedded_worker()->network_accessed_for_script());
+
+ // Install the imported script. The network accessed flag should be unchanged,
+ // as it's only meant for main scripts.
+ version_->embedded_worker()->network_accessed_for_script_ = false;
+ mock_url_loader_factory_->set_to_access_network(true);
+ DoRequest(kImportedScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
+ EXPECT_FALSE(version_->embedded_worker()->network_accessed_for_script());
+
+ // Install a new main script, this time simulating coming from cache. The
+ // network accessed flag should be off.
+ SetUpRegistration(kScriptURL);
+ version_->embedded_worker()->network_accessed_for_script_ = false;
+ mock_url_loader_factory_->set_to_access_network(false);
+ DoRequest(kScriptURL, &client, &loader);
+ client->RunUntilComplete();
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
+ EXPECT_FALSE(version_->embedded_worker()->network_accessed_for_script());
+}
+
+} // namespace service_worker_new_script_loader_unittest
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_handle.cc b/chromium/content/browser/service_worker/service_worker_object_host.cc
index 777cea9149d..49b037866c3 100644
--- a/chromium/content/browser/service_worker/service_worker_handle.cc
+++ b/chromium/content/browser/service_worker/service_worker_object_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/service_worker/service_worker_handle.h"
+#include "content/browser/service_worker/service_worker_object_host.h"
#include "content/browser/service_worker/service_worker_client_utils.h"
#include "content/browser/service_worker/service_worker_context_core.h"
@@ -18,7 +18,7 @@ namespace content {
namespace {
-using StatusCallback = base::OnceCallback<void(ServiceWorkerStatusCode)>;
+using StatusCallback = base::OnceCallback<void(blink::ServiceWorkerStatusCode)>;
using SetExtendableMessageEventSourceCallback =
base::OnceCallback<bool(mojom::ExtendableMessageEventPtr*)>;
@@ -29,8 +29,8 @@ void DispatchExtendableMessageEventAfterStartWorker(
const base::Optional<base::TimeDelta>& timeout,
StatusCallback callback,
SetExtendableMessageEventSourceCallback set_source_callback,
- ServiceWorkerStatusCode start_worker_status) {
- if (start_worker_status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode start_worker_status) {
+ if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(start_worker_status);
return;
}
@@ -39,7 +39,7 @@ void DispatchExtendableMessageEventAfterStartWorker(
event->message = std::move(message);
event->source_origin = source_origin;
if (!std::move(set_source_callback).Run(&event)) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_FAILED);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorFailed);
return;
}
@@ -52,7 +52,7 @@ void DispatchExtendableMessageEventAfterStartWorker(
request_id = worker->StartRequest(ServiceWorkerMetrics::EventType::MESSAGE,
std::move(callback));
}
- worker->event_dispatcher()->DispatchExtendableMessageEvent(
+ worker->endpoint()->DispatchExtendableMessageEvent(
std::move(event), worker->CreateSimpleEventCallback(request_id));
}
@@ -66,7 +66,7 @@ void StartWorkerToDispatchExtendableMessageEvent(
// If not enough time is left to actually process the event don't even
// bother starting the worker and sending the event.
if (timeout && *timeout < base::TimeDelta::FromMilliseconds(100)) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_TIMEOUT);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorTimeout);
return;
}
@@ -89,7 +89,7 @@ bool SetSourceClientInfo(
}
// The output |event| must be sent over Mojo immediately after this function
-// returns. See ServiceWorkerHandle::CreateCompleteObjectInfoToSend() for
+// returns. See ServiceWorkerObjectHost::CreateCompleteObjectInfoToSend() for
// details.
bool SetSourceServiceWorkerInfo(scoped_refptr<ServiceWorkerVersion> worker,
base::WeakPtr<ServiceWorkerProviderHost>
@@ -103,14 +103,14 @@ bool SetSourceServiceWorkerInfo(scoped_refptr<ServiceWorkerVersion> worker,
DCHECK_EQ(blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
source_service_worker_provider_host->provider_type());
blink::mojom::ServiceWorkerObjectInfoPtr source_worker_info;
- base::WeakPtr<ServiceWorkerHandle> service_worker_handle =
- worker->provider_host()->GetOrCreateServiceWorkerHandle(
+ base::WeakPtr<ServiceWorkerObjectHost> service_worker_object_host =
+ worker->provider_host()->GetOrCreateServiceWorkerObjectHost(
source_service_worker_provider_host->running_hosted_version());
- if (service_worker_handle) {
+ if (service_worker_object_host) {
// CreateCompleteObjectInfoToSend() is safe because |source_worker_info|
// will be sent immediately by the caller of this function.
source_worker_info =
- service_worker_handle->CreateCompleteObjectInfoToSend();
+ service_worker_object_host->CreateCompleteObjectInfoToSend();
}
(*event)->source_info_for_service_worker = std::move(source_worker_info);
@@ -129,7 +129,7 @@ void DispatchExtendableMessageEventFromClient(
// |source_client_info| may be null if a client sent the message but its
// info could not be retrieved.
if (!source_client_info) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_FAILED);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorFailed);
return;
}
@@ -148,7 +148,7 @@ void DispatchExtendableMessageEventFromServiceWorker(
base::WeakPtr<ServiceWorkerProviderHost>
source_service_worker_provider_host) {
if (!source_service_worker_provider_host) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_FAILED);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorFailed);
return;
}
@@ -162,34 +162,30 @@ void DispatchExtendableMessageEventFromServiceWorker(
} // namespace
-ServiceWorkerHandle::ServiceWorkerHandle(
+ServiceWorkerObjectHost::ServiceWorkerObjectHost(
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerProviderHost* provider_host,
scoped_refptr<ServiceWorkerVersion> version)
: context_(context),
provider_host_(provider_host),
provider_origin_(url::Origin::Create(provider_host->document_url())),
- provider_id_(provider_host->provider_id()),
version_(std::move(version)),
weak_ptr_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(context_ && provider_host_ && version_);
DCHECK(context_->GetLiveRegistration(version_->registration_id()));
- version_->AddListener(this);
+ version_->AddObserver(this);
bindings_.set_connection_error_handler(base::BindRepeating(
- &ServiceWorkerHandle::OnConnectionError, base::Unretained(this)));
+ &ServiceWorkerObjectHost::OnConnectionError, base::Unretained(this)));
}
-ServiceWorkerHandle::~ServiceWorkerHandle() {
- // TODO(crbug.com/838410): These CHECKs are temporary debugging for the linked
- // bug.
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- CHECK(!in_dtor_);
- in_dtor_ = true;
-
- version_->RemoveListener(this);
+ServiceWorkerObjectHost::~ServiceWorkerObjectHost() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ version_->RemoveObserver(this);
}
-void ServiceWorkerHandle::OnVersionStateChanged(ServiceWorkerVersion* version) {
+void ServiceWorkerObjectHost::OnVersionStateChanged(
+ ServiceWorkerVersion* version) {
DCHECK(version);
blink::mojom::ServiceWorkerState state =
mojo::ConvertTo<blink::mojom::ServiceWorkerState>(version->status());
@@ -200,7 +196,7 @@ void ServiceWorkerHandle::OnVersionStateChanged(ServiceWorkerVersion* version) {
}
blink::mojom::ServiceWorkerObjectInfoPtr
-ServiceWorkerHandle::CreateCompleteObjectInfoToSend() {
+ServiceWorkerObjectHost::CreateCompleteObjectInfoToSend() {
auto info = CreateIncompleteObjectInfo();
blink::mojom::ServiceWorkerObjectAssociatedPtr remote_object;
info->request = mojo::MakeRequest(&remote_object);
@@ -209,7 +205,7 @@ ServiceWorkerHandle::CreateCompleteObjectInfoToSend() {
}
blink::mojom::ServiceWorkerObjectInfoPtr
-ServiceWorkerHandle::CreateIncompleteObjectInfo() {
+ServiceWorkerObjectHost::CreateIncompleteObjectInfo() {
auto info = blink::mojom::ServiceWorkerObjectInfo::New();
info->url = version_->script_url();
info->state =
@@ -219,7 +215,7 @@ ServiceWorkerHandle::CreateIncompleteObjectInfo() {
return info;
}
-void ServiceWorkerHandle::AddRemoteObjectPtrAndUpdateState(
+void ServiceWorkerObjectHost::AddRemoteObjectPtrAndUpdateState(
blink::mojom::ServiceWorkerObjectAssociatedPtrInfo remote_object_ptr_info,
blink::mojom::ServiceWorkerState sent_state) {
DCHECK(remote_object_ptr_info.is_valid());
@@ -232,11 +228,11 @@ void ServiceWorkerHandle::AddRemoteObjectPtrAndUpdateState(
remote_objects_.AddPtr(std::move(remote_object));
}
-base::WeakPtr<ServiceWorkerHandle> ServiceWorkerHandle::AsWeakPtr() {
+base::WeakPtr<ServiceWorkerObjectHost> ServiceWorkerObjectHost::AsWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
-void ServiceWorkerHandle::PostMessageToServiceWorker(
+void ServiceWorkerObjectHost::PostMessageToServiceWorker(
::blink::TransferableMessage message) {
// When this method is called the encoded_message inside message could just
// point to the IPC message's buffer. But that buffer can become invalid
@@ -247,16 +243,16 @@ void ServiceWorkerHandle::PostMessageToServiceWorker(
DispatchExtendableMessageEvent(std::move(message), base::DoNothing());
}
-void ServiceWorkerHandle::TerminateForTesting(
+void ServiceWorkerObjectHost::TerminateForTesting(
TerminateForTestingCallback callback) {
version_->StopWorker(std::move(callback));
}
-void ServiceWorkerHandle::DispatchExtendableMessageEvent(
+void ServiceWorkerObjectHost::DispatchExtendableMessageEvent(
::blink::TransferableMessage message,
StatusCallback callback) {
if (!context_) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort);
return;
}
DCHECK_EQ(provider_origin_,
@@ -292,12 +288,12 @@ void ServiceWorkerHandle::DispatchExtendableMessageEvent(
NOTREACHED() << provider_host_->provider_type();
}
-void ServiceWorkerHandle::OnConnectionError() {
+void ServiceWorkerObjectHost::OnConnectionError() {
// If there are still bindings, |this| is still being used.
if (!bindings_.empty())
return;
// Will destroy |this|.
- provider_host_->RemoveServiceWorkerHandle(version_->version_id());
+ provider_host_->RemoveServiceWorkerObjectHost(version_->version_id());
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_handle.h b/chromium/content/browser/service_worker/service_worker_object_host.h
index 948f68283ac..0c43f3a238f 100644
--- a/chromium/content/browser/service_worker/service_worker_handle.h
+++ b/chromium/content/browser/service_worker/service_worker_object_host.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_SERVICE_WORKER_SERVICE_WORKER_HANDLE_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_HANDLE_H_
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_OBJECT_HOST_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_OBJECT_HOST_H_
#include <memory>
@@ -23,35 +23,37 @@ namespace content {
class ServiceWorkerContextCore;
class ServiceWorkerProviderHost;
-namespace service_worker_handle_unittest {
-class ServiceWorkerHandleTest;
-} // namespace service_worker_handle_unittest
+namespace service_worker_object_host_unittest {
+class ServiceWorkerObjectHostTest;
+} // namespace service_worker_object_host_unittest
// Roughly corresponds to one WebServiceWorker object in the renderer process.
//
// The WebServiceWorker object in the renderer process maintains a reference to
// |this| by owning an associated interface pointer to
-// blink::mojom::ServiceWorkerObjectHost.
+// blink::mojom::ServiceWorkerObjectHost. When all Mojo connections bound with
+// |bindings_| are disconnected, |this| will be deleted. See also comments on
+// |bindings_|.
//
// Has references to the corresponding ServiceWorkerVersion in order to ensure
// that the version is alive while this handle is around.
-class CONTENT_EXPORT ServiceWorkerHandle
+class CONTENT_EXPORT ServiceWorkerObjectHost
: public blink::mojom::ServiceWorkerObjectHost,
- public ServiceWorkerVersion::Listener {
+ public ServiceWorkerVersion::Observer {
public:
- ServiceWorkerHandle(base::WeakPtr<ServiceWorkerContextCore> context,
- ServiceWorkerProviderHost* provider_host,
- scoped_refptr<ServiceWorkerVersion> version);
- ~ServiceWorkerHandle() override;
+ ServiceWorkerObjectHost(base::WeakPtr<ServiceWorkerContextCore> context,
+ ServiceWorkerProviderHost* provider_host,
+ scoped_refptr<ServiceWorkerVersion> version);
+ ~ServiceWorkerObjectHost() override;
- // ServiceWorkerVersion::Listener overrides.
+ // ServiceWorkerVersion::Observer overrides.
void OnVersionStateChanged(ServiceWorkerVersion* version) override;
- // Returns an info for the ServiceWorker object of this handle. The info
- // contains a Mojo ptr to |this| which ensures |this| stays alive while the
- // info is alive. Furthermore, it contains a Mojo request for the
- // ServiceWorkerObject interface in the renderer. |this| will make calls to
- // the ServiceWorkerObject to update its state.
+ // Returns an info for the ServiceWorker object. The info contains a Mojo
+ // ptr to |this| which ensures |this| stays alive while the info is alive.
+ // Furthermore, it contains a Mojo request for the ServiceWorkerObject
+ // interface in the renderer. |this| will make calls to the
+ // ServiceWorkerObject to update its state.
//
// WARNING: The returned info must be sent immediately over Mojo, because
// |this| will start making calls on an associated interface ptr to
@@ -76,13 +78,12 @@ class CONTENT_EXPORT ServiceWorkerHandle
blink::mojom::ServiceWorkerObjectAssociatedPtrInfo remote_object_ptr_info,
blink::mojom::ServiceWorkerState sent_state);
- int provider_id() const { return provider_id_; }
ServiceWorkerVersion* version() { return version_.get(); }
- base::WeakPtr<ServiceWorkerHandle> AsWeakPtr();
+ base::WeakPtr<ServiceWorkerObjectHost> AsWeakPtr();
private:
- friend class service_worker_handle_unittest::ServiceWorkerHandleTest;
+ friend class service_worker_object_host_unittest::ServiceWorkerObjectHostTest;
// Implements blink::mojom::ServiceWorkerObjectHost.
void PostMessageToServiceWorker(
@@ -94,40 +95,36 @@ class CONTENT_EXPORT ServiceWorkerHandle
// observe the dispatch result in unit tests.
void DispatchExtendableMessageEvent(
::blink::TransferableMessage message,
- base::OnceCallback<void(ServiceWorkerStatusCode)> callback);
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)> callback);
void OnConnectionError();
base::WeakPtr<ServiceWorkerContextCore> context_;
// |provider_host_| is valid throughout lifetime of |this| because it owns
// |this|.
- ServiceWorkerProviderHost* provider_host_;
+ ServiceWorkerProviderHost* const provider_host_;
// The origin of the |provider_host_|. Note that this is const because once a
// JavaScript ServiceWorker object is created for an execution context, we
// don't expect that context to change origins and still hold on to the
// object.
const url::Origin provider_origin_;
- const int provider_id_;
scoped_refptr<ServiceWorkerVersion> version_;
+ // Typically both |bindings_| and |remote_objects_| contain only one Mojo
+ // connection, corresponding to the content::WebServiceWorkerImpl in the
+ // renderer which corresponds to the ServiceWorker JavaScript object. However,
+ // multiple Mojo connections may exist while propagating multiple service
+ // worker object infos to the renderer process, but only the first one that
+ // arrived there will be used to create the new content::WebServiceWorkerImpl
+ // instance and be bound to it.
mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerObjectHost> bindings_;
- // Typically |remote_objects_| contains only one Mojo connection,
- // corresponding to the content::WebServiceWorkerImpl in the renderer which
- // corresponds to the ServiceWorker JavaScript object. However, multiple Mojo
- // connections may exist while propagating multiple service worker object
- // infos to the renderer process, but only the first one that arrived there
- // will be used to create the new content::WebServiceWorkerImpl instance and
- // be bound to it.
mojo::AssociatedInterfacePtrSet<blink::mojom::ServiceWorkerObject>
remote_objects_;
- // TODO(crbug.com/838410): Temporary debugging for the linked bug.
- bool in_dtor_ = false;
+ base::WeakPtrFactory<ServiceWorkerObjectHost> weak_ptr_factory_;
- base::WeakPtrFactory<ServiceWorkerHandle> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceWorkerHandle);
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerObjectHost);
};
} // namespace content
-#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_HANDLE_H_
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_OBJECT_HOST_H_
diff --git a/chromium/content/browser/service_worker/service_worker_handle_unittest.cc b/chromium/content/browser/service_worker/service_worker_object_host_unittest.cc
index 6122d08b40c..fd1ca22f735 100644
--- a/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_object_host_unittest.cc
@@ -12,7 +12,7 @@
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
-#include "content/browser/service_worker/service_worker_handle.h"
+#include "content/browser/service_worker/service_worker_object_host.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
@@ -28,11 +28,11 @@
#include "third_party/blink/public/mojom/service_worker/service_worker_state.mojom.h"
namespace content {
-namespace service_worker_handle_unittest {
+namespace service_worker_object_host_unittest {
static void SaveStatusCallback(bool* called,
- ServiceWorkerStatusCode* out,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode* out,
+ blink::ServiceWorkerStatusCode status) {
*called = true;
*out = status;
}
@@ -52,8 +52,8 @@ class ExtendableMessageEventTestHelper : public EmbeddedWorkerTestHelper {
void OnExtendableMessageEvent(
mojom::ExtendableMessageEventPtr event,
- mojom::ServiceWorkerEventDispatcher::
- DispatchExtendableMessageEventCallback callback) override {
+ mojom::ServiceWorker::DispatchExtendableMessageEventCallback callback)
+ override {
events_.push_back(std::move(event));
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
base::Time::Now());
@@ -77,7 +77,7 @@ class FailToStartWorkerTestHelper : public ExtendableMessageEventTestHelper {
const GURL& scope,
const GURL& script_url,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -112,19 +112,13 @@ class MockServiceWorkerObject : public blink::mojom::ServiceWorkerObject {
mojo::AssociatedBinding<blink::mojom::ServiceWorkerObject> binding_;
};
-class ServiceWorkerHandleTest : public testing::Test {
+class ServiceWorkerObjectHostTest : public testing::Test {
public:
- ServiceWorkerHandleTest()
+ ServiceWorkerObjectHostTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
void Initialize(std::unique_ptr<EmbeddedWorkerTestHelper> helper) {
helper_ = std::move(helper);
-
- dispatcher_host_ = base::MakeRefCounted<ServiceWorkerDispatcherHost>(
- helper_->mock_render_process_id());
- helper_->RegisterDispatcherHost(helper_->mock_render_process_id(),
- dispatcher_host_);
- dispatcher_host_->Init(helper_->context_wrapper());
}
void SetUpRegistration(const GURL& scope, const GURL& script_url) {
@@ -150,39 +144,37 @@ class ServiceWorkerHandleTest : public testing::Test {
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
// Make the registration findable via storage functions.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
helper_->context()->storage()->StoreRegistration(
- registration_.get(),
- version_.get(),
+ registration_.get(), version_.get(),
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(SERVICE_WORKER_OK, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
}
void TearDown() override {
- dispatcher_host_ = nullptr;
registration_ = nullptr;
version_ = nullptr;
helper_.reset();
}
void CallDispatchExtendableMessageEvent(
- ServiceWorkerHandle* handle,
+ ServiceWorkerObjectHost* object_host,
::blink::TransferableMessage message,
- base::OnceCallback<void(ServiceWorkerStatusCode)> callback) {
- handle->DispatchExtendableMessageEvent(std::move(message),
- std::move(callback));
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)> callback) {
+ object_host->DispatchExtendableMessageEvent(std::move(message),
+ std::move(callback));
}
- size_t GetBindingsCount(ServiceWorkerHandle* handle) {
- return handle->bindings_.size();
+ size_t GetBindingsCount(ServiceWorkerObjectHost* object_host) {
+ return object_host->bindings_.size();
}
- ServiceWorkerHandle* GetServiceWorkerHandle(
+ ServiceWorkerObjectHost* GetServiceWorkerObjectHost(
ServiceWorkerProviderHost* provider_host,
int64_t version_id) {
- auto iter = provider_host->handles_.find(version_id);
- if (iter != provider_host->handles_.end())
+ auto iter = provider_host->service_worker_object_hosts_.find(version_id);
+ if (iter != provider_host->service_worker_object_hosts_.end())
return iter->second.get();
return nullptr;
}
@@ -213,20 +205,16 @@ class ServiceWorkerHandleTest : public testing::Test {
}
TestBrowserThreadBundle browser_thread_bundle_;
-
- base::SimpleTestTickClock tick_clock_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
- scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host_;
private:
- DISALLOW_COPY_AND_ASSIGN(ServiceWorkerHandleTest);
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerObjectHostTest);
};
-TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
+TEST_F(ServiceWorkerObjectHostTest, OnVersionStateChanged) {
const int64_t kProviderId = 99;
- const int kRenderFrameId = 44;
const GURL pattern("https://www.example.com/");
const GURL script_url("https://www.example.com/service_worker.js");
Initialize(std::make_unique<EmbeddedWorkerTestHelper>(base::FilePath()));
@@ -235,10 +223,10 @@ TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
std::unique_ptr<ServiceWorkerProviderHost> provider_host =
- CreateProviderHostWithDispatcherHost(
+ CreateProviderHostForWindow(
helper_->mock_render_process_id(), kProviderId,
- helper_->context()->AsWeakPtr(), kRenderFrameId,
- dispatcher_host_.get(), &remote_endpoint);
+ true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr(),
+ &remote_endpoint);
provider_host->SetDocumentUrl(pattern);
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info =
GetRegistrationFromRemote(remote_endpoint.host_ptr()->get(), pattern);
@@ -256,62 +244,65 @@ TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
EXPECT_EQ(blink::mojom::ServiceWorkerState::kInstalled, mock_object->state());
}
-TEST_F(ServiceWorkerHandleTest,
+TEST_F(ServiceWorkerObjectHostTest,
DispatchExtendableMessageEvent_FromServiceWorker) {
const GURL pattern("https://www.example.com/");
const GURL script_url("https://www.example.com/service_worker.js");
Initialize(std::make_unique<ExtendableMessageEventTestHelper>());
SetUpRegistration(pattern, script_url);
+ base::SimpleTestTickClock tick_clock;
// Set mock clock on version_ to check timeout behavior.
- tick_clock_.SetNowTicks(base::TimeTicks::Now());
- version_->SetTickClockForTesting(&tick_clock_);
+ tick_clock.SetNowTicks(base::TimeTicks::Now());
+ version_->SetTickClockForTesting(&tick_clock);
// Make sure worker has a non-zero timeout.
bool called = false;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
base::BindOnce(&SaveStatusCallback, &called, &status));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
version_->StartRequestWithCustomTimeout(
ServiceWorkerMetrics::EventType::ACTIVATE, base::DoNothing(),
base::TimeDelta::FromSeconds(10), ServiceWorkerVersion::KILL_ON_TIMEOUT);
// Advance clock by a couple seconds.
- tick_clock_.Advance(base::TimeDelta::FromSeconds(4));
+ tick_clock.Advance(base::TimeDelta::FromSeconds(4));
base::TimeDelta remaining_time = version_->remaining_timeout();
EXPECT_EQ(base::TimeDelta::FromSeconds(6), remaining_time);
- // Prepare a ServiceWorkerHandle corresponding to a JavaScript ServiceWorker
- // object in the service worker execution context for |version_|.
+ // Prepare a ServiceWorkerObjectHost corresponding to a JavaScript
+ // ServiceWorker object in the service worker execution context for
+ // |version_|.
ServiceWorkerProviderHost* provider_host = version_->provider_host();
blink::mojom::ServiceWorkerObjectInfoPtr info =
- provider_host->GetOrCreateServiceWorkerHandle(version_.get())
+ provider_host->GetOrCreateServiceWorkerObjectHost(version_)
->CreateCompleteObjectInfoToSend();
- ServiceWorkerHandle* sender_worker_handle =
- GetServiceWorkerHandle(provider_host, version_->version_id());
- EXPECT_EQ(1u, GetBindingsCount(sender_worker_handle));
+ ServiceWorkerObjectHost* sender_worker_object_host =
+ GetServiceWorkerObjectHost(provider_host, version_->version_id());
+ EXPECT_EQ(1u, GetBindingsCount(sender_worker_object_host));
// Dispatch an ExtendableMessageEvent simulating calling
// ServiceWorker#postMessage() on the ServiceWorker object corresponding to
- // |service_worker_handle|.
+ // |service_worker_object_host|.
blink::TransferableMessage message;
SetUpDummyMessagePort(&message.ports);
called = false;
- status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ status = blink::ServiceWorkerStatusCode::kErrorFailed;
CallDispatchExtendableMessageEvent(
- sender_worker_handle, std::move(message),
+ sender_worker_object_host, std::move(message),
base::BindOnce(&SaveStatusCallback, &called, &status));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
// The dispatched ExtendableMessageEvent should be kept in
// ExtendableMessageEventTestHelper, and the source service worker object info
// should correspond to the pair (|version_->provider_host()|, |version_|),
- // means it should correspond to |sender_worker_handle|.
- EXPECT_EQ(2u, GetBindingsCount(sender_worker_handle));
+ // means it should correspond to |sender_worker_object_host|.
+ EXPECT_EQ(2u, GetBindingsCount(sender_worker_object_host));
const std::vector<mojom::ExtendableMessageEventPtr>& events =
static_cast<ExtendableMessageEventTestHelper*>(helper_.get())->events();
EXPECT_EQ(1u, events.size());
@@ -322,9 +313,13 @@ TEST_F(ServiceWorkerHandleTest,
// Timeout of message event should not have extended life of service worker.
EXPECT_EQ(remaining_time, version_->remaining_timeout());
+ // Clean up.
+ base::RunLoop stop_loop;
+ version_->StopWorker(stop_loop.QuitClosure());
+ stop_loop.Run();
}
-TEST_F(ServiceWorkerHandleTest, DispatchExtendableMessageEvent_FromClient) {
+TEST_F(ServiceWorkerObjectHostTest, DispatchExtendableMessageEvent_FromClient) {
const int64_t kProviderId = 99;
const GURL pattern("https://www.example.com/");
const GURL script_url("https://www.example.com/service_worker.js");
@@ -339,33 +334,32 @@ TEST_F(ServiceWorkerHandleTest, DispatchExtendableMessageEvent_FromClient) {
WebContentsTester::CreateTestWebContents(helper_->browser_context(),
nullptr));
RenderFrameHost* frame_host = web_contents->GetMainFrame();
- ServiceWorkerProviderHostInfo provider_host_info(
- kProviderId, frame_host->GetRoutingID(),
- blink::mojom::ServiceWorkerProviderType::kForWindow,
- true /* is_parent_frame_secure */);
+ mojom::ServiceWorkerProviderHostInfoPtr provider_host_info =
+ CreateProviderHostInfoForWindow(kProviderId, frame_host->GetRoutingID());
std::unique_ptr<ServiceWorkerProviderHost> provider_host =
- ServiceWorkerProviderHost::Create(
- frame_host->GetProcess()->GetID(), std::move(provider_host_info),
- helper_->context()->AsWeakPtr(), dispatcher_host_->AsWeakPtr());
+ ServiceWorkerProviderHost::Create(frame_host->GetProcess()->GetID(),
+ std::move(provider_host_info),
+ helper_->context()->AsWeakPtr());
provider_host->SetDocumentUrl(pattern);
- // Prepare a ServiceWorkerHandle for the above |provider_host|.
+ // Prepare a ServiceWorkerObjectHost for the above |provider_host|.
blink::mojom::ServiceWorkerObjectInfoPtr info =
- provider_host->GetOrCreateServiceWorkerHandle(version_.get())
+ provider_host->GetOrCreateServiceWorkerObjectHost(version_)
->CreateCompleteObjectInfoToSend();
- ServiceWorkerHandle* handle =
- GetServiceWorkerHandle(provider_host.get(), version_->version_id());
+ ServiceWorkerObjectHost* object_host =
+ GetServiceWorkerObjectHost(provider_host.get(), version_->version_id());
// Simulate dispatching an ExtendableMessageEvent.
blink::TransferableMessage message;
SetUpDummyMessagePort(&message.ports);
bool called = false;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
CallDispatchExtendableMessageEvent(
- handle, std::move(message),
+ object_host, std::move(message),
base::BindOnce(&SaveStatusCallback, &called, &status));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
// The dispatched ExtendableMessageEvent should be kept in
// ExtendableMessageEventTestHelper, and its source client info should
// correspond to |provider_host|.
@@ -380,7 +374,7 @@ TEST_F(ServiceWorkerHandleTest, DispatchExtendableMessageEvent_FromClient) {
events[0]->source_info_for_client->client_type);
}
-TEST_F(ServiceWorkerHandleTest, DispatchExtendableMessageEvent_Fail) {
+TEST_F(ServiceWorkerObjectHostTest, DispatchExtendableMessageEvent_Fail) {
const int64_t kProviderId = 99;
const GURL pattern("https://www.example.com/");
const GURL script_url("https://www.example.com/service_worker.js");
@@ -395,39 +389,37 @@ TEST_F(ServiceWorkerHandleTest, DispatchExtendableMessageEvent_Fail) {
WebContentsTester::CreateTestWebContents(helper_->browser_context(),
nullptr));
RenderFrameHost* frame_host = web_contents->GetMainFrame();
- ServiceWorkerProviderHostInfo provider_host_info(
- kProviderId, frame_host->GetRoutingID(),
- blink::mojom::ServiceWorkerProviderType::kForWindow,
- true /* is_parent_frame_secure */);
+ mojom::ServiceWorkerProviderHostInfoPtr provider_host_info =
+ CreateProviderHostInfoForWindow(kProviderId, frame_host->GetRoutingID());
std::unique_ptr<ServiceWorkerProviderHost> provider_host =
- ServiceWorkerProviderHost::Create(
- frame_host->GetProcess()->GetID(), std::move(provider_host_info),
- helper_->context()->AsWeakPtr(), dispatcher_host_->AsWeakPtr());
+ ServiceWorkerProviderHost::Create(frame_host->GetProcess()->GetID(),
+ std::move(provider_host_info),
+ helper_->context()->AsWeakPtr());
provider_host->SetDocumentUrl(pattern);
- // Prepare a ServiceWorkerHandle for the above |provider_host|.
+ // Prepare a ServiceWorkerObjectHost for the above |provider_host|.
blink::mojom::ServiceWorkerObjectInfoPtr info =
- provider_host->GetOrCreateServiceWorkerHandle(version_.get())
+ provider_host->GetOrCreateServiceWorkerObjectHost(version_)
->CreateCompleteObjectInfoToSend();
- ServiceWorkerHandle* handle =
- GetServiceWorkerHandle(provider_host.get(), version_->version_id());
+ ServiceWorkerObjectHost* object_host =
+ GetServiceWorkerObjectHost(provider_host.get(), version_->version_id());
// Try to dispatch ExtendableMessageEvent. This should fail to start the
// worker and to dispatch the event.
blink::TransferableMessage message;
SetUpDummyMessagePort(&message.ports);
bool called = false;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ blink::ServiceWorkerStatusCode status = blink::ServiceWorkerStatusCode::kOk;
CallDispatchExtendableMessageEvent(
- handle, std::move(message),
+ object_host, std::move(message),
base::BindOnce(&SaveStatusCallback, &called, &status));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed, status);
// No ExtendableMessageEvent has been dispatched.
const std::vector<mojom::ExtendableMessageEventPtr>& events =
static_cast<ExtendableMessageEventTestHelper*>(helper_.get())->events();
EXPECT_EQ(0u, events.size());
}
-} // namespace service_worker_handle_unittest
+} // namespace service_worker_object_host_unittest
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_ping_controller.cc b/chromium/content/browser/service_worker/service_worker_ping_controller.cc
new file mode 100644
index 00000000000..2f9425a57b9
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_ping_controller.cc
@@ -0,0 +1,68 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/service_worker_ping_controller.h"
+
+#include "content/browser/service_worker/service_worker_version.h"
+
+namespace content {
+
+namespace {
+// Timeout for waiting for a response to a ping.
+constexpr base::TimeDelta kPingTimeout = base::TimeDelta::FromSeconds(30);
+} // namespace
+
+ServiceWorkerPingController::ServiceWorkerPingController(
+ ServiceWorkerVersion* version)
+ : version_(version) {}
+
+ServiceWorkerPingController::~ServiceWorkerPingController() = default;
+
+void ServiceWorkerPingController::Activate() {
+ ping_state_ = PingState::kPinging;
+}
+
+void ServiceWorkerPingController::Deactivate() {
+ ClearLastPingTime();
+ ping_state_ = PingState::kNotPinging;
+}
+
+void ServiceWorkerPingController::OnPongReceived() {
+ ClearLastPingTime();
+}
+
+bool ServiceWorkerPingController::IsActivated() const {
+ return ping_state_ == PingState::kPinging;
+}
+
+bool ServiceWorkerPingController::IsTimedOut() const {
+ return ping_state_ == PingState::kPingTimedOut;
+}
+
+void ServiceWorkerPingController::CheckPingStatus() {
+ if (version_->GetTickDuration(last_ping_time_) > kPingTimeout) {
+ ping_state_ = PingState::kPingTimedOut;
+ version_->OnPingTimeout();
+ return;
+ }
+
+ // Check if we want to send a next ping.
+ if (ping_state_ != PingState::kPinging || !last_ping_time_.is_null())
+ return;
+
+ version_->PingWorker();
+ version_->RestartTick(&last_ping_time_);
+}
+
+void ServiceWorkerPingController::SimulateTimeoutForTesting() {
+ version_->PingWorker();
+ ping_state_ = PingState::kPingTimedOut;
+ version_->OnPingTimeout();
+}
+
+void ServiceWorkerPingController::ClearLastPingTime() {
+ last_ping_time_ = base::TimeTicks();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_ping_controller.h b/chromium/content/browser/service_worker/service_worker_ping_controller.h
new file mode 100644
index 00000000000..5c7d261624f
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_ping_controller.h
@@ -0,0 +1,54 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_PING_CONTROLLER_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_PING_CONTROLLER_H_
+
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class ServiceWorkerVersion;
+
+// A controller for periodically sending a ping to the worker to see if the
+// worker is not stalling or is in a busy synchronous loop (possibly abusively).
+class CONTENT_EXPORT ServiceWorkerPingController final {
+ public:
+ explicit ServiceWorkerPingController(ServiceWorkerVersion* version);
+ ~ServiceWorkerPingController();
+
+ void Activate();
+ void Deactivate();
+ void OnPongReceived();
+
+ bool IsActivated() const;
+ bool IsTimedOut() const;
+
+ // Checks ping status. This is supposed to be called periodically.
+ // This may call:
+ // - version_->OnPingTimeout() if the worker hasn't reponded within a
+ // certain period.
+ // - version_->PingWorker() if we're running ping timer and can send next
+ // ping.
+ void CheckPingStatus();
+
+ void SimulateTimeoutForTesting();
+
+ private:
+ void ClearLastPingTime();
+
+ enum class PingState { kNotPinging, kPinging, kPingTimedOut };
+ ServiceWorkerVersion* version_; // Owns |this|.
+ // The time the most recent ping was sent.
+ base::TimeTicks last_ping_time_;
+ PingState ping_state_ = PingState::kNotPinging;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPingController);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_PING_CONTROLLER_H_
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager.cc b/chromium/content/browser/service_worker/service_worker_process_manager.cc
index 79850cf30c1..403f8b6525c 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager.cc
+++ b/chromium/content/browser/service_worker/service_worker_process_manager.cc
@@ -79,7 +79,8 @@ bool ServiceWorkerProcessManager::IsShutdown() {
return !browser_context_;
}
-ServiceWorkerStatusCode ServiceWorkerProcessManager::AllocateWorkerProcess(
+blink::ServiceWorkerStatusCode
+ServiceWorkerProcessManager::AllocateWorkerProcess(
int embedded_worker_id,
const GURL& pattern,
const GURL& script_url,
@@ -97,11 +98,11 @@ ServiceWorkerStatusCode ServiceWorkerProcessManager::AllocateWorkerProcess(
out_info->process_id = result;
out_info->start_situation =
ServiceWorkerMetrics::StartSituation::EXISTING_READY_PROCESS;
- return SERVICE_WORKER_OK;
+ return blink::ServiceWorkerStatusCode::kOk;
}
if (IsShutdown()) {
- return SERVICE_WORKER_ERROR_ABORT;
+ return blink::ServiceWorkerStatusCode::kErrorAbort;
}
DCHECK(!base::ContainsKey(worker_process_map_, embedded_worker_id))
@@ -138,9 +139,9 @@ ServiceWorkerStatusCode ServiceWorkerProcessManager::AllocateWorkerProcess(
rph->InSameStoragePartition(storage_partition_));
ServiceWorkerMetrics::StartSituation start_situation;
- if (!rph->HasConnection()) {
- // HasConnection() is false means that Init() has not been called or the
- // process has been killed.
+ if (!rph->IsInitializedAndNotDead()) {
+ // IsInitializedAndNotDead() is false means that Init() has not been called
+ // or the process has been killed.
start_situation = ServiceWorkerMetrics::StartSituation::NEW_PROCESS;
} else if (!rph->IsReady()) {
start_situation =
@@ -152,7 +153,7 @@ ServiceWorkerStatusCode ServiceWorkerProcessManager::AllocateWorkerProcess(
if (!rph->Init()) {
LOG(ERROR) << "Couldn't start a new process!";
- return SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND;
+ return blink::ServiceWorkerStatusCode::kErrorProcessNotFound;
}
worker_process_map_.emplace(embedded_worker_id, std::move(site_instance));
@@ -161,7 +162,7 @@ ServiceWorkerStatusCode ServiceWorkerProcessManager::AllocateWorkerProcess(
RenderProcessHost::KeepAliveClientType::kServiceWorker);
out_info->process_id = rph->GetID();
out_info->start_situation = start_situation;
- return SERVICE_WORKER_OK;
+ return blink::ServiceWorkerStatusCode::kOk;
}
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 71f589a970c..f768781f2c9 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager.h
+++ b/chromium/content/browser/service_worker/service_worker_process_manager.h
@@ -14,7 +14,7 @@
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "content/browser/service_worker/service_worker_metrics.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
class GURL;
@@ -66,15 +66,16 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
// false, or a suitable existing process is not found, a new process may be
// created.
//
- // If SERVICE_WORKER_OK is returned, |out_info| contains information about the
- // process.
+ // If blink::ServiceWorkerStatusCode::kOk is returned,
+ // |out_info| contains information about the process.
//
// Called on the UI thread.
- ServiceWorkerStatusCode AllocateWorkerProcess(int embedded_worker_id,
- const GURL& pattern,
- const GURL& script_url,
- bool can_use_existing_process,
- AllocatedProcessInfo* out_info);
+ blink::ServiceWorkerStatusCode AllocateWorkerProcess(
+ int embedded_worker_id,
+ const GURL& pattern,
+ const GURL& script_url,
+ bool can_use_existing_process,
+ AllocatedProcessInfo* out_info);
// Drops a reference to a process that was running a Service Worker, and its
// SiteInstance. This must match a call to AllocateWorkerProcess().
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 ab6899ad6ae..edc8d043b02 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
@@ -119,12 +119,13 @@ TEST_F(ServiceWorkerProcessManagerTest,
// Allocate a process to a worker, when process reuse is authorized.
ServiceWorkerProcessManager::AllocatedProcessInfo process_info;
- ServiceWorkerStatusCode status = process_manager_->AllocateWorkerProcess(
- kEmbeddedWorkerId, pattern_, script_url_,
- true /* can_use_existing_process */, &process_info);
+ blink::ServiceWorkerStatusCode status =
+ process_manager_->AllocateWorkerProcess(
+ kEmbeddedWorkerId, pattern_, script_url_,
+ true /* can_use_existing_process */, &process_info);
// An existing process should be allocated to the worker.
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
EXPECT_EQ(host->GetID(), process_info.process_id);
EXPECT_EQ(ServiceWorkerMetrics::StartSituation::EXISTING_UNREADY_PROCESS,
process_info.start_situation);
@@ -159,12 +160,13 @@ TEST_F(ServiceWorkerProcessManagerTest,
// Allocate a process to a worker, when process reuse is disallowed.
ServiceWorkerProcessManager::AllocatedProcessInfo process_info;
- ServiceWorkerStatusCode status = process_manager_->AllocateWorkerProcess(
- kEmbeddedWorkerId, pattern_, script_url_,
- false /* can_use_existing_process */, &process_info);
+ blink::ServiceWorkerStatusCode status =
+ process_manager_->AllocateWorkerProcess(
+ kEmbeddedWorkerId, pattern_, script_url_,
+ false /* can_use_existing_process */, &process_info);
// A new process should be allocated to the worker.
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
EXPECT_NE(host->GetID(), process_info.process_id);
EXPECT_EQ(ServiceWorkerMetrics::StartSituation::NEW_PROCESS,
process_info.start_situation);
@@ -187,12 +189,13 @@ TEST_F(ServiceWorkerProcessManagerTest, AllocateWorkerProcess_InShutdown) {
ASSERT_TRUE(process_manager_->IsShutdown());
ServiceWorkerProcessManager::AllocatedProcessInfo process_info;
- ServiceWorkerStatusCode status = process_manager_->AllocateWorkerProcess(
- 1, pattern_, script_url_, true /* can_use_existing_process */,
- &process_info);
+ blink::ServiceWorkerStatusCode status =
+ process_manager_->AllocateWorkerProcess(
+ 1, pattern_, script_url_, true /* can_use_existing_process */,
+ &process_info);
// Allocating a process in shutdown should abort.
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort, status);
EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, process_info.process_id);
EXPECT_EQ(ServiceWorkerMetrics::StartSituation::UNKNOWN,
process_info.start_situation);
@@ -213,10 +216,11 @@ TEST_F(ServiceWorkerProcessManagerTest,
{
const int kEmbeddedWorkerId = 55; // dummy value
ServiceWorkerProcessManager::AllocatedProcessInfo process_info;
- ServiceWorkerStatusCode status = process_manager_->AllocateWorkerProcess(
- kEmbeddedWorkerId, pattern_, script_url_,
- true /* can_use_existing_process */, &process_info);
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ blink::ServiceWorkerStatusCode status =
+ process_manager_->AllocateWorkerProcess(
+ kEmbeddedWorkerId, pattern_, script_url_,
+ true /* can_use_existing_process */, &process_info);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
// Instead of testing the input to the CreateRenderProcessHost(), it'd be
// more interesting to check the StoragePartition of the returned process
// here and below. Alas, MockRenderProcessHosts always use the default
@@ -248,10 +252,11 @@ TEST_F(ServiceWorkerProcessManagerTest,
{
const int kEmbeddedWorkerId = 77; // dummy value
ServiceWorkerProcessManager::AllocatedProcessInfo process_info;
- ServiceWorkerStatusCode status = process_manager_->AllocateWorkerProcess(
- kEmbeddedWorkerId, pattern_, script_url_,
- true /* can_use_existing_process */, &process_info);
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ blink::ServiceWorkerStatusCode status =
+ process_manager_->AllocateWorkerProcess(
+ kEmbeddedWorkerId, pattern_, script_url_,
+ true /* can_use_existing_process */, &process_info);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
EXPECT_EQ(
kGuestSiteUrl,
render_process_host_factory_->last_site_instance_used()->GetSiteURL());
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 4208300ee9b..f3f335bde5e 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.cc
@@ -21,7 +21,6 @@
#include "content/browser/service_worker/service_worker_context_request_handler.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
-#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_registration_object_host.h"
#include "content/browser/service_worker/service_worker_script_loader_factory.h"
#include "content/browser/service_worker/service_worker_type_converters.h"
@@ -43,6 +42,7 @@
#include "services/network/public/cpp/resource_request_body.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -147,6 +147,41 @@ ServiceWorkerMetrics::EventType PurposeToEventType(
} // anonymous namespace
+// RAII helper class for keeping track of versions waiting for an update hint
+// from the renderer.
+//
+// This class is move-only.
+class ServiceWorkerProviderHost::PendingUpdateVersion {
+ public:
+ explicit PendingUpdateVersion(scoped_refptr<ServiceWorkerVersion> version)
+ : version_(std::move(version)) {
+ version_->IncrementPendingUpdateHintCount();
+ }
+
+ PendingUpdateVersion(PendingUpdateVersion&& other) {
+ version_ = std::move(other.version_);
+ }
+
+ ~PendingUpdateVersion() {
+ if (version_)
+ version_->DecrementPendingUpdateHintCount();
+ }
+
+ PendingUpdateVersion& operator=(PendingUpdateVersion&& other) {
+ version_ = std::move(other.version_);
+ return *this;
+ }
+
+ // Needed for base::flat_set.
+ bool operator<(const PendingUpdateVersion& other) const {
+ return version_ < other.version_;
+ }
+
+ private:
+ scoped_refptr<ServiceWorkerVersion> version_;
+ DISALLOW_COPY_AND_ASSIGN(PendingUpdateVersion);
+};
+
// static
base::WeakPtr<ServiceWorkerProviderHost>
ServiceWorkerProviderHost::PreCreateNavigationHost(
@@ -156,11 +191,12 @@ ServiceWorkerProviderHost::PreCreateNavigationHost(
DCHECK(context);
auto host = base::WrapUnique(new ServiceWorkerProviderHost(
ChildProcessHost::kInvalidUniqueID,
- ServiceWorkerProviderHostInfo(
+ mojom::ServiceWorkerProviderHostInfo::New(
NextBrowserProvidedProviderId(), MSG_ROUTING_NONE,
blink::mojom::ServiceWorkerProviderType::kForWindow,
- are_ancestors_secure),
- context, nullptr /* dispatcher_host */));
+ are_ancestors_secure, nullptr /* host_request */,
+ nullptr /* client_ptr_info */),
+ context));
host->web_contents_getter_ = web_contents_getter;
auto weak_ptr = host->AsWeakPtr();
@@ -169,17 +205,32 @@ ServiceWorkerProviderHost::PreCreateNavigationHost(
}
// static
-std::unique_ptr<ServiceWorkerProviderHost>
+base::WeakPtr<ServiceWorkerProviderHost>
ServiceWorkerProviderHost::PreCreateForController(
- base::WeakPtr<ServiceWorkerContextCore> context) {
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ scoped_refptr<ServiceWorkerVersion> version,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr* out_provider_info) {
auto host = base::WrapUnique(new ServiceWorkerProviderHost(
ChildProcessHost::kInvalidUniqueID,
- ServiceWorkerProviderHostInfo(
+ mojom::ServiceWorkerProviderHostInfo::New(
NextBrowserProvidedProviderId(), MSG_ROUTING_NONE,
blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
- true /* is_parent_frame_secure */),
- std::move(context), nullptr));
- return host;
+ true /* is_parent_frame_secure */, nullptr /* host_request */,
+ nullptr /* client_ptr_info */),
+ context));
+ host->running_hosted_version_ = std::move(version);
+
+ (*out_provider_info)->provider_id = host->provider_id();
+ (*out_provider_info)->client_request = mojo::MakeRequest(&host->container_);
+ host->binding_.Bind(
+ mojo::MakeRequest(&((*out_provider_info)->host_ptr_info)));
+ host->binding_.set_connection_error_handler(
+ base::BindOnce(&RemoveProviderHost, context,
+ ChildProcessHost::kInvalidUniqueID, host->provider_id()));
+
+ auto weak_ptr = host->AsWeakPtr();
+ context->AddProviderHost(std::move(host));
+ return weak_ptr;
}
// static
@@ -190,12 +241,12 @@ ServiceWorkerProviderHost::PreCreateForSharedWorker(
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr* out_provider_info) {
auto host = base::WrapUnique(new ServiceWorkerProviderHost(
ChildProcessHost::kInvalidUniqueID,
- ServiceWorkerProviderHostInfo(
+ mojom::ServiceWorkerProviderHostInfo::New(
NextBrowserProvidedProviderId(), MSG_ROUTING_NONE,
blink::mojom::ServiceWorkerProviderType::kForSharedWorker,
- true /* is_parent_frame_secure */),
- context, nullptr));
- host->dispatcher_host_ = context->GetDispatcherHost(process_id)->AsWeakPtr();
+ true /* is_parent_frame_secure */, nullptr /* host_request */,
+ nullptr /* client_ptr_info */),
+ context));
host->render_process_id_ = process_id;
(*out_provider_info)->provider_id = host->provider_id();
@@ -213,33 +264,30 @@ ServiceWorkerProviderHost::PreCreateForSharedWorker(
// static
std::unique_ptr<ServiceWorkerProviderHost> ServiceWorkerProviderHost::Create(
int process_id,
- ServiceWorkerProviderHostInfo info,
- base::WeakPtr<ServiceWorkerContextCore> context,
- base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host) {
- auto host = base::WrapUnique(new ServiceWorkerProviderHost(
- process_id, std::move(info), context, dispatcher_host));
+ mojom::ServiceWorkerProviderHostInfoPtr info,
+ base::WeakPtr<ServiceWorkerContextCore> context) {
+ auto host = base::WrapUnique(
+ new ServiceWorkerProviderHost(process_id, std::move(info), context));
host->is_execution_ready_ = true;
return host;
}
ServiceWorkerProviderHost::ServiceWorkerProviderHost(
int render_process_id,
- ServiceWorkerProviderHostInfo info,
- base::WeakPtr<ServiceWorkerContextCore> context,
- base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host)
+ mojom::ServiceWorkerProviderHostInfoPtr info,
+ base::WeakPtr<ServiceWorkerContextCore> context)
: client_uuid_(base::GenerateGUID()),
create_time_(base::TimeTicks::Now()),
render_process_id_(render_process_id),
render_thread_id_(kDocumentMainThreadId),
info_(std::move(info)),
context_(context),
- dispatcher_host_(dispatcher_host),
allow_association_(true),
binding_(this),
interface_provider_binding_(this) {
- DCHECK_NE(blink::mojom::ServiceWorkerProviderType::kUnknown, info_.type);
+ DCHECK_NE(blink::mojom::ServiceWorkerProviderType::kUnknown, info_->type);
- if (info_.type ==
+ if (info_->type ==
blink::mojom::ServiceWorkerProviderType::kForServiceWorker) {
// Actual |render_process_id| will be set after choosing a process for the
// controller, and |render_thread id| will be set when the service worker
@@ -251,23 +299,21 @@ ServiceWorkerProviderHost::ServiceWorkerProviderHost(
context_->RegisterProviderHostByClientID(client_uuid_, this);
// |client_| and |binding_| will be bound on CompleteNavigationInitialized
- // (providers created for navigation) or on
- // CompleteStartWorkerPreparation (providers for service workers).
- if (!info_.client_ptr_info.is_valid() && !info_.host_request.is_pending())
+ // (providers created for navigation) or in
+ // PreCreateForController (providers for service workers).
+ // TODO(falken): All provider types should just set the bindings here for
+ // consistency.
+ if (!info_->client_ptr_info.is_valid() && !info_->host_request.is_pending())
return;
- container_.Bind(std::move(info_.client_ptr_info));
- binding_.Bind(std::move(info_.host_request));
+ container_.Bind(std::move(info_->client_ptr_info));
+ binding_.Bind(std::move(info_->host_request));
binding_.set_connection_error_handler(base::BindOnce(
- &RemoveProviderHost, context_, render_process_id, info_.provider_id));
+ &RemoveProviderHost, context_, render_process_id, info_->provider_id));
}
ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
- // TODO(crbug.com/838410): The CHECKs are temporary debugging for the linked
- // bug.
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- CHECK(!in_dtor_);
- in_dtor_ = true;
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (context_)
context_->UnregisterProviderHostByClientID(client_uuid_);
@@ -282,16 +328,23 @@ ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
// ServiceWorkerRegistrationObjectHosts owned by |this|. Otherwise, this
// destructor can trigger their Mojo connection error handlers, which would
// call back into halfway destroyed |this|. This is because they are
- // associated with the ServiceWorkerEventDispatcher interface, which can
- // be destroyed while in this destructor (|running_hosted_version_|'s
- // |event_dispatcher_|). See https://crbug.com/854993.
- handles_.clear();
+ // associated with the ServiceWorker interface, which can be destroyed while
+ // in this destructor (|running_hosted_version_|'s |event_dispatcher_|). See
+ // https://crbug.com/854993.
+ service_worker_object_hosts_.clear();
registration_object_hosts_.clear();
+
+ // This host may be destroyed before it received the anticipated
+ // HintToUpdateServiceWorker IPC from the renderer. This can occur on
+ // navigation failure or if the frame closed soon after navigation. The
+ // PendingVersionUpdate objects decrement the hint count upon destruction.
+ DCHECK(versions_to_update_.empty() ||
+ blink::ServiceWorkerUtils::IsServicificationEnabled());
}
int ServiceWorkerProviderHost::frame_id() const {
- if (info_.type == blink::mojom::ServiceWorkerProviderType::kForWindow)
- return info_.route_id;
+ if (info_->type == blink::mojom::ServiceWorkerProviderType::kForWindow)
+ return info_->route_id;
return MSG_ROUTING_NONE;
}
@@ -314,6 +367,24 @@ bool ServiceWorkerProviderHost::IsContextSecureForServiceWorker() const {
return schemes.find(document_url().scheme()) != schemes.end();
}
+blink::mojom::ControllerServiceWorkerMode
+ServiceWorkerProviderHost::GetControllerMode() const {
+ if (!controller_)
+ return blink::mojom::ControllerServiceWorkerMode::kNoController;
+ switch (controller_->fetch_handler_existence()) {
+ case ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST:
+ return blink::mojom::ControllerServiceWorkerMode::kNoFetchEventHandler;
+ case ServiceWorkerVersion::FetchHandlerExistence::EXISTS:
+ return blink::mojom::ControllerServiceWorkerMode::kControlled;
+ case ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN:
+ // UNKNOWN means the controller is still installing. It's not possible to
+ // have a controller that hasn't finished installing.
+ NOTREACHED();
+ }
+ NOTREACHED();
+ return blink::mojom::ControllerServiceWorkerMode::kNoController;
+}
+
void ServiceWorkerProviderHost::OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
ChangedVersionAttributesMask changed_mask,
@@ -359,7 +430,7 @@ void ServiceWorkerProviderHost::OnSkippedWaiting(
mojom::ControllerServiceWorkerPtr
ServiceWorkerProviderHost::GetControllerServiceWorkerPtr() {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
DCHECK(controller_);
if (controller_->fetch_handler_existence() ==
ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST) {
@@ -405,16 +476,24 @@ void ServiceWorkerProviderHost::SetControllerVersionAttribute(
// SetController message should be sent only for clients.
DCHECK(IsProviderForClient());
+ // If there is no connection to the renderer yet, |this| is hosting a reserved
+ // client undergoing navigation. The controller will be sent on navigation
+ // commit. See CommitNavigation in frame.mojom.
+ if (!container_.is_bound()) {
+ DCHECK_EQ(blink::mojom::ServiceWorkerClientType::kWindow, client_type());
+ DCHECK(!is_execution_ready_);
+ return;
+ }
SendSetControllerServiceWorker(notify_controllerchange);
}
bool ServiceWorkerProviderHost::IsProviderForServiceWorker() const {
- return info_.type ==
+ return info_->type ==
blink::mojom::ServiceWorkerProviderType::kForServiceWorker;
}
bool ServiceWorkerProviderHost::IsProviderForClient() const {
- switch (info_.type) {
+ switch (info_->type) {
case blink::mojom::ServiceWorkerProviderType::kForWindow:
case blink::mojom::ServiceWorkerProviderType::kForSharedWorker:
return true;
@@ -423,13 +502,13 @@ bool ServiceWorkerProviderHost::IsProviderForClient() const {
case blink::mojom::ServiceWorkerProviderType::kUnknown:
break;
}
- NOTREACHED() << info_.type;
+ NOTREACHED() << info_->type;
return false;
}
blink::mojom::ServiceWorkerClientType ServiceWorkerProviderHost::client_type()
const {
- switch (info_.type) {
+ switch (info_->type) {
case blink::mojom::ServiceWorkerProviderType::kForWindow:
return blink::mojom::ServiceWorkerClientType::kWindow;
case blink::mojom::ServiceWorkerProviderType::kForSharedWorker:
@@ -438,7 +517,7 @@ blink::mojom::ServiceWorkerClientType ServiceWorkerProviderHost::client_type()
case blink::mojom::ServiceWorkerProviderType::kUnknown:
break;
}
- NOTREACHED() << info_.type;
+ NOTREACHED() << info_->type;
return blink::mojom::ServiceWorkerClientType::kWindow;
}
@@ -504,9 +583,11 @@ void ServiceWorkerProviderHost::RemoveServiceWorkerRegistrationObjectHost(
registration_object_hosts_.erase(registration_id);
}
-void ServiceWorkerProviderHost::RemoveServiceWorkerHandle(int64_t version_id) {
- DCHECK(base::ContainsKey(handles_, version_id));
- handles_.erase(version_id);
+void ServiceWorkerProviderHost::RemoveServiceWorkerObjectHost(
+ int64_t version_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(base::ContainsKey(service_worker_object_hosts_, version_id));
+ service_worker_object_hosts_.erase(version_id);
}
bool ServiceWorkerProviderHost::AllowServiceWorker(const GURL& scope) {
@@ -522,6 +603,17 @@ void ServiceWorkerProviderHost::NotifyControllerLost() {
SetControllerVersionAttribute(nullptr, true /* notify_controllerchange */);
}
+void ServiceWorkerProviderHost::AddServiceWorkerToUpdate(
+ scoped_refptr<ServiceWorkerVersion> version) {
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+ // This is only called for windows now, but it should be called for all
+ // clients someday.
+ DCHECK_EQ(provider_type(),
+ blink::mojom::ServiceWorkerProviderType::kForWindow);
+
+ versions_to_update_.emplace(std::move(version));
+}
+
std::unique_ptr<ServiceWorkerRequestHandler>
ServiceWorkerProviderHost::CreateRequestHandler(
network::mojom::FetchRequestMode request_mode,
@@ -566,20 +658,21 @@ ServiceWorkerProviderHost::CreateRequestHandler(
return std::unique_ptr<ServiceWorkerRequestHandler>();
}
-base::WeakPtr<ServiceWorkerHandle>
-ServiceWorkerProviderHost::GetOrCreateServiceWorkerHandle(
- ServiceWorkerVersion* version) {
+base::WeakPtr<ServiceWorkerObjectHost>
+ServiceWorkerProviderHost::GetOrCreateServiceWorkerObjectHost(
+ scoped_refptr<ServiceWorkerVersion> version) {
if (!context_ || !version)
return nullptr;
const int64_t version_id = version->version_id();
- auto existing_handle = handles_.find(version_id);
- if (existing_handle != handles_.end())
- return existing_handle->second->AsWeakPtr();
+ auto existing_object_host = service_worker_object_hosts_.find(version_id);
+ if (existing_object_host != service_worker_object_hosts_.end())
+ return existing_object_host->second->AsWeakPtr();
- handles_[version_id] =
- std::make_unique<ServiceWorkerHandle>(context_, this, version);
- return handles_[version_id]->AsWeakPtr();
+ service_worker_object_hosts_[version_id] =
+ std::make_unique<ServiceWorkerObjectHost>(context_, this,
+ std::move(version));
+ return service_worker_object_hosts_[version_id]->AsWeakPtr();
}
bool ServiceWorkerProviderHost::CanAssociateRegistration(
@@ -597,22 +690,27 @@ void ServiceWorkerProviderHost::PostMessageToClient(
ServiceWorkerVersion* version,
blink::TransferableMessage message) {
DCHECK(IsProviderForClient());
- if (!dispatcher_host_)
- return;
blink::mojom::ServiceWorkerObjectInfoPtr info;
- base::WeakPtr<ServiceWorkerHandle> handle =
- GetOrCreateServiceWorkerHandle(version);
- if (handle)
- info = handle->CreateCompleteObjectInfoToSend();
+ base::WeakPtr<ServiceWorkerObjectHost> object_host =
+ GetOrCreateServiceWorkerObjectHost(version);
+ if (object_host)
+ info = object_host->CreateCompleteObjectInfoToSend();
container_->PostMessageToClient(std::move(info), std::move(message));
}
void ServiceWorkerProviderHost::CountFeature(blink::mojom::WebFeature feature) {
- if (!dispatcher_host_)
- return;
// CountFeature message should be sent only for clients.
DCHECK(IsProviderForClient());
+ // If there is no connection to the renderer yet, |this| is hosting a reserved
+ // client undergoing navigation. The use counter will be sent correctly in
+ // CompleteNavigationInitialized() later.
+ if (!container_.is_bound()) {
+ DCHECK_EQ(blink::mojom::ServiceWorkerClientType::kWindow, client_type());
+ DCHECK(!is_execution_ready_);
+ return;
+ }
+
container_->CountFeature(feature);
}
@@ -630,28 +728,26 @@ void ServiceWorkerProviderHost::ClaimedByRegistration(
void ServiceWorkerProviderHost::CompleteNavigationInitialized(
int process_id,
- ServiceWorkerProviderHostInfo info,
- base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host) {
+ mojom::ServiceWorkerProviderHostInfoPtr info) {
DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
- DCHECK_EQ(blink::mojom::ServiceWorkerProviderType::kForWindow, info_.type);
+ DCHECK_EQ(blink::mojom::ServiceWorkerProviderType::kForWindow, info_->type);
DCHECK_EQ(kDocumentMainThreadId, render_thread_id_);
DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id);
- DCHECK_EQ(info_.provider_id, info.provider_id);
- DCHECK_NE(MSG_ROUTING_NONE, info.route_id);
+ DCHECK_EQ(info_->provider_id, info->provider_id);
+ DCHECK_NE(MSG_ROUTING_NONE, info->route_id);
is_execution_ready_ = true;
// Connect with the mojom::ServiceWorkerContainer on the renderer.
DCHECK(!container_.is_bound());
DCHECK(!binding_.is_bound());
- container_.Bind(std::move(info.client_ptr_info));
- binding_.Bind(std::move(info.host_request));
+ container_.Bind(std::move(info->client_ptr_info));
+ binding_.Bind(std::move(info->host_request));
binding_.set_connection_error_handler(
base::BindOnce(&RemoveProviderHost, context_, process_id, provider_id()));
- info_.route_id = info.route_id;
+ info_->route_id = info->route_id;
render_process_id_ = process_id;
- dispatcher_host_ = dispatcher_host;
// Now that there is a connection with the renderer-side provider, initialize
// the handle for ServiceWorkerContainer#controller, and send the controller
@@ -668,34 +764,21 @@ void ServiceWorkerProviderHost::CompleteNavigationInitialized(
mojom::ServiceWorkerProviderInfoForStartWorkerPtr
ServiceWorkerProviderHost::CompleteStartWorkerPreparation(
int process_id,
- scoped_refptr<ServiceWorkerVersion> hosted_version,
- scoped_refptr<network::SharedURLLoaderFactory> loader_factory) {
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info) {
DCHECK(context_);
DCHECK_EQ(kInvalidEmbeddedWorkerThreadId, render_thread_id_);
DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
DCHECK_EQ(blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
provider_type());
- DCHECK(!running_hosted_version_);
+ DCHECK_EQ(provider_info->provider_id, provider_id());
DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id);
-
- running_hosted_version_ = std::move(hosted_version);
-
- ServiceWorkerDispatcherHost* dispatcher_host =
- context_->GetDispatcherHost(process_id);
- DCHECK(dispatcher_host);
render_process_id_ = process_id;
- dispatcher_host_ = dispatcher_host->AsWeakPtr();
-
- // Initialize provider_info.
- mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info =
- mojom::ServiceWorkerProviderInfoForStartWorker::New();
- provider_info->provider_id = provider_id();
- provider_info->client_request = mojo::MakeRequest(&container_);
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_ptr_info;
- if (ServiceWorkerUtils::IsServicificationEnabled()) {
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo
+ script_loader_factory_ptr_info;
mojo::MakeStrongAssociatedBinding(
std::make_unique<ServiceWorkerScriptLoaderFactory>(
context_, AsWeakPtr(), std::move(loader_factory)),
@@ -704,10 +787,6 @@ ServiceWorkerProviderHost::CompleteStartWorkerPreparation(
std::move(script_loader_factory_ptr_info);
}
- binding_.Bind(mojo::MakeRequest(&provider_info->host_ptr_info));
- binding_.set_connection_error_handler(
- base::BindOnce(&RemoveProviderHost, context_, process_id, provider_id()));
-
interface_provider_binding_.Bind(FilterRendererExposedInterfaces(
mojom::kNavigation_ServiceWorkerSpec, process_id,
mojo::MakeRequest(&provider_info->interface_provider)));
@@ -751,7 +830,7 @@ void ServiceWorkerProviderHost::ReturnRegistrationForReadyIfNeeded() {
TRACE_EVENT_ASYNC_END1("ServiceWorker",
"ServiceWorkerProviderHost::GetRegistrationForReady",
this, "Registration ID", registration->id());
- if (!dispatcher_host_ || !IsContextAlive()) {
+ if (!IsContextAlive()) {
// Here no need to run or destroy |get_ready_callback_|, which will destroy
// together with |binding_| when |this| destroys.
return;
@@ -768,8 +847,7 @@ bool ServiceWorkerProviderHost::IsContextAlive() {
void ServiceWorkerProviderHost::SendSetControllerServiceWorker(
bool notify_controllerchange) {
- if (!dispatcher_host_)
- return;
+ DCHECK(IsProviderForClient());
auto controller_info = mojom::ControllerServiceWorkerInfo::New();
controller_info->client_id = client_uuid();
@@ -783,21 +861,25 @@ void ServiceWorkerProviderHost::SendSetControllerServiceWorker(
DCHECK(associated_registration_);
DCHECK_EQ(associated_registration_->active_version(), controller_.get());
+ controller_info->mode = GetControllerMode();
+
+ // S13nServiceWorker: Pass an endpoint for the client to talk to this
+ // controller.
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ controller_info->endpoint = GetControllerServiceWorkerPtr().PassInterface();
+
// Set the info for the JavaScript ServiceWorkerContainer#controller object.
- base::WeakPtr<ServiceWorkerHandle> handle =
- GetOrCreateServiceWorkerHandle(controller_.get());
- if (handle)
- controller_info->object_info = handle->CreateCompleteObjectInfoToSend();
+ base::WeakPtr<ServiceWorkerObjectHost> object_host =
+ GetOrCreateServiceWorkerObjectHost(controller_);
+ if (object_host)
+ controller_info->object_info =
+ object_host->CreateCompleteObjectInfoToSend();
// Populate used features for UseCounter purposes.
std::vector<blink::mojom::WebFeature> used_features;
for (const blink::mojom::WebFeature feature : controller_->used_features())
used_features.push_back(feature);
- // S13nServiceWorker: Pass an endpoint for the client to talk to this
- // controller.
- if (ServiceWorkerUtils::IsServicificationEnabled())
- controller_info->endpoint = GetControllerServiceWorkerPtr().PassInterface();
container_->SetController(std::move(controller_info), used_features,
notify_controllerchange);
@@ -837,13 +919,14 @@ void ServiceWorkerProviderHost::Register(
void ServiceWorkerProviderHost::RegistrationComplete(
RegisterCallback callback,
int64_t trace_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
TRACE_EVENT_ASYNC_END2("ServiceWorker", "ServiceWorkerProviderHost::Register",
- trace_id, "Status", status, "Registration ID",
- registration_id);
- if (!dispatcher_host_ || !IsContextAlive()) {
+ trace_id, "Status",
+ blink::ServiceWorkerStatusToString(status),
+ "Registration ID", registration_id);
+ if (!IsContextAlive()) {
std::move(callback).Run(
blink::mojom::ServiceWorkerErrorType::kAbort,
std::string(kServiceWorkerRegisterErrorPrefix) +
@@ -852,7 +935,7 @@ void ServiceWorkerProviderHost::RegistrationComplete(
return;
}
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::string error_message;
blink::mojom::ServiceWorkerErrorType error_type;
GetServiceWorkerErrorTypeForRegistration(status, status_message,
@@ -934,14 +1017,14 @@ void ServiceWorkerProviderHost::GetRegistrations(
void ServiceWorkerProviderHost::GetRegistrationComplete(
GetRegistrationCallback callback,
int64_t trace_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
TRACE_EVENT_ASYNC_END2(
"ServiceWorker", "ServiceWorkerProviderHost::GetRegistration", trace_id,
- "Status", status, "Registration ID",
+ "Status", blink::ServiceWorkerStatusToString(status), "Registration ID",
registration ? registration->id()
: blink::mojom::kInvalidServiceWorkerRegistrationId);
- if (!dispatcher_host_ || !IsContextAlive()) {
+ if (!IsContextAlive()) {
std::move(callback).Run(
blink::mojom::ServiceWorkerErrorType::kAbort,
std::string(kServiceWorkerGetRegistrationErrorPrefix) +
@@ -950,7 +1033,8 @@ void ServiceWorkerProviderHost::GetRegistrationComplete(
return;
}
- if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
+ if (status != blink::ServiceWorkerStatusCode::kOk &&
+ status != blink::ServiceWorkerStatusCode::kErrorNotFound) {
std::string error_message;
blink::mojom::ServiceWorkerErrorType error_type;
GetServiceWorkerErrorTypeForRegistration(status, std::string(), &error_type,
@@ -961,9 +1045,10 @@ void ServiceWorkerProviderHost::GetRegistrationComplete(
return;
}
- DCHECK(status != SERVICE_WORKER_OK || registration);
+ DCHECK(status != blink::ServiceWorkerStatusCode::kOk || registration);
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info;
- if (status == SERVICE_WORKER_OK && !registration->is_uninstalling())
+ if (status == blink::ServiceWorkerStatusCode::kOk &&
+ !registration->is_uninstalling())
info = CreateServiceWorkerRegistrationObjectInfo(std::move(registration));
std::move(callback).Run(blink::mojom::ServiceWorkerErrorType::kNone,
@@ -973,13 +1058,13 @@ void ServiceWorkerProviderHost::GetRegistrationComplete(
void ServiceWorkerProviderHost::GetRegistrationsComplete(
GetRegistrationsCallback callback,
int64_t trace_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
registrations) {
- TRACE_EVENT_ASYNC_END1("ServiceWorker",
- "ServiceWorkerProviderHost::GetRegistrations",
- trace_id, "Status", status);
- if (!dispatcher_host_ || !IsContextAlive()) {
+ TRACE_EVENT_ASYNC_END1(
+ "ServiceWorker", "ServiceWorkerProviderHost::GetRegistrations", trace_id,
+ "Status", blink::ServiceWorkerStatusToString(status));
+ if (!IsContextAlive()) {
std::move(callback).Run(
blink::mojom::ServiceWorkerErrorType::kAbort,
std::string(kServiceWorkerGetRegistrationsErrorPrefix) +
@@ -988,7 +1073,7 @@ void ServiceWorkerProviderHost::GetRegistrationsComplete(
return;
}
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::string error_message;
blink::mojom::ServiceWorkerErrorType error_type;
GetServiceWorkerErrorTypeForRegistration(status, std::string(), &error_type,
@@ -1036,9 +1121,9 @@ void ServiceWorkerProviderHost::GetRegistrationForReady(
void ServiceWorkerProviderHost::StartControllerComplete(
mojom::ControllerServiceWorkerRequest controller_request,
- ServiceWorkerStatusCode status) {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
- if (status == SERVICE_WORKER_OK)
+ blink::ServiceWorkerStatusCode status) {
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+ if (status == blink::ServiceWorkerStatusCode::kOk)
controller_->controller()->Clone(std::move(controller_request));
}
@@ -1046,10 +1131,10 @@ void ServiceWorkerProviderHost::EnsureControllerServiceWorker(
mojom::ControllerServiceWorkerRequest controller_request,
mojom::ControllerServiceWorkerPurpose purpose) {
// TODO(kinuko): Log the reasons we drop the request.
- if (!dispatcher_host_ || !IsContextAlive() || !controller_)
+ if (!IsContextAlive() || !controller_)
return;
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
controller_->RunAfterStartWorker(
PurposeToEventType(purpose),
base::BindOnce(&ServiceWorkerProviderHost::StartControllerComplete,
@@ -1058,7 +1143,7 @@ void ServiceWorkerProviderHost::EnsureControllerServiceWorker(
void ServiceWorkerProviderHost::CloneForWorker(
mojom::ServiceWorkerContainerHostRequest container_host_request) {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
bindings_for_worker_threads_.AddBinding(this,
std::move(container_host_request));
}
@@ -1067,6 +1152,17 @@ void ServiceWorkerProviderHost::Ping(PingCallback callback) {
std::move(callback).Run();
}
+void ServiceWorkerProviderHost::HintToUpdateServiceWorker() {
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+ if (!IsProviderForClient()) {
+ mojo::ReportBadMessage("SWPH_HTUSW_NOT_CLIENT");
+ return;
+ }
+
+ // The destructors notify the ServiceWorkerVersions to update.
+ versions_to_update_.clear();
+}
+
bool ServiceWorkerProviderHost::IsValidRegisterMessage(
const GURL& script_url,
const blink::mojom::ServiceWorkerRegistrationOptions& options,
@@ -1175,7 +1271,7 @@ bool ServiceWorkerProviderHost::CanServeContainerHostMethods(
const GURL& scope,
const char* error_prefix,
Args... args) {
- if (!dispatcher_host_ || !IsContextAlive()) {
+ if (!IsContextAlive()) {
std::move(*callback).Run(
blink::mojom::ServiceWorkerErrorType::kAbort,
std::string(error_prefix) +
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 9b69c149e3a..ded291f894a 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.h
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.h
@@ -19,11 +19,11 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
-#include "content/browser/service_worker/service_worker_handle.h"
+#include "content/browser/service_worker/service_worker_object_host.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_container.mojom.h"
-#include "content/common/service_worker/service_worker_provider_host_info.h"
+#include "content/common/service_worker/service_worker_provider.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
@@ -40,8 +40,8 @@ namespace network {
class ResourceRequestBody;
}
-namespace service_worker_handle_unittest {
-class ServiceWorkerHandleTest;
+namespace service_worker_object_host_unittest {
+class ServiceWorkerObjectHostTest;
}
namespace storage {
@@ -51,7 +51,6 @@ class BlobStorageContext;
namespace content {
class ServiceWorkerContextCore;
-class ServiceWorkerDispatcherHost;
class ServiceWorkerRegistrationObjectHost;
class ServiceWorkerRequestHandler;
class ServiceWorkerVersion;
@@ -147,11 +146,16 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
bool are_ancestors_secure,
const WebContentsGetter& web_contents_getter);
- // Creates a ServiceWorkerProviderHost for a service worker execution context.
- // Information about this provider host is passed down to the service worker
- // via StartWorker message.
- static std::unique_ptr<ServiceWorkerProviderHost> PreCreateForController(
- base::WeakPtr<ServiceWorkerContextCore> context);
+ // Used for starting a service worker. Returns a provider host for the service
+ // worker and partially fills |out_provider_info|. The host stays alive as
+ // long as this info stays alive (namely, as long as
+ // |out_provider_info->host_ptr_info| stays alive).
+ // CompleteStartWorkerPreparation() must be called later to get a full info to
+ // send to the renderer.
+ static base::WeakPtr<ServiceWorkerProviderHost> PreCreateForController(
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ scoped_refptr<ServiceWorkerVersion> version,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr* out_provider_info);
// S13nServiceWorker:
// Used for starting a shared worker. Returns a provider host for the shared
@@ -168,23 +172,22 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// |process_id|.
static std::unique_ptr<ServiceWorkerProviderHost> Create(
int process_id,
- ServiceWorkerProviderHostInfo info,
- base::WeakPtr<ServiceWorkerContextCore> context,
- base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host);
+ mojom::ServiceWorkerProviderHostInfoPtr info,
+ base::WeakPtr<ServiceWorkerContextCore> context);
~ServiceWorkerProviderHost() override;
const std::string& client_uuid() const { return client_uuid_; }
base::TimeTicks create_time() const { return create_time_; }
int process_id() const { return render_process_id_; }
- int provider_id() const { return info_.provider_id; }
+ int provider_id() const { return info_->provider_id; }
int frame_id() const;
- int route_id() const { return info_.route_id; }
+ int route_id() const { return info_->route_id; }
const WebContentsGetter& web_contents_getter() const {
return web_contents_getter_;
}
- bool is_parent_frame_secure() const { return info_.is_parent_frame_secure; }
+ bool is_parent_frame_secure() const { return info_->is_parent_frame_secure; }
// Returns whether this provider host is secure enough to have a service
// worker controller.
@@ -196,6 +199,10 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// security, so they must be set properly before calling this function.
bool IsContextSecureForServiceWorker() const;
+ // For service worker clients. Describes whether the client has a controller
+ // and if it has a fetch event handler.
+ blink::mojom::ControllerServiceWorkerMode GetControllerMode() const;
+
// Returns this provider's controller. The controller is typically the same as
// active_version() but can differ in the following cases:
// (1) The client was created before the registration existed or had an active
@@ -244,7 +251,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// CompleteStartWorkerPreparation() is called).
ServiceWorkerVersion* running_hosted_version() const {
DCHECK(!running_hosted_version_ ||
- info_.type ==
+ info_->type ==
blink::mojom::ServiceWorkerProviderType::kForServiceWorker);
return running_hosted_version_.get();
}
@@ -291,7 +298,8 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// is in scope of all |matching_registrations_|.
// |document_url_| is the service worker script URL if this is for a
// service worker execution context. It will be used when creating
- // ServiceWorkerHandle or handling ServiceWorkerRegistration#{*} calls etc.
+ // ServiceWorkerObjectHost or handling ServiceWorkerRegistration#{*} calls
+ // etc.
// TODO(leonhsl): We should rename |document_url_| to something more
// appropriate and/or split this class into one for clients vs one for service
// workers.
@@ -305,7 +313,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
const GURL& topmost_frame_url() const;
blink::mojom::ServiceWorkerProviderType provider_type() const {
- return info_.type;
+ return info_->type;
}
bool IsProviderForServiceWorker() const;
bool IsProviderForClient() const;
@@ -352,12 +360,11 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
CreateServiceWorkerRegistrationObjectInfo(
scoped_refptr<ServiceWorkerRegistration> registration);
- // Returns a ServiceWorkerHandle instance for |version| for this provider
+ // Returns a ServiceWorkerObjectHost instance for |version| for this provider
// host. A new instance is created if one does not already exist.
- // TODO(leonhsl): Make |version| be a scoped_refptr because we'll take its
- // ownership.
- base::WeakPtr<ServiceWorkerHandle> GetOrCreateServiceWorkerHandle(
- ServiceWorkerVersion* version);
+ // ServiceWorkerObjectHost will have an ownership of the |version|.
+ base::WeakPtr<ServiceWorkerObjectHost> GetOrCreateServiceWorkerObjectHost(
+ scoped_refptr<ServiceWorkerVersion> version);
// Returns true if |registration| can be associated with this provider.
bool CanAssociateRegistration(ServiceWorkerRegistration* registration);
@@ -386,15 +393,16 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// provider hosts used for navigation requests.
void CompleteNavigationInitialized(
int process_id,
- ServiceWorkerProviderHostInfo info,
- base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host);
+ mojom::ServiceWorkerProviderHostInfoPtr info);
// For service worker execution contexts. Completes initialization of this
// provider host. It is called once a renderer process has been found to host
// the worker. Returns the info needed for creating a provider on the renderer
- // which will be connected to this provider host. This instance will take the
- // reference to |hosted_version|, so be careful not to create a reference
- // cycle.
+ // which will be connected to this provider host.
+ //
+ // |provider_info| should be the info returned by PreCreateForController(),
+ // which is partially filled out. This function returns it after
+ // filling it out completely.
//
// S13nServiceWorker:
// |loader_factory| is the factory to use for "network" requests for the
@@ -404,8 +412,8 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
mojom::ServiceWorkerProviderInfoForStartWorkerPtr
CompleteStartWorkerPreparation(
int process_id,
- scoped_refptr<ServiceWorkerVersion> hosted_version,
- scoped_refptr<network::SharedURLLoaderFactory> loader_factory);
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info);
// Called when the shared worker main script resource has finished loading.
// After this is called, is_execution_ready() returns true.
@@ -422,8 +430,8 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// |registration_id|.
void RemoveServiceWorkerRegistrationObjectHost(int64_t registration_id);
- // Removes the ServiceWorkerHandle corresponding to |version_id|.
- void RemoveServiceWorkerHandle(int64_t version_id);
+ // Removes the ServiceWorkerObjectHost corresponding to |version_id|.
+ void RemoveServiceWorkerObjectHost(int64_t version_id);
// Calls ContentBrowserClient::AllowServiceWorker(). Returns true if content
// settings allows service workers to run at |scope|. If this provider is for
@@ -436,6 +444,26 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// cache.
void NotifyControllerLost();
+ // S13nServiceWorker:
+ // For service worker clients. Called when |version| is the active worker upon
+ // the main resource request for this client. Remembers |version| as needing
+ // a Soft Update. To avoid affecting page load performance, the update occurs
+ // when we get a HintToUpdateServiceWorker message from the renderer, or when
+ // |this| is destroyed before receiving that message.
+ //
+ // Corresponds to the Handle Fetch algorithm:
+ // "If request is a non-subresource request...invoke Soft Update algorithm
+ // with registration."
+ // https://w3c.github.io/ServiceWorker/#on-fetch-request-algorithm
+ //
+ // This can be called multiple times due to redirects during a main resource
+ // load. All service workers are updated.
+ //
+ // For non-S13nServiceWorker: The update logic is controlled entirely by
+ // ServiceWorkerControlleeRequestHandler, which sees all resource request
+ // activity and schedules an update at a convenient time.
+ void AddServiceWorkerToUpdate(scoped_refptr<ServiceWorkerVersion> version);
+
bool is_execution_ready() const { return is_execution_ready_; }
private:
@@ -443,7 +471,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
friend class ServiceWorkerProviderHostTest;
friend class ServiceWorkerWriteToCacheJobTest;
friend class ServiceWorkerContextRequestHandlerTest;
- friend class service_worker_handle_unittest::ServiceWorkerHandleTest;
+ friend class service_worker_object_host_unittest::ServiceWorkerObjectHostTest;
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest, Update_SameScript);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
Update_SameSizeScript);
@@ -467,11 +495,9 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
FRIEND_TEST_ALL_PREFIXES(BackgroundSyncManagerTest,
RegisterWithoutLiveSWRegistration);
- ServiceWorkerProviderHost(
- int process_id,
- ServiceWorkerProviderHostInfo info,
- base::WeakPtr<ServiceWorkerContextCore> context,
- base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host);
+ ServiceWorkerProviderHost(int process_id,
+ mojom::ServiceWorkerProviderHostInfoPtr info,
+ base::WeakPtr<ServiceWorkerContextCore> context);
// ServiceWorkerRegistration::Listener overrides.
void OnVersionAttributesChanged(
@@ -519,31 +545,32 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
void CloneForWorker(
mojom::ServiceWorkerContainerHostRequest container_host_request) override;
void Ping(PingCallback callback) override;
+ void HintToUpdateServiceWorker() override;
// Callback for ServiceWorkerContextCore::RegisterServiceWorker().
void RegistrationComplete(RegisterCallback callback,
int64_t trace_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id);
// Callback for ServiceWorkerStorage::FindRegistrationForDocument().
void GetRegistrationComplete(
GetRegistrationCallback callback,
int64_t trace_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
// Callback for ServiceWorkerStorage::GetRegistrationsForOrigin().
void GetRegistrationsComplete(
GetRegistrationsCallback callback,
int64_t trace_id,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
registrations);
// Callback for ServiceWorkerVersion::RunAfterStartWorker()
void StartControllerComplete(
mojom::ControllerServiceWorkerRequest controller_request,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
bool IsValidRegisterMessage(
const GURL& script_url,
@@ -580,7 +607,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// Otherwise, |kDocumentMainThreadId|.
int render_thread_id_;
- ServiceWorkerProviderHostInfo info_;
+ mojom::ServiceWorkerProviderHostInfoPtr info_;
// Only set when this object is pre-created for a navigation. It indicates the
// tab where the navigation occurs.
@@ -607,12 +634,12 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
std::unique_ptr<ServiceWorkerRegistrationObjectHost>>
registration_object_hosts_;
- // Contains all ServiceWorkerHandle instances corresponding to
+ // Contains all ServiceWorkerObjectHost instances corresponding to
// the service worker JavaScript objects for the hosted execution
// context (service worker global scope or service worker client) in the
// renderer process.
- std::map<int64_t /* version_id */, std::unique_ptr<ServiceWorkerHandle>>
- handles_;
+ std::map<int64_t /* version_id */, std::unique_ptr<ServiceWorkerObjectHost>>
+ service_worker_object_hosts_;
// The ready() promise is only allowed to be created once.
// |get_ready_callback_| has three states:
@@ -627,22 +654,11 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// ServiceWorkerContainer#controller).
scoped_refptr<ServiceWorkerVersion> controller_;
// For service worker execution contexts. The ServiceWorkerVersion of the
- // service worker this is a provider for. This is nullptr if the service
- // worker is still being started up (until CompleteStartWorkerPreparation() is
- // called).
+ // service worker this is a provider for.
scoped_refptr<ServiceWorkerVersion> running_hosted_version_;
base::WeakPtr<ServiceWorkerContextCore> context_;
- // |dispatcher_host_| is expected to outlive |this| because it destroys
- // |this| upon destruction. However, it may be null in some cases:
- // 1) In some tests.
- // 2) Navigations and service worker startup pre-create a
- // ServiceWorkerProviderHost instance before there is a renderer assigned to
- // it. The dispatcher host is set once the instance starts hosting a
- // renderer.
- base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host_;
-
bool allow_association_;
// |container_| is the Mojo endpoint to the renderer-side
@@ -677,8 +693,11 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// redirects.
bool is_execution_ready_ = false;
- // TODO(crbug.com/838410): Temporary debugging for the linked bug.
- bool in_dtor_ = false;
+ // For service worker clients. The service workers in the chain of redirects
+ // during the main resource request for this client. These workers should be
+ // updated "soon". See AddServiceWorkerToUpdate() documentation.
+ class PendingUpdateVersion;
+ base::flat_set<PendingUpdateVersion> versions_to_update_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHost);
};
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc b/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc
index d5a07710e2f..7cc8b71f605 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
@@ -27,8 +28,9 @@
#include "content/public/test/test_utils.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_content_client.h"
-#include "mojo/edk/embedder/embedder.h"
+#include "mojo/core/embedder/embedder.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -73,7 +75,7 @@ class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
} // namespace
-class ServiceWorkerProviderHostTest : public testing::Test {
+class ServiceWorkerProviderHostTest : public testing::TestWithParam<bool> {
protected:
ServiceWorkerProviderHostTest()
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
@@ -83,10 +85,18 @@ class ServiceWorkerProviderHostTest : public testing::Test {
~ServiceWorkerProviderHostTest() override {}
void SetUp() override {
+ if (IsServiceWorkerServicificationEnabled()) {
+ scoped_feature_list_.InitAndEnableFeature(
+ blink::features::kServiceWorkerServicification);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ blink::features::kServiceWorkerServicification);
+ }
+
old_content_browser_client_ =
SetBrowserClientForTesting(&test_content_browser_client_);
ResetSchemesAndOriginsWhitelist();
- mojo::edk::SetDefaultProcessErrorCallback(base::Bind(
+ mojo::core::SetDefaultProcessErrorCallback(base::Bind(
&ServiceWorkerProviderHostTest::OnMojoError, base::Unretained(this)));
helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
@@ -117,8 +127,8 @@ class ServiceWorkerProviderHostTest : public testing::Test {
SetBrowserClientForTesting(old_content_browser_client_);
// Reset cached security schemes so we don't affect other tests.
ResetSchemesAndOriginsWhitelist();
- mojo::edk::SetDefaultProcessErrorCallback(
- mojo::edk::ProcessErrorCallback());
+ mojo::core::SetDefaultProcessErrorCallback(
+ mojo::core::ProcessErrorCallback());
}
ServiceWorkerRemoteProviderEndpoint PrepareServiceWorkerProviderHost(
@@ -162,21 +172,15 @@ class ServiceWorkerProviderHostTest : public testing::Test {
}
void FinishNavigation(ServiceWorkerProviderHost* host,
- ServiceWorkerProviderHostInfo info) {
+ mojom::ServiceWorkerProviderHostInfoPtr info) {
// In production code, the loader/request handler does this.
host->SetDocumentUrl(GURL("https://www.example.com/page"));
host->SetTopmostFrameUrl(GURL("https://www.example.com/page"));
// In production code, the OnProviderCreated IPC is received which
// does this.
- std::unique_ptr<ServiceWorkerProviderHost> owned_host =
- helper_->context()->ReleaseProviderHost(host->process_id(),
- host->provider_id());
- host->CompleteNavigationInitialized(
- helper_->mock_render_process_id(), std::move(info),
- helper_->GetDispatcherHostForProcess(helper_->mock_render_process_id())
- ->AsWeakPtr());
- helper_->context()->AddProviderHost(std::move(owned_host));
+ host->CompleteNavigationInitialized(helper_->mock_render_process_id(),
+ std::move(info));
}
blink::mojom::ServiceWorkerErrorType Register(
@@ -255,8 +259,29 @@ class ServiceWorkerProviderHostTest : public testing::Test {
return false;
}
- std::vector<std::string> bad_messages_;
+ bool IsServiceWorkerServicificationEnabled() { return GetParam(); }
+
+ void ExpectUpdateIsScheduled(ServiceWorkerVersion* version) {
+ EXPECT_TRUE(version->is_update_scheduled_);
+ EXPECT_TRUE(version->update_timer_.IsRunning());
+ }
+
+ void ExpectUpdateIsNotScheduled(ServiceWorkerVersion* version) {
+ EXPECT_FALSE(version->is_update_scheduled_);
+ EXPECT_FALSE(version->update_timer_.IsRunning());
+ }
+
+ bool HasVersionToUpdate(ServiceWorkerProviderHost* host) {
+ return !host->versions_to_update_.empty();
+ }
+
+ // |scoped_feature_list_| must be before |thread_bundle_|, since
+ // the thread bundle's destruction causes service worker-related
+ // objects to destruct, whose destructors need to know whether servicification
+ // is enabled.
+ base::test::ScopedFeatureList scoped_feature_list_;
TestBrowserThreadBundle thread_bundle_;
+
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
ServiceWorkerContextCore* context_;
scoped_refptr<ServiceWorkerRegistration> registration1_;
@@ -268,6 +293,7 @@ class ServiceWorkerProviderHostTest : public testing::Test {
ContentBrowserClient* old_content_browser_client_;
int next_renderer_provided_id_;
std::vector<ServiceWorkerRemoteProviderEndpoint> remote_endpoints_;
+ std::vector<std::string> bad_messages_;
private:
ServiceWorkerProviderHost* CreateProviderHostInternal(
@@ -278,30 +304,21 @@ class ServiceWorkerProviderHostTest : public testing::Test {
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true,
base::Callback<WebContents*(void)>());
- ServiceWorkerProviderHostInfo info(
- host->provider_id(), 1 /* route_id */,
- blink::mojom::ServiceWorkerProviderType::kForWindow,
- true /* is_parent_frame_secure */);
+ mojom::ServiceWorkerProviderHostInfoPtr info =
+ CreateProviderHostInfoForWindow(host->provider_id(), 1 /* route_id */);
remote_endpoint->BindWithProviderHostInfo(&info);
- std::unique_ptr<ServiceWorkerProviderHost> owned_host =
- helper_->context()->ReleaseProviderHost(host->process_id(),
- host->provider_id());
- host->CompleteNavigationInitialized(
- helper_->mock_render_process_id(), std::move(info),
- helper_->GetDispatcherHostForProcess(helper_->mock_render_process_id())
- ->AsWeakPtr());
+ host->CompleteNavigationInitialized(helper_->mock_render_process_id(),
+ std::move(info));
host->SetDocumentUrl(document_url);
host->SetTopmostFrameUrl(topmost_frame_url);
- helper_->context()->AddProviderHost(std::move(owned_host));
-
return host.get();
}
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHostTest);
};
-TEST_F(ServiceWorkerProviderHostTest, MatchRegistration) {
+TEST_P(ServiceWorkerProviderHostTest, MatchRegistration) {
ServiceWorkerProviderHost* provider_host1 =
CreateProviderHost(GURL("https://www.example.com/example1.html"));
@@ -327,7 +344,7 @@ TEST_F(ServiceWorkerProviderHostTest, MatchRegistration) {
ASSERT_EQ(nullptr, provider_host1->MatchRegistration());
}
-TEST_F(ServiceWorkerProviderHostTest, ContextSecurity) {
+TEST_P(ServiceWorkerProviderHostTest, ContextSecurity) {
ServiceWorkerProviderHost* provider_host_secure_parent =
CreateProviderHost(GURL("https://www.example.com/example1.html"));
ServiceWorkerProviderHost* provider_host_insecure_parent =
@@ -388,7 +405,7 @@ class MockServiceWorkerRegistration : public ServiceWorkerRegistration {
std::set<ServiceWorkerRegistration::Listener*> listeners_;
};
-TEST_F(ServiceWorkerProviderHostTest, RemoveProvider) {
+TEST_P(ServiceWorkerProviderHostTest, RemoveProvider) {
// Create a provider host connected with the renderer process.
ServiceWorkerProviderHost* provider_host =
CreateProviderHost(GURL("https://www.example.com/example1.html"));
@@ -427,16 +444,14 @@ class MockServiceWorkerContainer : public mojom::ServiceWorkerContainer {
mojo::AssociatedBinding<mojom::ServiceWorkerContainer> binding_;
};
-TEST_F(ServiceWorkerProviderHostTest, Controller) {
+TEST_P(ServiceWorkerProviderHostTest, Controller) {
// Create a host.
base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
base::Callback<WebContents*(void)>());
- ServiceWorkerProviderHostInfo info(
- host->provider_id(), 1 /* route_id */,
- blink::mojom::ServiceWorkerProviderType::kForWindow,
- true /* is_parent_frame_secure */);
+ mojom::ServiceWorkerProviderHostInfoPtr info =
+ CreateProviderHostInfoForWindow(host->provider_id(), 1 /* route_id */);
remote_endpoints_.emplace_back();
remote_endpoints_.back().BindWithProviderHostInfo(&info);
auto container = std::make_unique<MockServiceWorkerContainer>(
@@ -446,6 +461,9 @@ TEST_F(ServiceWorkerProviderHostTest, Controller) {
scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
registration1_.get(), GURL("https://www.example.com/sw.js"),
1 /* version_id */, helper_->context()->AsWeakPtr());
+ version->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version->SetStatus(ServiceWorkerVersion::ACTIVATED);
registration1_->SetActiveVersion(version);
// Finish the navigation.
@@ -461,16 +479,14 @@ TEST_F(ServiceWorkerProviderHostTest, Controller) {
EXPECT_TRUE(container->was_set_controller_called());
}
-TEST_F(ServiceWorkerProviderHostTest, ActiveIsNotController) {
+TEST_P(ServiceWorkerProviderHostTest, ActiveIsNotController) {
// Create a host.
base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
base::Callback<WebContents*(void)>());
- ServiceWorkerProviderHostInfo info(
- host->provider_id(), 1 /* route_id */,
- blink::mojom::ServiceWorkerProviderType::kForWindow,
- true /* is_parent_frame_secure */);
+ mojom::ServiceWorkerProviderHostInfoPtr info =
+ CreateProviderHostInfoForWindow(host->provider_id(), 1 /* route_id */);
remote_endpoints_.emplace_back();
remote_endpoints_.back().BindWithProviderHostInfo(&info);
auto container = std::make_unique<MockServiceWorkerContainer>(
@@ -499,7 +515,7 @@ TEST_F(ServiceWorkerProviderHostTest, ActiveIsNotController) {
EXPECT_FALSE(container->was_set_controller_called());
}
-TEST_F(ServiceWorkerProviderHostTest,
+TEST_P(ServiceWorkerProviderHostTest,
Register_ContentSettingsDisallowsServiceWorker) {
ServiceWorkerTestContentBrowserClient test_browser_client;
ContentBrowserClient* old_browser_client =
@@ -540,7 +556,7 @@ TEST_F(ServiceWorkerProviderHostTest,
SetBrowserClientForTesting(old_browser_client);
}
-TEST_F(ServiceWorkerProviderHostTest, AllowsServiceWorker) {
+TEST_P(ServiceWorkerProviderHostTest, AllowsServiceWorker) {
// Create an active version.
scoped_refptr<ServiceWorkerVersion> version =
base::MakeRefCounted<ServiceWorkerVersion>(
@@ -549,7 +565,7 @@ TEST_F(ServiceWorkerProviderHostTest, AllowsServiceWorker) {
registration1_->SetActiveVersion(version);
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
- std::unique_ptr<ServiceWorkerProviderHost> host =
+ base::WeakPtr<ServiceWorkerProviderHost> host =
CreateProviderHostForServiceWorkerContext(
helper_->mock_render_process_id(), true /* is_parent_frame_secure */,
version.get(), helper_->context()->AsWeakPtr(), &remote_endpoint);
@@ -569,7 +585,7 @@ TEST_F(ServiceWorkerProviderHostTest, AllowsServiceWorker) {
SetBrowserClientForTesting(old_browser_client);
}
-TEST_F(ServiceWorkerProviderHostTest, Register_HTTPS) {
+TEST_P(ServiceWorkerProviderHostTest, Register_HTTPS) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("https://www.example.com/foo"));
@@ -579,7 +595,7 @@ TEST_F(ServiceWorkerProviderHostTest, Register_HTTPS) {
GURL("https://www.example.com/bar")));
}
-TEST_F(ServiceWorkerProviderHostTest, Register_NonSecureTransportLocalhost) {
+TEST_P(ServiceWorkerProviderHostTest, Register_NonSecureTransportLocalhost) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("http://127.0.0.3:81/foo"));
@@ -589,7 +605,7 @@ TEST_F(ServiceWorkerProviderHostTest, Register_NonSecureTransportLocalhost) {
GURL("http://127.0.0.3:81/baz")));
}
-TEST_F(ServiceWorkerProviderHostTest, Register_InvalidScopeShouldFail) {
+TEST_P(ServiceWorkerProviderHostTest, Register_InvalidScopeShouldFail) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("https://www.example.com/foo"));
@@ -599,7 +615,7 @@ TEST_F(ServiceWorkerProviderHostTest, Register_InvalidScopeShouldFail) {
EXPECT_EQ(1u, bad_messages_.size());
}
-TEST_F(ServiceWorkerProviderHostTest, Register_InvalidScriptShouldFail) {
+TEST_P(ServiceWorkerProviderHostTest, Register_InvalidScriptShouldFail) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("https://www.example.com/foo"));
@@ -609,7 +625,7 @@ TEST_F(ServiceWorkerProviderHostTest, Register_InvalidScriptShouldFail) {
EXPECT_EQ(1u, bad_messages_.size());
}
-TEST_F(ServiceWorkerProviderHostTest, Register_NonSecureOriginShouldFail) {
+TEST_P(ServiceWorkerProviderHostTest, Register_NonSecureOriginShouldFail) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("http://www.example.com/foo"));
@@ -619,7 +635,7 @@ TEST_F(ServiceWorkerProviderHostTest, Register_NonSecureOriginShouldFail) {
EXPECT_EQ(1u, bad_messages_.size());
}
-TEST_F(ServiceWorkerProviderHostTest, Register_CrossOriginShouldFail) {
+TEST_P(ServiceWorkerProviderHostTest, Register_CrossOriginShouldFail) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("https://www.example.com/foo"));
@@ -654,7 +670,7 @@ TEST_F(ServiceWorkerProviderHostTest, Register_CrossOriginShouldFail) {
EXPECT_EQ(6u, bad_messages_.size());
}
-TEST_F(ServiceWorkerProviderHostTest, Register_BadCharactersShouldFail) {
+TEST_P(ServiceWorkerProviderHostTest, Register_BadCharactersShouldFail) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("https://www.example.com"));
@@ -687,7 +703,7 @@ TEST_F(ServiceWorkerProviderHostTest, Register_BadCharactersShouldFail) {
EXPECT_EQ(6u, bad_messages_.size());
}
-TEST_F(ServiceWorkerProviderHostTest, Register_FileSystemDocumentShouldFail) {
+TEST_P(ServiceWorkerProviderHostTest, Register_FileSystemDocumentShouldFail) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(
GURL("filesystem:https://www.example.com/temporary/a"));
@@ -709,7 +725,7 @@ TEST_F(ServiceWorkerProviderHostTest, Register_FileSystemDocumentShouldFail) {
EXPECT_EQ(3u, bad_messages_.size());
}
-TEST_F(ServiceWorkerProviderHostTest,
+TEST_P(ServiceWorkerProviderHostTest,
Register_FileSystemScriptOrScopeShouldFail) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(
@@ -732,7 +748,7 @@ TEST_F(ServiceWorkerProviderHostTest,
EXPECT_EQ(3u, bad_messages_.size());
}
-TEST_F(ServiceWorkerProviderHostTest, EarlyContextDeletion) {
+TEST_P(ServiceWorkerProviderHostTest, EarlyContextDeletion) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("https://www.example.com/foo"));
@@ -746,7 +762,7 @@ TEST_F(ServiceWorkerProviderHostTest, EarlyContextDeletion) {
EXPECT_TRUE(remote_endpoint.host_ptr()->encountered_error());
}
-TEST_F(ServiceWorkerProviderHostTest, GetRegistration_Success) {
+TEST_P(ServiceWorkerProviderHostTest, GetRegistration_Success) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("https://www.example.com/foo"));
@@ -761,7 +777,7 @@ TEST_F(ServiceWorkerProviderHostTest, GetRegistration_Success) {
EXPECT_EQ(kScope, info->options->scope);
}
-TEST_F(ServiceWorkerProviderHostTest,
+TEST_P(ServiceWorkerProviderHostTest,
GetRegistration_NotFoundShouldReturnNull) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("https://www.example.com/foo"));
@@ -773,7 +789,7 @@ TEST_F(ServiceWorkerProviderHostTest,
EXPECT_FALSE(info);
}
-TEST_F(ServiceWorkerProviderHostTest, GetRegistration_CrossOriginShouldFail) {
+TEST_P(ServiceWorkerProviderHostTest, GetRegistration_CrossOriginShouldFail) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("https://www.example.com/foo"));
@@ -783,7 +799,7 @@ TEST_F(ServiceWorkerProviderHostTest, GetRegistration_CrossOriginShouldFail) {
EXPECT_EQ(1u, bad_messages_.size());
}
-TEST_F(ServiceWorkerProviderHostTest, GetRegistration_InvalidScopeShouldFail) {
+TEST_P(ServiceWorkerProviderHostTest, GetRegistration_InvalidScopeShouldFail) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("https://www.example.com/foo"));
@@ -792,7 +808,7 @@ TEST_F(ServiceWorkerProviderHostTest, GetRegistration_InvalidScopeShouldFail) {
EXPECT_EQ(1u, bad_messages_.size());
}
-TEST_F(ServiceWorkerProviderHostTest,
+TEST_P(ServiceWorkerProviderHostTest,
GetRegistration_NonSecureOriginShouldFail) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("http://www.example.com/foo"));
@@ -803,7 +819,7 @@ TEST_F(ServiceWorkerProviderHostTest,
EXPECT_EQ(1u, bad_messages_.size());
}
-TEST_F(ServiceWorkerProviderHostTest, GetRegistrations_SecureOrigin) {
+TEST_P(ServiceWorkerProviderHostTest, GetRegistrations_SecureOrigin) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("https://www.example.com/foo"));
@@ -811,7 +827,7 @@ TEST_F(ServiceWorkerProviderHostTest, GetRegistrations_SecureOrigin) {
GetRegistrations(remote_endpoint.host_ptr()->get()));
}
-TEST_F(ServiceWorkerProviderHostTest,
+TEST_P(ServiceWorkerProviderHostTest,
GetRegistrations_NonSecureOriginShouldFail) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint =
PrepareServiceWorkerProviderHost(GURL("http://www.example.com/foo"));
@@ -824,7 +840,7 @@ TEST_F(ServiceWorkerProviderHostTest,
// Test that a "reserved" (i.e., not execution ready) client is not included
// when iterating over client provider hosts. If it were, it'd be undesirably
// exposed via the Clients API.
-TEST_F(ServiceWorkerProviderHostTest,
+TEST_P(ServiceWorkerProviderHostTest,
ReservedClientsAreNotExposedToClientsAPI) {
{
auto provider_info = mojom::ServiceWorkerProviderInfoForSharedWorker::New();
@@ -844,10 +860,8 @@ TEST_F(ServiceWorkerProviderHostTest,
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true,
base::RepeatingCallback<WebContents*(void)>());
- ServiceWorkerProviderHostInfo info(
- host->provider_id(), 1 /* route_id */,
- blink::mojom::ServiceWorkerProviderType::kForWindow,
- true /* is_parent_frame_secure */);
+ mojom::ServiceWorkerProviderHostInfoPtr info =
+ CreateProviderHostInfoForWindow(host->provider_id(), 1 /* route_id */);
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
remote_endpoint.BindWithProviderHostInfo(&info);
host->SetDocumentUrl(GURL("https://www.example.com/page"));
@@ -858,4 +872,272 @@ TEST_F(ServiceWorkerProviderHostTest,
}
}
+// Regression test for https://crbug.com/860106. When a provider host
+// is destroyed, it removes itself as a controllee from its controller.
+// This can trigger the waiting version starting to activate. The
+// destructing host shouldn't try to change its controller to the new
+// active version.
+TEST_P(ServiceWorkerProviderHostTest, DontSetControllerInDestructor) {
+ // This test requires the idle timeout mechanism of S13nSW to exercise the
+ // desired code path.
+ if (!IsServiceWorkerServicificationEnabled())
+ return;
+
+ // Make a window.
+ ServiceWorkerProviderHost* provider_host1 =
+ CreateProviderHost(GURL("https://www.example.com/example1.html"));
+
+ // Make an active version.
+ auto version1 = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration1_.get(), GURL("https://www.example.com/sw.js"),
+ 1 /* version_id */, helper_->context()->AsWeakPtr());
+ version1->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration1_->SetActiveVersion(version1);
+
+ // Make the registration findable via storage functions. This allows
+ // the service worker to start, which will be needed later.
+ base::RunLoop loop;
+ helper_->context()->storage()->LazyInitializeForTest(loop.QuitClosure());
+ loop.Run();
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records;
+ records.push_back(WriteToDiskCacheSync(
+ helper_->context()->storage(), version1->script_url(),
+ helper_->context()->storage()->NewResourceId(), {} /* headers */,
+ "I'm the body", "I'm the meta data"));
+ version1->script_cache_map()->SetResources(records);
+ version1->SetMainScriptHttpResponseInfo(
+ EmbeddedWorkerTestHelper::CreateHttpResponseInfo());
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ helper_->context()->storage()->StoreRegistration(
+ registration1_.get(), version1.get(),
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
+
+ // Make the active worker the controller and give it an ongoing request. This
+ // way when a waiting worker calls SkipWaiting(), activation won't trigger
+ // until we're ready.
+ provider_host1->AssociateRegistration(registration1_.get(), false);
+ EXPECT_EQ(version1.get(), provider_host1->controller());
+ // The worker must be running to have a request.
+ version1->StartWorker(ServiceWorkerMetrics::EventType::PUSH,
+ base::DoNothing());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version1->running_status());
+ int request = version1->StartRequest(ServiceWorkerMetrics::EventType::PUSH,
+ base::DoNothing());
+
+ // Make the waiting worker and have it call SkipWaiting().
+ auto version2 = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration1_.get(), GURL("https://www.example.com/sw.js"),
+ 2 /* version_id */, helper_->context()->AsWeakPtr());
+ version2->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version2->SetStatus(ServiceWorkerVersion::INSTALLED);
+ registration1_->SetWaitingVersion(version2);
+ version2->SkipWaiting(base::DoNothing());
+
+ // Finish the request. Activation won't yet occur until as
+ // |idle_time_fired_in_renderer_| isn't true.
+ version1->FinishRequest(request, true, base::Time::Now());
+
+ // Destroy the provider host. This triggers activation, and since
+ // SkipWaiting() was called, the provider host is in danger
+ // of receiving an OnSkippedWaiting() call during destruction.
+ ASSERT_TRUE(remote_endpoints_.back().host_ptr()->is_bound());
+ remote_endpoints_.back().host_ptr()->reset();
+ base::RunLoop().RunUntilIdle();
+
+ // No crash should occur, and the new version should be the active
+ // one.
+ EXPECT_EQ(version2.get(), registration1_->active_version());
+ EXPECT_FALSE(version2->HasControllee());
+}
+
+// Tests that the service worker involved with a navigation (via
+// AddServiceWorkerToUpdate) is updated when the host for the navigation is
+// destroyed.
+TEST_P(ServiceWorkerProviderHostTest, UpdateServiceWorkerOnDestruction) {
+ // This code path only is used in S13nSW.
+ if (!IsServiceWorkerServicificationEnabled())
+ return;
+
+ // Make a window.
+ ServiceWorkerProviderHost* host =
+ CreateProviderHost(GURL("https://www.example.com/example.html"));
+
+ // Make an active version.
+ auto version1 = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration1_.get(), GURL("https://www.example.com/sw.js"),
+ 1 /* version_id */, helper_->context()->AsWeakPtr());
+ version1->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration1_->SetActiveVersion(version1);
+
+ auto version2 = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration2_.get(), GURL("https://www.example.com/sw.js"),
+ 2 /* version_id */, helper_->context()->AsWeakPtr());
+ version2->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version2->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration2_->SetActiveVersion(version1);
+
+ host->AddServiceWorkerToUpdate(version1);
+ host->AddServiceWorkerToUpdate(version2);
+ ExpectUpdateIsNotScheduled(version1.get());
+ ExpectUpdateIsNotScheduled(version2.get());
+
+ // Destroy the provider host.
+ ASSERT_TRUE(remote_endpoints_.back().host_ptr()->is_bound());
+ remote_endpoints_.back().host_ptr()->reset();
+ base::RunLoop().RunUntilIdle();
+
+ // The provider host's destructor should have scheduled the update.
+ ExpectUpdateIsScheduled(version1.get());
+ ExpectUpdateIsScheduled(version2.get());
+}
+
+// Tests that the service worker involved with a navigation is updated when the
+// host receives a HintToUpdateServiceWorker message.
+TEST_P(ServiceWorkerProviderHostTest, HintToUpdateServiceWorker) {
+ // This code path only is used in S13nSW.
+ if (!IsServiceWorkerServicificationEnabled())
+ return;
+
+ // Make an active version.
+ auto version1 = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration1_.get(), GURL("https://www.example.com/sw.js"),
+ 1 /* version_id */, helper_->context()->AsWeakPtr());
+ version1->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration1_->SetActiveVersion(version1);
+
+ // Make a window.
+ ServiceWorkerProviderHost* host =
+ CreateProviderHost(GURL("https://www.example.com/example.html"));
+
+ // Mark the service worker as needing update. Update should not be scheduled
+ // yet.
+ host->AddServiceWorkerToUpdate(version1);
+ ExpectUpdateIsNotScheduled(version1.get());
+ EXPECT_TRUE(HasVersionToUpdate(host));
+
+ // Send the hint from the renderer. Update should be scheduled.
+ mojom::ServiceWorkerContainerHostAssociatedPtr* host_ptr =
+ remote_endpoints_.back().host_ptr();
+ (*host_ptr)->HintToUpdateServiceWorker();
+ base::RunLoop().RunUntilIdle();
+ ExpectUpdateIsScheduled(version1.get());
+ EXPECT_FALSE(HasVersionToUpdate(host));
+}
+
+// Tests that the host receives a HintToUpdateServiceWorker message but
+// there was no service worker at main resource request time. This
+// can happen due to claim().
+TEST_P(ServiceWorkerProviderHostTest,
+ HintToUpdateServiceWorkerButNoVersionToUpdate) {
+ // This code path only is used in S13nSW.
+ if (!IsServiceWorkerServicificationEnabled())
+ return;
+
+ // Make a window.
+ ServiceWorkerProviderHost* host =
+ CreateProviderHost(GURL("https://www.example.com/example.html"));
+
+ // Make an active version.
+ auto version1 = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration1_.get(), GURL("https://www.example.com/sw.js"),
+ 1 /* version_id */, helper_->context()->AsWeakPtr());
+ version1->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration1_->SetActiveVersion(version1);
+
+ // Pretend the registration gets associated after the main
+ // resource request, so AddServiceWorkerToUpdate() is not called.
+
+ ExpectUpdateIsNotScheduled(version1.get());
+ EXPECT_FALSE(HasVersionToUpdate(host));
+
+ // Send the hint from the renderer. Update should not be scheduled, since
+ // AddServiceWorkerToUpdate() was not called.
+ mojom::ServiceWorkerContainerHostAssociatedPtr* host_ptr =
+ remote_endpoints_.back().host_ptr();
+ (*host_ptr)->HintToUpdateServiceWorker();
+ base::RunLoop().RunUntilIdle();
+ ExpectUpdateIsNotScheduled(version1.get());
+ EXPECT_FALSE(HasVersionToUpdate(host));
+}
+
+TEST_P(ServiceWorkerProviderHostTest, HintToUpdateServiceWorkerMultiple) {
+ // This code path only is used in S13nSW.
+ if (!IsServiceWorkerServicificationEnabled())
+ return;
+
+ // Make active versions.
+ auto version1 = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration1_.get(), GURL("https://www.example.com/sw.js"),
+ 1 /* version_id */, helper_->context()->AsWeakPtr());
+ version1->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration1_->SetActiveVersion(version1);
+
+ auto version2 = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration2_.get(), GURL("https://www.example.com/sw.js"),
+ 2 /* version_id */, helper_->context()->AsWeakPtr());
+ version2->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version2->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration2_->SetActiveVersion(version1);
+
+ auto version3 = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration3_.get(), GURL("https://other.example.com/sw.js"),
+ 3 /* version_id */, helper_->context()->AsWeakPtr());
+ version3->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version3->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration3_->SetActiveVersion(version1);
+
+ // Make a window.
+ ServiceWorkerProviderHost* host =
+ CreateProviderHost(GURL("https://www.example.com/example.html"));
+
+ // Mark the service worker as needing update. Update should not be scheduled
+ // yet.
+ host->AddServiceWorkerToUpdate(version1);
+ host->AddServiceWorkerToUpdate(version2);
+ host->AddServiceWorkerToUpdate(version3);
+ ExpectUpdateIsNotScheduled(version1.get());
+ ExpectUpdateIsNotScheduled(version2.get());
+ ExpectUpdateIsNotScheduled(version3.get());
+ EXPECT_TRUE(HasVersionToUpdate(host));
+
+ // Pretend another page also used version3.
+ version3->IncrementPendingUpdateHintCount();
+
+ // Send the hint from the renderer. Update should be scheduled except for
+ // |version3| as it's being used by another page.
+ mojom::ServiceWorkerContainerHostAssociatedPtr* host_ptr =
+ remote_endpoints_.back().host_ptr();
+ (*host_ptr)->HintToUpdateServiceWorker();
+ base::RunLoop().RunUntilIdle();
+ ExpectUpdateIsScheduled(version1.get());
+ ExpectUpdateIsScheduled(version2.get());
+ ExpectUpdateIsNotScheduled(version3.get());
+ EXPECT_FALSE(HasVersionToUpdate(host));
+
+ // Pretend the other page also finished for version3.
+ version3->DecrementPendingUpdateHintCount();
+ ExpectUpdateIsScheduled(version3.get());
+}
+
+INSTANTIATE_TEST_CASE_P(IsServiceWorkerServicificationEnabled,
+ ServiceWorkerProviderHostTest,
+ ::testing::Bool(););
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc b/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc
index e90ad63f3f0..04c4f20c2aa 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
@@ -201,7 +201,8 @@ void ServiceWorkerReadFromCacheJob::SetupRangeResponse(int resource_size) {
void ServiceWorkerReadFromCacheJob::Done(const net::URLRequestStatus& status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!status.is_success()) {
- version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_DISK_CACHE);
+ version_->SetStartWorkerStatusCode(
+ blink::ServiceWorkerStatusCode::kErrorDiskCache);
// TODO(falken): Retry before evicting.
if (context_) {
ServiceWorkerRegistration* registration =
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 85f49357f2e..4fdb26ad89c 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
@@ -39,17 +39,17 @@ const int64_t kImportedScriptResourceId = 11;
const int64_t kNonExistentResourceId = 12;
const int64_t kResourceSize = 100;
-void DidStoreRegistration(ServiceWorkerStatusCode* status_out,
+void DidStoreRegistration(blink::ServiceWorkerStatusCode* status_out,
const base::Closure& quit_closure,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
*status_out = status;
quit_closure.Run();
}
void DidFindRegistration(
- ServiceWorkerStatusCode* status_out,
+ blink::ServiceWorkerStatusCode* status_out,
const base::Closure& quit_closure,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
*status_out = status;
quit_closure.Run();
@@ -103,7 +103,7 @@ class ServiceWorkerReadFromCacheJobTest : public testing::Test {
version_->script_cache_map()->SetResources(resources);
version_->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
- ASSERT_EQ(SERVICE_WORKER_OK, StoreRegistration());
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, StoreRegistration());
ASSERT_TRUE(WriteResource(main_script_.resource_id));
ASSERT_TRUE(WriteResource(imported_script_.resource_id));
}
@@ -142,9 +142,10 @@ class ServiceWorkerReadFromCacheJobTest : public testing::Test {
return true;
}
- ServiceWorkerStatusCode StoreRegistration() {
+ blink::ServiceWorkerStatusCode StoreRegistration() {
base::RunLoop run_loop;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
context()->storage()->StoreRegistration(
registration_.get(), version_.get(),
base::BindOnce(&DidStoreRegistration, &status, run_loop.QuitClosure()));
@@ -152,9 +153,10 @@ class ServiceWorkerReadFromCacheJobTest : public testing::Test {
return status;
}
- ServiceWorkerStatusCode FindRegistration() {
+ blink::ServiceWorkerStatusCode FindRegistration() {
base::RunLoop run_loop;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
context()->storage()->FindRegistrationForId(
registration_->id(), registration_->pattern().GetOrigin(),
base::BindOnce(&DidFindRegistration, &status, run_loop.QuitClosure()));
@@ -168,8 +170,8 @@ class ServiceWorkerReadFromCacheJobTest : public testing::Test {
base::RunLoop().RunUntilIdle();
}
- ServiceWorkerStatusCode DeduceStartWorkerFailureReason(
- ServiceWorkerStatusCode default_code) {
+ blink::ServiceWorkerStatusCode DeduceStartWorkerFailureReason(
+ blink::ServiceWorkerStatusCode default_code) {
return version_->DeduceStartWorkerFailureReason(default_code);
}
@@ -207,8 +209,9 @@ TEST_F(ServiceWorkerReadFromCacheJobTest, ReadMainScript) {
EXPECT_EQ(net::URLRequestStatus::SUCCESS, request->status().status());
EXPECT_EQ(0, request->status().error());
- EXPECT_EQ(SERVICE_WORKER_OK,
- DeduceStartWorkerFailureReason(SERVICE_WORKER_OK));
+ EXPECT_EQ(
+ blink::ServiceWorkerStatusCode::kOk,
+ DeduceStartWorkerFailureReason(blink::ServiceWorkerStatusCode::kOk));
}
TEST_F(ServiceWorkerReadFromCacheJobTest, ReadImportedScript) {
@@ -225,12 +228,13 @@ TEST_F(ServiceWorkerReadFromCacheJobTest, ReadImportedScript) {
EXPECT_EQ(net::URLRequestStatus::SUCCESS, request->status().status());
EXPECT_EQ(0, request->status().error());
- EXPECT_EQ(SERVICE_WORKER_OK,
- DeduceStartWorkerFailureReason(SERVICE_WORKER_OK));
+ EXPECT_EQ(
+ blink::ServiceWorkerStatusCode::kOk,
+ DeduceStartWorkerFailureReason(blink::ServiceWorkerStatusCode::kOk));
}
TEST_F(ServiceWorkerReadFromCacheJobTest, ResourceNotFound) {
- ASSERT_EQ(SERVICE_WORKER_OK, FindRegistration());
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, FindRegistration());
// Populate the script cache map with a nonexistent resource.
ServiceWorkerScriptCacheMap* script_cache_map = version_->script_cache_map();
@@ -257,12 +261,13 @@ TEST_F(ServiceWorkerReadFromCacheJobTest, ResourceNotFound) {
EXPECT_EQ(net::URLRequestStatus::FAILED, request->status().status());
EXPECT_EQ(net::ERR_CACHE_MISS, request->status().error());
- EXPECT_EQ(SERVICE_WORKER_ERROR_DISK_CACHE,
- DeduceStartWorkerFailureReason(SERVICE_WORKER_OK));
+ EXPECT_EQ(
+ blink::ServiceWorkerStatusCode::kErrorDiskCache,
+ DeduceStartWorkerFailureReason(blink::ServiceWorkerStatusCode::kOk));
// The version should be doomed by the job.
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, FindRegistration());
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound, FindRegistration());
}
} // namespace content
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 69d7b3154e2..81b62c81e86 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_register_job.cc
@@ -10,21 +10,23 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_job_coordinator.h"
#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_type_converters.h"
+#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "content/common/service_worker/service_worker.mojom.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"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "net/base/net_errors.h"
+#include "third_party/blink/public/common/service_worker/service_worker_type_converters.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
namespace content {
@@ -46,8 +48,7 @@ ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
should_uninstall_on_failure_(false),
force_bypass_cache_(false),
skip_script_comparison_(false),
- promise_resolved_status_(SERVICE_WORKER_OK),
- observer_(this),
+ promise_resolved_status_(blink::ServiceWorkerStatusCode::kOk),
weak_factory_(this) {}
ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
@@ -65,8 +66,7 @@ ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
should_uninstall_on_failure_(false),
force_bypass_cache_(force_bypass_cache),
skip_script_comparison_(skip_script_comparison),
- promise_resolved_status_(SERVICE_WORKER_OK),
- observer_(this),
+ promise_resolved_status_(blink::ServiceWorkerStatusCode::kOk),
weak_factory_(this) {
internal_.registration = registration;
}
@@ -113,7 +113,8 @@ void ServiceWorkerRegisterJob::StartImpl() {
if (registration.get())
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(std::move(next_step), SERVICE_WORKER_OK, registration));
+ base::BindOnce(std::move(next_step),
+ blink::ServiceWorkerStatusCode::kOk, registration));
else
context_->storage()->FindRegistrationForPattern(pattern_,
std::move(next_step));
@@ -121,7 +122,7 @@ void ServiceWorkerRegisterJob::StartImpl() {
void ServiceWorkerRegisterJob::Abort() {
SetPhase(ABORT);
- CompleteInternal(SERVICE_WORKER_ERROR_ABORT, std::string());
+ CompleteInternal(blink::ServiceWorkerStatusCode::kErrorAbort, std::string());
// Don't have to call FinishJob() because the caller takes care of removing
// the jobs from the queue.
}
@@ -145,7 +146,8 @@ RegistrationJobType ServiceWorkerRegisterJob::GetType() const {
void ServiceWorkerRegisterJob::DoomInstallingWorker() {
doom_installing_worker_ = true;
if (phase_ == INSTALL)
- Complete(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED, std::string());
+ Complete(blink::ServiceWorkerStatusCode::kErrorInstallWorkerFailed,
+ std::string());
}
ServiceWorkerRegisterJob::Internal::Internal() {}
@@ -209,10 +211,11 @@ void ServiceWorkerRegisterJob::SetPhase(Phase phase) {
// "Let registration be the result of running the [[GetRegistration]] algorithm.
// Throughout this file, comments in quotes are excerpts from the spec.
void ServiceWorkerRegisterJob::ContinueWithRegistration(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> existing_registration) {
DCHECK_EQ(REGISTRATION_JOB, job_type_);
- if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kErrorNotFound &&
+ status != blink::ServiceWorkerStatusCode::kOk) {
Complete(status);
return;
}
@@ -251,23 +254,23 @@ void ServiceWorkerRegisterJob::ContinueWithRegistration(
}
void ServiceWorkerRegisterJob::ContinueWithUpdate(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> existing_registration) {
DCHECK_EQ(UPDATE_JOB, job_type_);
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
Complete(status);
return;
}
if (existing_registration.get() != registration()) {
- Complete(SERVICE_WORKER_ERROR_NOT_FOUND);
+ Complete(blink::ServiceWorkerStatusCode::kErrorNotFound);
return;
}
// A previous job may have unregistered this registration.
if (registration()->is_uninstalling() ||
!registration()->GetNewestVersion()) {
- Complete(SERVICE_WORKER_ERROR_NOT_FOUND);
+ Complete(blink::ServiceWorkerStatusCode::kErrorNotFound);
return;
}
@@ -287,7 +290,7 @@ void ServiceWorkerRegisterJob::RegisterAndContinue() {
int64_t registration_id = context_->storage()->NewRegistrationId();
if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId) {
- Complete(SERVICE_WORKER_ERROR_ABORT);
+ Complete(blink::ServiceWorkerStatusCode::kErrorAbort);
return;
}
@@ -301,8 +304,8 @@ void ServiceWorkerRegisterJob::RegisterAndContinue() {
void ServiceWorkerRegisterJob::ContinueWithUninstallingRegistration(
scoped_refptr<ServiceWorkerRegistration> existing_registration,
- ServiceWorkerStatusCode status) {
- if (status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode status) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
Complete(status);
return;
}
@@ -313,8 +316,8 @@ void ServiceWorkerRegisterJob::ContinueWithUninstallingRegistration(
void ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl(
scoped_refptr<ServiceWorkerRegistration> existing_registration,
- ServiceWorkerStatusCode status) {
- if (status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode status) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
Complete(status);
return;
}
@@ -331,7 +334,7 @@ void ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl(
DCHECK(!existing_registration->installing_version());
if (existing_registration->active_version()) {
ResolvePromise(status, std::string(), existing_registration.get());
- Complete(SERVICE_WORKER_OK);
+ Complete(blink::ServiceWorkerStatusCode::kOk);
return;
}
@@ -347,7 +350,7 @@ void ServiceWorkerRegisterJob::UpdateAndContinue() {
int64_t version_id = context_->storage()->NewVersionId();
if (version_id == blink::mojom::kInvalidServiceWorkerVersionId) {
- Complete(SERVICE_WORKER_ERROR_ABORT);
+ Complete(blink::ServiceWorkerStatusCode::kErrorAbort);
return;
}
@@ -357,10 +360,9 @@ void ServiceWorkerRegisterJob::UpdateAndContinue() {
version_id, context_));
new_version()->set_force_bypass_cache_for_scripts(force_bypass_cache_);
if (registration()->has_installed_version() && !skip_script_comparison_) {
- new_version()->set_pause_after_download(true);
- observer_.Add(new_version()->embedded_worker());
- } else {
- new_version()->set_pause_after_download(false);
+ new_version()->SetToPauseAfterDownload(
+ base::BindOnce(&ServiceWorkerRegisterJob::OnPausedAfterDownload,
+ weak_factory_.GetWeakPtr()));
}
new_version()->StartWorker(
ServiceWorkerMetrics::EventType::INSTALL,
@@ -369,17 +371,17 @@ void ServiceWorkerRegisterJob::UpdateAndContinue() {
}
void ServiceWorkerRegisterJob::OnStartWorkerFinished(
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
BumpLastUpdateCheckTimeIfNeeded();
- if (status == SERVICE_WORKER_OK) {
+ if (status == blink::ServiceWorkerStatusCode::kOk) {
InstallAndContinue();
return;
}
// "If serviceWorker fails to start up..." then reject the promise with an
// error and abort.
- if (status == SERVICE_WORKER_ERROR_TIMEOUT) {
+ if (status == blink::ServiceWorkerStatusCode::kErrorTimeout) {
Complete(status, "Timed out while trying to start the Service Worker.");
return;
}
@@ -408,7 +410,8 @@ void ServiceWorkerRegisterJob::InstallAndContinue() {
new_version()->SetStatus(ServiceWorkerVersion::INSTALLING);
// "Resolve registrationPromise with registration."
- ResolvePromise(SERVICE_WORKER_OK, std::string(), registration());
+ ResolvePromise(blink::ServiceWorkerStatusCode::kOk, std::string(),
+ registration());
// "Fire a simple event named updatefound..."
registration()->NotifyUpdateFound();
@@ -423,12 +426,12 @@ void ServiceWorkerRegisterJob::InstallAndContinue() {
// only do so after we've started the worker and dispatched the install
// event, as those are atomic substeps in the [[Install]] algorithm.
if (doom_installing_worker_)
- Complete(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED);
+ Complete(blink::ServiceWorkerStatusCode::kErrorInstallWorkerFailed);
}
void ServiceWorkerRegisterJob::DispatchInstallEvent(
- ServiceWorkerStatusCode start_worker_status) {
- if (start_worker_status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode start_worker_status) {
+ if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
OnInstallFailed(start_worker_status);
return;
}
@@ -442,7 +445,7 @@ void ServiceWorkerRegisterJob::DispatchInstallEvent(
base::BindOnce(&ServiceWorkerRegisterJob::OnInstallFailed,
weak_factory_.GetWeakPtr()));
- new_version()->event_dispatcher()->DispatchInstallEvent(
+ new_version()->endpoint()->DispatchInstallEvent(
base::BindOnce(&ServiceWorkerRegisterJob::OnInstallFinished,
weak_factory_.GetWeakPtr(), request_id));
}
@@ -457,11 +460,13 @@ void ServiceWorkerRegisterJob::OnInstallFinished(
new_version()->FinishRequest(request_id, succeeded, dispatch_event_time);
if (!succeeded) {
- OnInstallFailed(mojo::ConvertTo<ServiceWorkerStatusCode>(event_status));
+ OnInstallFailed(
+ mojo::ConvertTo<blink::ServiceWorkerStatusCode>(event_status));
return;
}
- ServiceWorkerMetrics::RecordInstallEventStatus(SERVICE_WORKER_OK);
+ ServiceWorkerMetrics::RecordInstallEventStatus(
+ blink::ServiceWorkerStatusCode::kOk);
SetPhase(STORE);
DCHECK(!registration()->last_update_check().is_null());
@@ -475,17 +480,19 @@ void ServiceWorkerRegisterJob::OnInstallFinished(
weak_factory_.GetWeakPtr()));
}
-void ServiceWorkerRegisterJob::OnInstallFailed(ServiceWorkerStatusCode status) {
+void ServiceWorkerRegisterJob::OnInstallFailed(
+ blink::ServiceWorkerStatusCode status) {
ServiceWorkerMetrics::RecordInstallEventStatus(status);
- DCHECK_NE(status, SERVICE_WORKER_OK)
- << "OnInstallFailed should not handle SERVICE_WORKER_OK";
+ DCHECK_NE(status, blink::ServiceWorkerStatusCode::kOk)
+ << "OnInstallFailed should not handle "
+ "blink::ServiceWorkerStatusCode::kOk";
Complete(status, std::string("ServiceWorker failed to install: ") +
- ServiceWorkerStatusToString(status));
+ blink::ServiceWorkerStatusToString(status));
}
void ServiceWorkerRegisterJob::OnStoreRegistrationComplete(
- ServiceWorkerStatusCode status) {
- if (status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode status) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
Complete(status);
return;
}
@@ -515,36 +522,35 @@ void ServiceWorkerRegisterJob::OnStoreRegistrationComplete(
// client is using registration as their service worker registration."
registration()->ActivateWaitingVersionWhenReady();
- Complete(SERVICE_WORKER_OK);
+ Complete(blink::ServiceWorkerStatusCode::kOk);
}
-void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) {
+void ServiceWorkerRegisterJob::Complete(blink::ServiceWorkerStatusCode status) {
Complete(status, std::string());
}
-void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status,
+void ServiceWorkerRegisterJob::Complete(blink::ServiceWorkerStatusCode status,
const std::string& status_message) {
CompleteInternal(status, status_message);
context_->job_coordinator()->FinishJob(pattern_, this);
}
void ServiceWorkerRegisterJob::CompleteInternal(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message) {
SetPhase(COMPLETE);
- if (new_version()) {
- new_version()->set_pause_after_download(false);
- observer_.RemoveAll();
- }
+ if (new_version())
+ new_version()->SetToNotPauseAfterDownload();
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
if (registration()) {
if (should_uninstall_on_failure_)
registration()->ClearWhenReady();
if (new_version()) {
- if (status == SERVICE_WORKER_ERROR_EXISTS)
- new_version()->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS);
+ if (status == blink::ServiceWorkerStatusCode::kErrorExists)
+ new_version()->SetStartWorkerStatusCode(
+ blink::ServiceWorkerStatusCode::kErrorExists);
else
new_version()->ReportError(status, status_message);
registration()->UnsetVersion(new_version());
@@ -571,7 +577,7 @@ void ServiceWorkerRegisterJob::CompleteInternal(
}
void ServiceWorkerRegisterJob::ResolvePromise(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
ServiceWorkerRegistration* registration) {
DCHECK(!is_promise_resolved_);
@@ -602,20 +608,27 @@ void ServiceWorkerRegisterJob::AddRegistrationToMatchingProviderHosts(
}
}
-void ServiceWorkerRegisterJob::OnScriptLoaded() {
- DCHECK(new_version()->pause_after_download());
- new_version()->set_pause_after_download(false);
+void ServiceWorkerRegisterJob::OnPausedAfterDownload() {
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.
+ // OnPausedAfterDownload() 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,
+ ResolvePromise(blink::ServiceWorkerStatusCode::kOk, std::string(),
+ registration());
+ // Note: Complete() destroys this job and hence risks destroying
+ // |new_version()| inside this callback, which is impolite and dangerous.
+ // But most of this class operates this way, and introducing asynchronicity
+ // here can potentially create bad interactions with other callbacks into
+ // this class, so continue the pattern here. This code path should be
+ // removed anyway when the byte-to-byte update check is moved outside of
+ // worker startup.
+ Complete(blink::ServiceWorkerStatusCode::kErrorExists,
"The updated worker is identical to the incumbent.");
return;
}
@@ -623,16 +636,6 @@ void ServiceWorkerRegisterJob::OnScriptLoaded() {
new_version()->embedded_worker()->ResumeAfterDownload();
}
-void ServiceWorkerRegisterJob::OnDestroyed() {
- // The version's EmbeddedWorkerInstance is getting destructed, so
- // remove the observer to avoid a use-after-free. We expect to continue when
- // the StartWorker() callback is called with failure.
- // TODO(crbug.com/855852): Remove the EmbeddedWorkerInstance::Listener
- // interface and have this class listen to ServiceWorkerVersion directly.
- if (observer_.IsObserving(new_version()->embedded_worker()))
- observer_.Remove(new_version()->embedded_worker());
-}
-
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
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 29cd3f2e423..53814919752 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.h
+++ b/chromium/content/browser/service_worker/service_worker_register_job.h
@@ -10,12 +10,10 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/scoped_observer.h"
#include "base/time/time.h"
-#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/service_worker_register_job_base.h"
#include "content/browser/service_worker/service_worker_registration.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
#include "url/gurl.h"
@@ -36,10 +34,9 @@ namespace content {
// - waiting for older ServiceWorkerVersions to deactivate
// - designating the new version to be the 'active' version
// - updating storage
-class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase,
- public EmbeddedWorkerInstance::Listener {
+class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
public:
- typedef base::OnceCallback<void(ServiceWorkerStatusCode status,
+ typedef base::OnceCallback<void(blink::ServiceWorkerStatusCode status,
const std::string& status_message,
ServiceWorkerRegistration* registration)>
RegistrationCallback;
@@ -103,44 +100,42 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase,
void StartImpl();
void ContinueWithRegistration(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void ContinueWithUpdate(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void RegisterAndContinue();
void ContinueWithUninstallingRegistration(
scoped_refptr<ServiceWorkerRegistration> existing_registration,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void ContinueWithRegistrationForSameScriptUrl(
scoped_refptr<ServiceWorkerRegistration> existing_registration,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
void UpdateAndContinue();
- void OnStartWorkerFinished(ServiceWorkerStatusCode status);
- void OnStoreRegistrationComplete(ServiceWorkerStatusCode status);
+ void OnStartWorkerFinished(blink::ServiceWorkerStatusCode status);
+ void OnStoreRegistrationComplete(blink::ServiceWorkerStatusCode status);
void InstallAndContinue();
- void DispatchInstallEvent(ServiceWorkerStatusCode start_worker_status);
+ void DispatchInstallEvent(blink::ServiceWorkerStatusCode start_worker_status);
void OnInstallFinished(
int request_id,
blink::mojom::ServiceWorkerEventStatus event_status,
bool has_fetch_handler,
base::Time dispatch_event_time);
- void OnInstallFailed(ServiceWorkerStatusCode status);
- void Complete(ServiceWorkerStatusCode status);
- void Complete(ServiceWorkerStatusCode status,
+ void OnInstallFailed(blink::ServiceWorkerStatusCode status);
+ void Complete(blink::ServiceWorkerStatusCode status);
+ void Complete(blink::ServiceWorkerStatusCode status,
const std::string& status_message);
- void CompleteInternal(ServiceWorkerStatusCode status,
+ void CompleteInternal(blink::ServiceWorkerStatusCode status,
const std::string& status_message);
- void ResolvePromise(ServiceWorkerStatusCode status,
+ void ResolvePromise(blink::ServiceWorkerStatusCode status,
const std::string& status_message,
ServiceWorkerRegistration* registration);
void AddRegistrationToMatchingProviderHosts(
ServiceWorkerRegistration* registration);
- // EmbeddedWorkerInstance::Listener implementation:
- void OnScriptLoaded() override;
- void OnDestroyed() override;
+ void OnPausedAfterDownload();
void BumpLastUpdateCheckTimeIfNeeded();
@@ -159,11 +154,10 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase,
bool should_uninstall_on_failure_;
bool force_bypass_cache_;
bool skip_script_comparison_;
- ServiceWorkerStatusCode promise_resolved_status_;
+ blink::ServiceWorkerStatusCode promise_resolved_status_;
std::string promise_resolved_status_message_;
scoped_refptr<ServiceWorkerRegistration> promise_resolved_registration_;
- ScopedObserver<EmbeddedWorkerInstance, EmbeddedWorkerInstance::Listener>
- observer_;
+
base::WeakPtrFactory<ServiceWorkerRegisterJob> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegisterJob);
diff --git a/chromium/content/browser/service_worker/service_worker_registration.cc b/chromium/content/browser/service_worker/service_worker_registration.cc
index 98c613109de..dec34316469 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration.cc
@@ -14,8 +14,8 @@
#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"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace content {
@@ -64,7 +64,7 @@ ServiceWorkerRegistration::~ServiceWorkerRegistration() {
if (context_)
context_->RemoveLiveRegistration(registration_id_);
if (active_version())
- active_version()->RemoveListener(this);
+ active_version()->RemoveObserver(this);
}
ServiceWorkerVersion* ServiceWorkerRegistration::GetNewestVersion() const {
@@ -126,10 +126,10 @@ void ServiceWorkerRegistration::SetActiveVersion(
if (version)
UnsetVersionInternal(version.get(), &mask);
if (active_version_)
- active_version_->RemoveListener(this);
+ active_version_->RemoveObserver(this);
active_version_ = version;
if (active_version_) {
- active_version_->AddListener(this);
+ active_version_->AddObserver(this);
active_version_->SetNavigationPreloadState(navigation_preload_state_);
}
mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION);
@@ -188,7 +188,7 @@ void ServiceWorkerRegistration::UnsetVersionInternal(
should_activate_when_ready_ = false;
mask->add(ChangedVersionAttributesMask::WAITING_VERSION);
} else if (active_version_.get() == version) {
- active_version_->RemoveListener(this);
+ active_version_->RemoveObserver(this);
active_version_ = nullptr;
mask->add(ChangedVersionAttributesMask::ACTIVE_VERSION);
}
@@ -212,12 +212,12 @@ void ServiceWorkerRegistration::ActivateWaitingVersionWhenReady() {
}
if (IsLameDuckActiveVersion()) {
- if (ServiceWorkerUtils::IsServicificationEnabled() &&
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
active_version()->running_status() == EmbeddedWorkerStatus::RUNNING) {
// If the waiting worker is ready and the active worker needs to be
// swapped out, ask the active worker to trigger idle timer as soon as
// possible.
- active_version()->event_dispatcher()->SetIdleTimerDelayToZero();
+ active_version()->endpoint()->SetIdleTimerDelayToZero();
}
StartLameDuckTimer();
}
@@ -260,7 +260,7 @@ void ServiceWorkerRegistration::ClearWhenReady() {
void ServiceWorkerRegistration::AbortPendingClear(StatusCallback callback) {
DCHECK(context_);
if (!is_uninstalling()) {
- std::move(callback).Run(SERVICE_WORKER_OK);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk);
return;
}
is_uninstalling_ = false;
@@ -294,13 +294,13 @@ void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) {
}
if (IsLameDuckActiveVersion()) {
- if (ServiceWorkerUtils::IsServicificationEnabled() &&
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
should_activate_when_ready_ &&
active_version()->running_status() == EmbeddedWorkerStatus::RUNNING) {
// If the waiting worker is ready and the active worker needs to be
// swapped out, ask the active worker to trigger idle timer as soon as
// possible.
- active_version()->event_dispatcher()->SetIdleTimerDelayToZero();
+ active_version()->endpoint()->SetIdleTimerDelayToZero();
}
StartLameDuckTimer();
}
@@ -497,13 +497,14 @@ void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback(
void ServiceWorkerRegistration::DispatchActivateEvent(
scoped_refptr<ServiceWorkerVersion> activating_version,
- ServiceWorkerStatusCode start_worker_status) {
- if (start_worker_status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode start_worker_status) {
+ if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
OnActivateEventFinished(activating_version, start_worker_status);
return;
}
if (activating_version != active_version()) {
- OnActivateEventFinished(activating_version, SERVICE_WORKER_ERROR_FAILED);
+ OnActivateEventFinished(activating_version,
+ blink::ServiceWorkerStatusCode::kErrorFailed);
return;
}
@@ -514,13 +515,13 @@ void ServiceWorkerRegistration::DispatchActivateEvent(
ServiceWorkerMetrics::EventType::ACTIVATE,
base::BindOnce(&ServiceWorkerRegistration::OnActivateEventFinished, this,
activating_version));
- activating_version->event_dispatcher()->DispatchActivateEvent(
+ activating_version->endpoint()->DispatchActivateEvent(
activating_version->CreateSimpleEventCallback(request_id));
}
void ServiceWorkerRegistration::OnActivateEventFinished(
scoped_refptr<ServiceWorkerVersion> activating_version,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
// Activate is prone to failing due to shutdown, because it's triggered when
// tabs close.
bool is_shutdown =
@@ -537,7 +538,7 @@ void ServiceWorkerRegistration::OnActivateEventFinished(
// it should still be activated. However, if the failure occurred during
// shutdown, ignore it to give the worker another chance the next time the
// browser starts up.
- if (is_shutdown && status != SERVICE_WORKER_OK)
+ if (is_shutdown && status != blink::ServiceWorkerStatusCode::kOk)
return;
// "Run the Update State algorithm passing registration's active worker and
@@ -547,7 +548,7 @@ void ServiceWorkerRegistration::OnActivateEventFinished(
}
void ServiceWorkerRegistration::OnDeleteFinished(
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
for (auto& listener : listeners_)
listener.OnRegistrationDeleted(this);
}
@@ -581,7 +582,7 @@ void ServiceWorkerRegistration::Clear() {
}
if (active_version_.get()) {
versions_to_doom.push_back(active_version_);
- active_version_->RemoveListener(this);
+ active_version_->RemoveObserver(this);
active_version_ = nullptr;
mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION);
}
@@ -603,9 +604,9 @@ void ServiceWorkerRegistration::Clear() {
void ServiceWorkerRegistration::OnRestoreFinished(
StatusCallback callback,
scoped_refptr<ServiceWorkerVersion> version,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
if (!context_) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort);
return;
}
context_->storage()->NotifyDoneInstallingRegistration(
diff --git a/chromium/content/browser/service_worker/service_worker_registration.h b/chromium/content/browser/service_worker/service_worker_registration.h
index 032fa94be09..e579f31c727 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.h
+++ b/chromium/content/browser/service_worker/service_worker_registration.h
@@ -36,10 +36,10 @@ class ServiceWorkerActivationTest;
// facilitate multiple controllees being associated with the same registration.
class CONTENT_EXPORT ServiceWorkerRegistration
: public base::RefCounted<ServiceWorkerRegistration>,
- public ServiceWorkerVersion::Listener {
+ public ServiceWorkerVersion::Observer {
public:
using StatusCallback =
- base::OnceCallback<void(ServiceWorkerStatusCode status)>;
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode status)>;
class CONTENT_EXPORT Listener {
public:
@@ -91,7 +91,7 @@ class CONTENT_EXPORT ServiceWorkerRegistration
// state. If you require an ACTIVATED version, use
// ServiceWorkerContextWrapper::FindReadyRegistration* to get a registration
// with such a version. Alternatively, use
- // ServiceWorkerVersion::Listener::OnVersionStateChanged to wait for the
+ // ServiceWorkerVersion::Observer::OnVersionStateChanged to wait for the
// ACTIVATING version to become ACTIVATED.
ServiceWorkerVersion* active_version() const {
return active_version_.get();
@@ -187,7 +187,7 @@ class CONTENT_EXPORT ServiceWorkerRegistration
ServiceWorkerVersion* version,
ChangedVersionAttributesMask* mask);
- // ServiceWorkerVersion::Listener override.
+ // ServiceWorkerVersion::Observer override.
void OnNoControllees(ServiceWorkerVersion* version) override;
void OnNoWork(ServiceWorkerVersion* version) override;
@@ -204,19 +204,19 @@ class CONTENT_EXPORT ServiceWorkerRegistration
scoped_refptr<ServiceWorkerVersion> activating_version);
void DispatchActivateEvent(
scoped_refptr<ServiceWorkerVersion> activating_version,
- ServiceWorkerStatusCode start_worker_status);
+ blink::ServiceWorkerStatusCode start_worker_status);
void OnActivateEventFinished(
scoped_refptr<ServiceWorkerVersion> activating_version,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
- void OnDeleteFinished(ServiceWorkerStatusCode status);
+ void OnDeleteFinished(blink::ServiceWorkerStatusCode status);
// This method corresponds to the [[ClearRegistration]] algorithm.
void Clear();
void OnRestoreFinished(StatusCallback callback,
scoped_refptr<ServiceWorkerVersion> version,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
const GURL pattern_;
blink::mojom::ServiceWorkerUpdateViaCache update_via_cache_;
diff --git a/chromium/content/browser/service_worker/service_worker_registration_object_host.cc b/chromium/content/browser/service_worker/service_worker_registration_object_host.cc
index 38ea97ec4ac..4e758bf31af 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_object_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_object_host.cc
@@ -6,7 +6,7 @@
#include "content/browser/service_worker/service_worker_consts.h"
#include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_handle.h"
+#include "content/browser/service_worker/service_worker_object_host.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "net/http/http_util.h"
@@ -17,15 +17,15 @@ namespace content {
namespace {
// Returns an object info to send over Mojo. The info must be sent immediately.
-// See ServiceWorkerHandle::CreateCompleteObjectInfoToSend() for details.
+// See ServiceWorkerObjectHost::CreateCompleteObjectInfoToSend() for details.
blink::mojom::ServiceWorkerObjectInfoPtr CreateCompleteObjectInfoToSend(
ServiceWorkerProviderHost* provider_host,
ServiceWorkerVersion* version) {
- base::WeakPtr<ServiceWorkerHandle> service_worker_handle =
- provider_host->GetOrCreateServiceWorkerHandle(version);
- if (!service_worker_handle)
+ base::WeakPtr<ServiceWorkerObjectHost> service_worker_object_host =
+ provider_host->GetOrCreateServiceWorkerObjectHost(version);
+ if (!service_worker_object_host)
return nullptr;
- return service_worker_handle->CreateCompleteObjectInfoToSend();
+ return service_worker_object_host->CreateCompleteObjectInfoToSend();
}
} // anonymous namespace
@@ -212,10 +212,10 @@ void ServiceWorkerRegistrationObjectHost::SetNavigationPreloadHeader(
void ServiceWorkerRegistrationObjectHost::UpdateComplete(
UpdateCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::string error_message;
blink::mojom::ServiceWorkerErrorType error_type;
GetServiceWorkerErrorTypeForRegistration(status, status_message,
@@ -231,8 +231,8 @@ void ServiceWorkerRegistrationObjectHost::UpdateComplete(
void ServiceWorkerRegistrationObjectHost::UnregistrationComplete(
UnregisterCallback callback,
- ServiceWorkerStatusCode status) {
- if (status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode status) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::string error_message;
blink::mojom::ServiceWorkerErrorType error_type;
GetServiceWorkerErrorTypeForRegistration(status, std::string(), &error_type,
@@ -249,8 +249,8 @@ void ServiceWorkerRegistrationObjectHost::UnregistrationComplete(
void ServiceWorkerRegistrationObjectHost::DidUpdateNavigationPreloadEnabled(
bool enable,
EnableNavigationPreloadCallback callback,
- ServiceWorkerStatusCode status) {
- if (status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode status) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(
blink::mojom::ServiceWorkerErrorType::kUnknown,
std::string(ServiceWorkerConsts::kEnableNavigationPreloadErrorPrefix) +
@@ -267,8 +267,8 @@ void ServiceWorkerRegistrationObjectHost::DidUpdateNavigationPreloadEnabled(
void ServiceWorkerRegistrationObjectHost::DidUpdateNavigationPreloadHeader(
const std::string& value,
SetNavigationPreloadHeaderCallback callback,
- ServiceWorkerStatusCode status) {
- if (status != SERVICE_WORKER_OK) {
+ blink::ServiceWorkerStatusCode status) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(
blink::mojom::ServiceWorkerErrorType::kUnknown,
std::string(
diff --git a/chromium/content/browser/service_worker/service_worker_registration_object_host.h b/chromium/content/browser/service_worker/service_worker_registration_object_host.h
index 6af91e91ccd..b96daf0cda7 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_object_host.h
+++ b/chromium/content/browser/service_worker/service_worker_registration_object_host.h
@@ -70,25 +70,25 @@ class CONTENT_EXPORT ServiceWorkerRegistrationObjectHost
// Called back from ServiceWorkerContextCore when an update is complete.
void UpdateComplete(UpdateCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id);
// Called back from ServiceWorkerContextCore when the unregistration is
// complete.
void UnregistrationComplete(UnregisterCallback callback,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// Called back from ServiceWorkerStorage when setting navigation preload is
// complete.
void DidUpdateNavigationPreloadEnabled(
bool enable,
EnableNavigationPreloadCallback callback,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// Called back from ServiceWorkerStorage when setting navigation preload
// header is complete.
void DidUpdateNavigationPreloadHeader(
const std::string& value,
SetNavigationPreloadHeaderCallback callback,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// Sets the corresponding version field to the given version or if the given
// version is nullptr, clears the field.
diff --git a/chromium/content/browser/service_worker/service_worker_registration_status.cc b/chromium/content/browser/service_worker/service_worker_registration_status.cc
index 97954034a48..c331293b639 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_status.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_status.cc
@@ -15,7 +15,7 @@ namespace content {
using blink::WebServiceWorkerError;
void GetServiceWorkerErrorTypeForRegistration(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
blink::mojom::ServiceWorkerErrorType* out_error,
std::string* out_message) {
@@ -23,58 +23,57 @@ void GetServiceWorkerErrorTypeForRegistration(
if (!status_message.empty())
*out_message = status_message;
else
- *out_message = ServiceWorkerStatusToString(status);
+ *out_message = blink::ServiceWorkerStatusToString(status);
switch (status) {
- case SERVICE_WORKER_OK:
+ case blink::ServiceWorkerStatusCode::kOk:
NOTREACHED() << "Calling this when status == OK is not allowed";
return;
- case SERVICE_WORKER_ERROR_START_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND:
- case SERVICE_WORKER_ERROR_REDUNDANT:
- case SERVICE_WORKER_ERROR_DISALLOWED:
+ case blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorInstallWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorProcessNotFound:
+ case blink::ServiceWorkerStatusCode::kErrorRedundant:
+ case blink::ServiceWorkerStatusCode::kErrorDisallowed:
*out_error = blink::mojom::ServiceWorkerErrorType::kInstall;
return;
- case SERVICE_WORKER_ERROR_NOT_FOUND:
+ case blink::ServiceWorkerStatusCode::kErrorNotFound:
*out_error = blink::mojom::ServiceWorkerErrorType::kNotFound;
return;
- case SERVICE_WORKER_ERROR_NETWORK:
+ case blink::ServiceWorkerStatusCode::kErrorNetwork:
*out_error = blink::mojom::ServiceWorkerErrorType::kNetwork;
return;
- case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED:
+ case blink::ServiceWorkerStatusCode::kErrorScriptEvaluateFailed:
*out_error = blink::mojom::ServiceWorkerErrorType::kScriptEvaluateFailed;
return;
- case SERVICE_WORKER_ERROR_SECURITY:
+ case blink::ServiceWorkerStatusCode::kErrorSecurity:
*out_error = blink::mojom::ServiceWorkerErrorType::kSecurity;
return;
- case SERVICE_WORKER_ERROR_TIMEOUT:
+ case blink::ServiceWorkerStatusCode::kErrorTimeout:
*out_error = blink::mojom::ServiceWorkerErrorType::kTimeout;
return;
- case SERVICE_WORKER_ERROR_ABORT:
+ case blink::ServiceWorkerStatusCode::kErrorAbort:
*out_error = blink::mojom::ServiceWorkerErrorType::kAbort;
return;
- case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED:
- case SERVICE_WORKER_ERROR_IPC_FAILED:
- case SERVICE_WORKER_ERROR_FAILED:
- case SERVICE_WORKER_ERROR_EXISTS:
- case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED:
- case SERVICE_WORKER_ERROR_STATE:
- case SERVICE_WORKER_ERROR_DISK_CACHE:
- case SERVICE_WORKER_ERROR_MAX_VALUE:
+ case blink::ServiceWorkerStatusCode::kErrorActivateWorkerFailed:
+ case blink::ServiceWorkerStatusCode::kErrorIpcFailed:
+ case blink::ServiceWorkerStatusCode::kErrorFailed:
+ case blink::ServiceWorkerStatusCode::kErrorExists:
+ case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
+ case blink::ServiceWorkerStatusCode::kErrorState:
+ case blink::ServiceWorkerStatusCode::kErrorDiskCache:
// Unexpected, or should have bailed out before calling this, or we don't
// have a corresponding blink error code yet.
break; // Fall through to NOTREACHED().
}
- NOTREACHED() << "Got unexpected error code: " << status << " "
- << ServiceWorkerStatusToString(status);
+ NOTREACHED() << "Got unexpected error code: " << static_cast<uint32_t>(status)
+ << " " << blink::ServiceWorkerStatusToString(status);
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_registration_status.h b/chromium/content/browser/service_worker/service_worker_registration_status.h
index b7368901770..b09c204d65d 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_status.h
+++ b/chromium/content/browser/service_worker/service_worker_registration_status.h
@@ -6,14 +6,14 @@
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_STATUS_H_
#include "base/strings/string16.h"
-#include "content/common/service_worker/service_worker_status_code.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h"
namespace content {
// This should only be called for errors, where status != OK.
void GetServiceWorkerErrorTypeForRegistration(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::string& status_message,
blink::mojom::ServiceWorkerErrorType* out_error,
std::string* out_message);
diff --git a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
index 2a7e84d67f4..35671bbced4 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -25,7 +25,7 @@
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_content_browser_client.h"
-#include "mojo/edk/embedder/embedder.h"
+#include "mojo/core/embedder/embedder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -46,8 +46,8 @@ int CreateInflightRequest(ServiceWorkerVersion* version) {
}
static void SaveStatusCallback(bool* called,
- ServiceWorkerStatusCode* out,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode* out,
+ blink::ServiceWorkerStatusCode status) {
*called = true;
*out = status;
}
@@ -270,15 +270,13 @@ TEST_F(ServiceWorkerRegistrationTest, FailedRegistrationNoCrash) {
options.scope = kScope;
auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
options, kRegistrationId, context()->AsWeakPtr());
- auto dispatcher_host = base::MakeRefCounted<ServiceWorkerDispatcherHost>(
- helper_->mock_render_process_id());
// Prepare a ServiceWorkerProviderHost.
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
std::unique_ptr<ServiceWorkerProviderHost> provider_host =
- CreateProviderHostWithDispatcherHost(
- helper_->mock_render_process_id(), 1 /* dummy provider_id */,
- context()->AsWeakPtr(), 1 /* route_id */, dispatcher_host.get(),
- &remote_endpoint);
+ CreateProviderHostForWindow(helper_->mock_render_process_id(),
+ 1 /* dummy provider_id */,
+ true /* is_parent_frame_secure */,
+ context()->AsWeakPtr(), &remote_endpoint);
auto registration_object_host =
std::make_unique<ServiceWorkerRegistrationObjectHost>(
context()->AsWeakPtr(), provider_host.get(), registration);
@@ -370,12 +368,12 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
version_1->script_cache_map()->SetResources(records_1);
version_1->SetMainScriptHttpResponseInfo(
EmbeddedWorkerTestHelper::CreateHttpResponseInfo());
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
context()->storage()->StoreRegistration(
registration_.get(), version_1.get(),
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(SERVICE_WORKER_OK, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
// Give the active version a controllee.
host_ = CreateProviderHostForWindow(
@@ -417,7 +415,7 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
}
void TearDown() override {
- registration_->active_version()->RemoveListener(registration_.get());
+ registration_->active_version()->RemoveObserver(registration_.get());
ServiceWorkerRegistrationTest::TearDown();
}
@@ -661,14 +659,14 @@ class ServiceWorkerRegistrationObjectHostTest
protected:
void SetUp() override {
ServiceWorkerRegistrationTest::SetUp();
- mojo::edk::SetDefaultProcessErrorCallback(base::AdaptCallbackForRepeating(
+ mojo::core::SetDefaultProcessErrorCallback(base::AdaptCallbackForRepeating(
base::BindOnce(&ServiceWorkerRegistrationObjectHostTest::OnMojoError,
base::Unretained(this))));
}
void TearDown() override {
- mojo::edk::SetDefaultProcessErrorCallback(
- mojo::edk::ProcessErrorCallback());
+ mojo::core::SetDefaultProcessErrorCallback(
+ mojo::core::ProcessErrorCallback());
ServiceWorkerRegistrationTest::TearDown();
}
@@ -702,19 +700,21 @@ class ServiceWorkerRegistrationObjectHostTest
return error;
}
- ServiceWorkerStatusCode FindRegistrationInStorage(int64_t registration_id,
- const GURL& scope) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ blink::ServiceWorkerStatusCode FindRegistrationInStorage(
+ int64_t registration_id,
+ const GURL& scope) {
+ base::Optional<blink::ServiceWorkerStatusCode> status;
storage()->FindRegistrationForId(
registration_id, scope,
base::AdaptCallbackForRepeating(base::BindOnce(
- [](ServiceWorkerStatusCode* out_status,
- ServiceWorkerStatusCode status,
+ [](base::Optional<blink::ServiceWorkerStatusCode>* out_status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
*out_status = status;
},
&status)));
- return status;
+ base::RunLoop().RunUntilIdle();
+ return status.value();
}
int64_t SetUpRegistration(const GURL& scope, const GURL& script_url) {
@@ -744,12 +744,13 @@ class ServiceWorkerRegistrationObjectHostTest
version->SetStatus(ServiceWorkerVersion::INSTALLING);
// Make the registration findable via storage functions.
bool called = false;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
storage()->StoreRegistration(registration.get(), version.get(),
base::AdaptCallbackForRepeating(base::BindOnce(
&SaveStatusCallback, &called, &status)));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
return registration->id();
}
@@ -759,10 +760,10 @@ class ServiceWorkerRegistrationObjectHostTest
const GURL& document_url) {
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
std::unique_ptr<ServiceWorkerProviderHost> host =
- CreateProviderHostWithDispatcherHost(
- helper_->mock_render_process_id(), provider_id,
- context()->AsWeakPtr(), 1 /* route_id */, dispatcher_host(),
- &remote_endpoint);
+ CreateProviderHostForWindow(helper_->mock_render_process_id(),
+ provider_id,
+ true /* is_parent_frame_secure */,
+ context()->AsWeakPtr(), &remote_endpoint);
host->SetDocumentUrl(document_url);
context()->AddProviderHost(std::move(host));
return remote_endpoint;
@@ -790,11 +791,6 @@ class ServiceWorkerRegistrationObjectHostTest
return registration_info;
}
- ServiceWorkerDispatcherHost* dispatcher_host() {
- return helper_->GetDispatcherHostForProcess(
- helper_->mock_render_process_id());
- }
-
void OnMojoError(const std::string& error) { bad_messages_.push_back(error); }
std::vector<std::string> bad_messages_;
@@ -902,12 +898,12 @@ TEST_F(ServiceWorkerRegistrationObjectHostTest, Unregister_Success) {
info->request = nullptr;
info->waiting->request = nullptr;
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationInStorage(registration_id, kScope));
EXPECT_EQ(blink::mojom::ServiceWorkerErrorType::kNone,
CallUnregister(registration_host_ptr.get()));
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
FindRegistrationInStorage(registration_id, kScope));
EXPECT_EQ(blink::mojom::ServiceWorkerErrorType::kNotFound,
CallUnregister(registration_host_ptr.get()));
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 379a90df55e..15033201505 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.cc
@@ -17,7 +17,6 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_url_request_job.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/resource_context.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
@@ -31,6 +30,7 @@
#include "net/url_request/url_request_interceptor.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "storage/browser/blob/blob_storage_context.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
@@ -83,22 +83,20 @@ void ServiceWorkerRequestHandler::InitializeForNavigation(
bool is_parent_frame_secure,
scoped_refptr<network::ResourceRequestBody> body,
const base::Callback<WebContents*(void)>& web_contents_getter) {
- CHECK(IsBrowserSideNavigationEnabled());
-
- // S13nServiceWorker enabled, NetworkService disabled:
- // To start the navigation, InitializeForNavigationNetworkService() is called
- // instead of this, but when that request handler falls back to network,
- // InitializeForNavigation() is called.
- // Since we already determined to fall back to network, don't create another
- // handler.
- if (ServiceWorkerUtils::IsServicificationEnabled())
- return;
-
// Only create a handler when there is a ServiceWorkerNavigationHandlerCore
// to take ownership of a pre-created SeviceWorkerProviderHost.
if (!navigation_handle_core)
return;
+ // This is the legacy path used by non-NetworkService and
+ // non-S13nServiceWorker. The NetworkService/S13nServiceWorker path is
+ // InitializeForNavigationNetworkService().
+ //
+ // This function can still be called with a null navigation_handle_core by
+ // ResourceDispatcherHostImpl::BeginNavigationRequest when S13nSW is on and
+ // NetworkService is off, so this DCHECK must be after the null check above.
+ DCHECK(!blink::ServiceWorkerUtils::IsServicificationEnabled());
+
// Create the handler even for insecure HTTP since it's used in the
// case of redirect to HTTPS.
if (!request->url().SchemeIsHTTPOrHTTPS() &&
@@ -149,7 +147,7 @@ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
bool is_parent_frame_secure,
scoped_refptr<network::ResourceRequestBody> body,
const base::Callback<WebContents*(void)>& web_contents_getter) {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
DCHECK(navigation_handle_core);
// Create the handler even for insecure HTTP since it's used in the
@@ -169,8 +167,7 @@ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
// Initialize the SWProviderHost.
base::WeakPtr<ServiceWorkerProviderHost> provider_host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
- navigation_handle_core->context_wrapper()->context()->AsWeakPtr(),
- is_parent_frame_secure, web_contents_getter);
+ context->AsWeakPtr(), is_parent_frame_secure, web_contents_getter);
std::unique_ptr<ServiceWorkerRequestHandler> handler(
provider_host->CreateRequestHandler(
@@ -192,7 +189,7 @@ std::unique_ptr<NavigationLoaderInterceptor>
ServiceWorkerRequestHandler::InitializeForSharedWorker(
const network::ResourceRequest& resource_request,
base::WeakPtr<ServiceWorkerProviderHost> host) {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
// Create the handler even for insecure HTTP since it's used in the
// case of redirect to HTTPS.
@@ -237,7 +234,7 @@ void ServiceWorkerRequestHandler::InitializeHandler(
// request handler falls back to network, InitializeHandler() is called.
// Since we already determined to fall back to network, don't create another
// handler.
- if (ServiceWorkerUtils::IsServicificationEnabled())
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
return;
// Create the handler even for insecure HTTP since it's used in the
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 1dc6fb71f4e..5ab4546ffb3 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.h
@@ -14,13 +14,13 @@
#include "base/time/time.h"
#include "content/browser/loader/navigation_loader_interceptor.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/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "net/url_request/url_request_job_factory.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace net {
class NetworkDelegate;
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc
index a49f0d0f0e2..1806fc576cd 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc
@@ -25,6 +25,7 @@
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
namespace service_worker_request_handler_unittest {
@@ -119,6 +120,11 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
const std::string& method,
bool skip_service_worker,
ResourceType resource_type) {
+ // Skip handler initialization tests when S13nServiceWorker is enabled
+ // because we don't use this path. See also comments in
+ // ServiceWorkerRequestHandler::InitializeHandler().
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
InitializeProviderHostForWindow();
std::unique_ptr<net::URLRequest> request = CreateRequest(url, method);
InitializeHandler(request.get(), skip_service_worker, resource_type);
diff --git a/chromium/content/browser/service_worker/service_worker_script_loader_factory.cc b/chromium/content/browser/service_worker/service_worker_script_loader_factory.cc
index 344db0e12f9..e90b006c0fd 100644
--- a/chromium/content/browser/service_worker/service_worker_script_loader_factory.cc
+++ b/chromium/content/browser/service_worker/service_worker_script_loader_factory.cc
@@ -10,10 +10,10 @@
#include "content/browser/service_worker/service_worker_new_script_loader.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_version.h"
-#include "content/common/service_worker/service_worker_utils.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
@@ -38,24 +38,30 @@ void ServiceWorkerScriptLoaderFactory::CreateLoaderAndStart(
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
- if (!ShouldHandleScriptRequest(resource_request)) {
- // If the request should not be handled, just do a passthrough load. This
- // needs a relaying as we use different associated message pipes.
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+ if (!CheckIfScriptRequestIsValid(resource_request)) {
// TODO(kinuko): Record the reason like what we do with netlog in
// ServiceWorkerContextRequestHandler.
- loader_factory_->CreateLoaderAndStart(
- std::move(request), routing_id, request_id, options, resource_request,
- std::move(client), traffic_annotation);
+ client->OnComplete(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
return;
}
- // If we get here, the service worker is not installed, so the script is
- // usually not yet installed. However, there is a special case when an
- // installing worker that imports the same script twice (e.g.
- // importScripts('dupe.js'); importScripts('dupe.js');) or if it recursively
- // imports the main script. In this case, read the installed script from
- // storage.
+ // There are four cases of how to handle the request for the script.
+ // A) service worker is installed, script is installed: serve from storage
+ // (use ServceWorkerInstalledScriptLoader). Typically this case is handled
+ // by ServiceWorkerInstalledScriptsSender, but we can still get here when a
+ // new service worker starts up and becomes installed while it is running.
+ // B) service worker is installed, script is not installed: serve from direct
+ // network. This happens when the script is newly imported after
+ // installation.
+ // TODO(crbug.com/719052): deprecate this.
+ // C) service worker is not installed, script is installed: serve from
+ // storage (use ServceWorkerInstalledScriptLoader)
+ // D) service worker is not installed, script is not installed: serve from
+ // network with installing the script (use ServceWorkerNewScriptLoader)
+ // This is the common case: load the script and install it.
+
+ // Case A and C:
scoped_refptr<ServiceWorkerVersion> version =
provider_host_->running_hosted_version();
int64_t resource_id =
@@ -70,7 +76,17 @@ void ServiceWorkerScriptLoaderFactory::CreateLoaderAndStart(
return;
}
- // The common case: load the script and install it.
+ // Case B:
+ if (ServiceWorkerVersion::IsInstalled(version->status())) {
+ // TODO(kinuko): Record the reason like what we do with netlog in
+ // ServiceWorkerContextRequestHandler.
+ loader_factory_->CreateLoaderAndStart(
+ std::move(request), routing_id, request_id, options, resource_request,
+ std::move(client), traffic_annotation);
+ return;
+ }
+
+ // Case D:
mojo::MakeStrongBinding(
std::make_unique<ServiceWorkerNewScriptLoader>(
routing_id, request_id, options, resource_request, std::move(client),
@@ -81,12 +97,10 @@ void ServiceWorkerScriptLoaderFactory::CreateLoaderAndStart(
void ServiceWorkerScriptLoaderFactory::Clone(
network::mojom::URLLoaderFactoryRequest request) {
- // This method is required to support synchronous requests which are not
- // performed during installation.
- NOTREACHED();
+ bindings_.AddBinding(this, std::move(request));
}
-bool ServiceWorkerScriptLoaderFactory::ShouldHandleScriptRequest(
+bool ServiceWorkerScriptLoaderFactory::CheckIfScriptRequestIsValid(
const network::ResourceRequest& resource_request) {
if (!context_ || !provider_host_)
return false;
@@ -98,45 +112,23 @@ bool ServiceWorkerScriptLoaderFactory::ShouldHandleScriptRequest(
// Handle only the service worker main script (RESOURCE_TYPE_SERVICE_WORKER)
// or importScripts() (RESOURCE_TYPE_SCRIPT).
- switch (resource_request.resource_type) {
- case RESOURCE_TYPE_SERVICE_WORKER:
- // The main script should be fetched only when we start a new service
- // worker.
- if (version->status() != ServiceWorkerVersion::NEW)
- return false;
- break;
- case RESOURCE_TYPE_SCRIPT:
- // TODO(nhiroki): In the current implementation, importScripts() can be
- // called in any ServiceWorkerVersion::Status except for REDUNDANT, but
- // the spec defines importScripts() works only on the initial script
- // evaluation and the install event. Update this check once
- // importScripts() is fixed (https://crbug.com/719052).
- if (version->status() == ServiceWorkerVersion::REDUNDANT) {
- // This could happen if browser-side has set the status to redundant but
- // the worker has not yet stopped. The worker is already doomed so just
- // reject the request. Handle it specially here because otherwise it'd
- // be unclear whether "REDUNDANT" should count as installed or not
- // installed when making decisions about how to handle the request and
- // logging UMA.
- return false;
- }
- break;
- default:
- // TODO(nhiroki): Record bad message, we shouldn't come here for other
- // request types.
- NOTREACHED();
- return false;
+ if (resource_request.resource_type != RESOURCE_TYPE_SERVICE_WORKER &&
+ resource_request.resource_type != RESOURCE_TYPE_SCRIPT) {
+ mojo::ReportBadMessage("SWSLF_BAD_RESOURCE_TYPE");
+ return false;
}
- // TODO(falken): Make sure we don't handle a redirected request.
-
- // For installed service workers, typically all the scripts are served via
- // script streaming, so we don't come here. However, we still come here when
- // the service worker is importing a script that was never installed. For now,
- // return false here to fallback to network. Eventually, it should be
- // deprecated (https://crbug.com/719052).
- if (ServiceWorkerVersion::IsInstalled(version->status()))
+ if (version->status() == ServiceWorkerVersion::REDUNDANT) {
+ // This could happen if browser-side has set the status to redundant but
+ // the worker has not yet stopped. The worker is already doomed so just
+ // reject the request. Handle it specially here because otherwise it'd
+ // be unclear whether "REDUNDANT" should count as installed or not
+ // installed when making decisions about how to handle the request and
+ // logging UMA.
return false;
+ }
+
+ // TODO(falken): Make sure we don't handle a redirected request.
return true;
}
diff --git a/chromium/content/browser/service_worker/service_worker_script_loader_factory.h b/chromium/content/browser/service_worker/service_worker_script_loader_factory.h
index 995bb61f499..efc08ff62e5 100644
--- a/chromium/content/browser/service_worker/service_worker_script_loader_factory.h
+++ b/chromium/content/browser/service_worker/service_worker_script_loader_factory.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_LOADER_FACTORY_H_
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace network {
@@ -54,13 +55,15 @@ class ServiceWorkerScriptLoaderFactory
void Clone(network::mojom::URLLoaderFactoryRequest request) override;
private:
- bool ShouldHandleScriptRequest(
+ bool CheckIfScriptRequestIsValid(
const network::ResourceRequest& resource_request);
base::WeakPtr<ServiceWorkerContextCore> context_;
base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
+ mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
+
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerScriptLoaderFactory);
};
diff --git a/chromium/content/browser/service_worker/service_worker_storage.cc b/chromium/content/browser/service_worker/service_worker_storage.cc
index 81676aaacaf..93a71912a4c 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage.cc
@@ -44,11 +44,12 @@ void RunSoon(const base::Location& from_here, base::OnceClosure closure) {
}
void CompleteFindNow(scoped_refptr<ServiceWorkerRegistration> registration,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
ServiceWorkerStorage::FindRegistrationCallback callback) {
if (registration && registration->is_deleted()) {
// It's past the point of no return and no longer findable.
- std::move(callback).Run(SERVICE_WORKER_ERROR_NOT_FOUND, nullptr);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorNotFound,
+ nullptr);
return;
}
std::move(callback).Run(status, std::move(registration));
@@ -56,7 +57,7 @@ void CompleteFindNow(scoped_refptr<ServiceWorkerRegistration> registration,
void CompleteFindSoon(const base::Location& from_here,
scoped_refptr<ServiceWorkerRegistration> registration,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
ServiceWorkerStorage::FindRegistrationCallback callback) {
RunSoon(from_here, base::BindOnce(&CompleteFindNow, std::move(registration),
status, std::move(callback)));
@@ -70,18 +71,18 @@ const base::FilePath::CharType kDiskCacheName[] =
const int kMaxServiceWorkerStorageMemDiskCacheSize = 10 * 1024 * 1024;
const int kMaxServiceWorkerStorageDiskCacheSize = 250 * 1024 * 1024;
-ServiceWorkerStatusCode DatabaseStatusToStatusCode(
+blink::ServiceWorkerStatusCode DatabaseStatusToStatusCode(
ServiceWorkerDatabase::Status status) {
switch (status) {
case ServiceWorkerDatabase::STATUS_OK:
- return SERVICE_WORKER_OK;
+ return blink::ServiceWorkerStatusCode::kOk;
case ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND:
- return SERVICE_WORKER_ERROR_NOT_FOUND;
+ return blink::ServiceWorkerStatusCode::kErrorNotFound;
case ServiceWorkerDatabase::STATUS_ERROR_MAX:
NOTREACHED();
FALLTHROUGH;
default:
- return SERVICE_WORKER_ERROR_FAILED;
+ return blink::ServiceWorkerStatusCode::kErrorFailed;
}
}
@@ -148,7 +149,8 @@ void ServiceWorkerStorage::FindRegistrationForDocument(
switch (state_) {
case DISABLED:
CompleteFindNow(scoped_refptr<ServiceWorkerRegistration>(),
- SERVICE_WORKER_ERROR_ABORT, std::move(callback));
+ blink::ServiceWorkerStatusCode::kErrorAbort,
+ std::move(callback));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -169,15 +171,15 @@ void ServiceWorkerStorage::FindRegistrationForDocument(
// Look for something currently being installed.
scoped_refptr<ServiceWorkerRegistration> installing_registration =
FindInstallingRegistrationForDocument(document_url);
- ServiceWorkerStatusCode status = installing_registration
- ? SERVICE_WORKER_OK
- : SERVICE_WORKER_ERROR_NOT_FOUND;
+ blink::ServiceWorkerStatusCode status =
+ installing_registration
+ ? blink::ServiceWorkerStatusCode::kOk
+ : blink::ServiceWorkerStatusCode::kErrorNotFound;
TRACE_EVENT_INSTANT2(
"ServiceWorker",
"ServiceWorkerStorage::FindRegistrationForDocument:CheckInstalling",
- TRACE_EVENT_SCOPE_THREAD,
- "URL", document_url.spec(),
- "Status", ServiceWorkerStatusToString(status));
+ TRACE_EVENT_SCOPE_THREAD, "URL", document_url.spec(), "Status",
+ blink::ServiceWorkerStatusToString(status));
CompleteFindNow(std::move(installing_registration), status,
std::move(callback));
return;
@@ -205,7 +207,8 @@ void ServiceWorkerStorage::FindRegistrationForPattern(
switch (state_) {
case DISABLED:
CompleteFindSoon(FROM_HERE, scoped_refptr<ServiceWorkerRegistration>(),
- SERVICE_WORKER_ERROR_ABORT, std::move(callback));
+ blink::ServiceWorkerStatusCode::kErrorAbort,
+ std::move(callback));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -222,9 +225,10 @@ void ServiceWorkerStorage::FindRegistrationForPattern(
// Look for something currently being installed.
scoped_refptr<ServiceWorkerRegistration> installing_registration =
FindInstallingRegistrationForPattern(scope);
- ServiceWorkerStatusCode installing_status =
- installing_registration ? SERVICE_WORKER_OK
- : SERVICE_WORKER_ERROR_NOT_FOUND;
+ blink::ServiceWorkerStatusCode installing_status =
+ installing_registration
+ ? blink::ServiceWorkerStatusCode::kOk
+ : blink::ServiceWorkerStatusCode::kErrorNotFound;
CompleteFindSoon(FROM_HERE, std::move(installing_registration),
installing_status, std::move(callback));
return;
@@ -260,7 +264,8 @@ void ServiceWorkerStorage::FindRegistrationForId(
switch (state_) {
case DISABLED:
CompleteFindNow(scoped_refptr<ServiceWorkerRegistration>(),
- SERVICE_WORKER_ERROR_ABORT, std::move(callback));
+ blink::ServiceWorkerStatusCode::kErrorAbort,
+ std::move(callback));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -279,8 +284,9 @@ void ServiceWorkerStorage::FindRegistrationForId(
scoped_refptr<ServiceWorkerRegistration> installing_registration =
FindInstallingRegistrationForId(registration_id);
CompleteFindNow(installing_registration,
- installing_registration ? SERVICE_WORKER_OK
- : SERVICE_WORKER_ERROR_NOT_FOUND,
+ installing_registration
+ ? blink::ServiceWorkerStatusCode::kOk
+ : blink::ServiceWorkerStatusCode::kErrorNotFound,
std::move(callback));
return;
}
@@ -288,8 +294,8 @@ void ServiceWorkerStorage::FindRegistrationForId(
scoped_refptr<ServiceWorkerRegistration> registration =
context_->GetLiveRegistration(registration_id);
if (registration) {
- CompleteFindNow(std::move(registration), SERVICE_WORKER_OK,
- std::move(callback));
+ CompleteFindNow(std::move(registration),
+ blink::ServiceWorkerStatusCode::kOk, std::move(callback));
return;
}
@@ -307,7 +313,8 @@ void ServiceWorkerStorage::FindRegistrationForIdOnly(
FindRegistrationCallback callback) {
switch (state_) {
case DISABLED:
- CompleteFindNow(nullptr, SERVICE_WORKER_ERROR_ABORT, std::move(callback));
+ CompleteFindNow(nullptr, blink::ServiceWorkerStatusCode::kErrorAbort,
+ std::move(callback));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -345,10 +352,11 @@ void ServiceWorkerStorage::GetRegistrationsForOrigin(
GetRegistrationsCallback callback) {
switch (state_) {
case DISABLED:
- RunSoon(FROM_HERE,
- base::BindOnce(
- std::move(callback), SERVICE_WORKER_ERROR_ABORT,
- std::vector<scoped_refptr<ServiceWorkerRegistration>>()));
+ RunSoon(
+ FROM_HERE,
+ base::BindOnce(
+ std::move(callback), blink::ServiceWorkerStatusCode::kErrorAbort,
+ std::vector<scoped_refptr<ServiceWorkerRegistration>>()));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -378,7 +386,8 @@ void ServiceWorkerStorage::GetAllRegistrationsInfos(
switch (state_) {
case DISABLED:
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT,
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort,
std::vector<ServiceWorkerRegistrationInfo>()));
return;
case INITIALIZING: // Fall-through.
@@ -411,7 +420,8 @@ void ServiceWorkerStorage::StoreRegistration(
DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_;
if (IsDisabled()) {
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
@@ -439,7 +449,8 @@ void ServiceWorkerStorage::StoreRegistration(
if (resources.empty()) {
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_FAILED));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
@@ -471,7 +482,8 @@ void ServiceWorkerStorage::UpdateToActiveState(
DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_;
if (IsDisabled()) {
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
@@ -507,7 +519,7 @@ void ServiceWorkerStorage::UpdateNavigationPreloadEnabled(
StatusCallback callback) {
DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_;
if (IsDisabled()) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort);
return;
}
@@ -526,7 +538,7 @@ void ServiceWorkerStorage::UpdateNavigationPreloadHeader(
StatusCallback callback) {
DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_;
if (IsDisabled()) {
- std::move(callback).Run(SERVICE_WORKER_ERROR_ABORT);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort);
return;
}
@@ -544,7 +556,8 @@ void ServiceWorkerStorage::DeleteRegistration(int64_t registration_id,
DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_;
if (IsDisabled()) {
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
@@ -636,7 +649,8 @@ void ServiceWorkerStorage::StoreUserData(
switch (state_) {
case DISABLED:
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -651,13 +665,15 @@ void ServiceWorkerStorage::StoreUserData(
if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId ||
key_value_pairs.empty()) {
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_FAILED));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
for (const auto& kv : key_value_pairs) {
if (kv.first.empty()) {
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_FAILED));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
}
@@ -678,7 +694,7 @@ void ServiceWorkerStorage::GetUserData(int64_t registration_id,
case DISABLED:
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback), std::vector<std::string>(),
- SERVICE_WORKER_ERROR_ABORT));
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -694,14 +710,14 @@ void ServiceWorkerStorage::GetUserData(int64_t registration_id,
keys.empty()) {
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback), std::vector<std::string>(),
- SERVICE_WORKER_ERROR_FAILED));
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
for (const std::string& key : keys) {
if (key.empty()) {
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback), std::vector<std::string>(),
- SERVICE_WORKER_ERROR_FAILED));
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
}
@@ -723,7 +739,7 @@ void ServiceWorkerStorage::GetUserDataByKeyPrefix(
case DISABLED:
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback), std::vector<std::string>(),
- SERVICE_WORKER_ERROR_ABORT));
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -739,13 +755,13 @@ void ServiceWorkerStorage::GetUserDataByKeyPrefix(
if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId) {
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback), std::vector<std::string>(),
- SERVICE_WORKER_ERROR_FAILED));
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
if (key_prefix.empty()) {
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback), std::vector<std::string>(),
- SERVICE_WORKER_ERROR_FAILED));
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
@@ -767,7 +783,7 @@ void ServiceWorkerStorage::GetUserKeysAndDataByKeyPrefix(
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback),
base::flat_map<std::string, std::string>(),
- SERVICE_WORKER_ERROR_ABORT));
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -785,7 +801,7 @@ void ServiceWorkerStorage::GetUserKeysAndDataByKeyPrefix(
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback),
base::flat_map<std::string, std::string>(),
- SERVICE_WORKER_ERROR_FAILED));
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
@@ -805,7 +821,8 @@ void ServiceWorkerStorage::ClearUserData(int64_t registration_id,
switch (state_) {
case DISABLED:
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -820,13 +837,15 @@ void ServiceWorkerStorage::ClearUserData(int64_t registration_id,
if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId ||
keys.empty()) {
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_FAILED));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
for (const std::string& key : keys) {
if (key.empty()) {
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_FAILED));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
}
@@ -846,7 +865,8 @@ void ServiceWorkerStorage::ClearUserDataByKeyPrefixes(
switch (state_) {
case DISABLED:
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -862,13 +882,15 @@ void ServiceWorkerStorage::ClearUserDataByKeyPrefixes(
if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId ||
key_prefixes.empty()) {
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_FAILED));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
for (const std::string& key_prefix : key_prefixes) {
if (key_prefix.empty()) {
RunSoon(FROM_HERE,
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_FAILED));
+ base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
}
@@ -890,7 +912,7 @@ void ServiceWorkerStorage::GetUserDataForAllRegistrations(
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback),
std::vector<std::pair<int64_t, std::string>>(),
- SERVICE_WORKER_ERROR_ABORT));
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -906,7 +928,7 @@ void ServiceWorkerStorage::GetUserDataForAllRegistrations(
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback),
std::vector<std::pair<int64_t, std::string>>(),
- SERVICE_WORKER_ERROR_FAILED));
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
@@ -928,7 +950,7 @@ void ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefix(
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback),
std::vector<std::pair<int64_t, std::string>>(),
- SERVICE_WORKER_ERROR_ABORT));
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
case INITIALIZING: // Fall-through.
case UNINITIALIZED:
@@ -944,7 +966,7 @@ void ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefix(
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback),
std::vector<std::pair<int64_t, std::string>>(),
- SERVICE_WORKER_ERROR_FAILED));
+ blink::ServiceWorkerStatusCode::kErrorFailed));
return;
}
@@ -1012,11 +1034,11 @@ void ServiceWorkerStorage::NotifyInstallingRegistration(
}
void ServiceWorkerStorage::NotifyDoneInstallingRegistration(
- ServiceWorkerRegistration* registration,
- ServiceWorkerVersion* version,
- ServiceWorkerStatusCode status) {
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerVersion* version,
+ blink::ServiceWorkerStatusCode status) {
installing_registrations_.erase(registration->id());
- if (status != SERVICE_WORKER_OK && version) {
+ if (status != blink::ServiceWorkerStatusCode::kOk && version) {
ResourceList resources;
version->script_cache_map()->GetResources(&resources);
@@ -1160,20 +1182,19 @@ void ServiceWorkerStorage::DidFindRegistrationForDocument(
// Look for something currently being installed.
scoped_refptr<ServiceWorkerRegistration> installing_registration =
FindInstallingRegistrationForDocument(document_url);
- ServiceWorkerStatusCode installing_status =
- installing_registration ? SERVICE_WORKER_OK
- : SERVICE_WORKER_ERROR_NOT_FOUND;
+ blink::ServiceWorkerStatusCode installing_status =
+ installing_registration
+ ? blink::ServiceWorkerStatusCode::kOk
+ : blink::ServiceWorkerStatusCode::kErrorNotFound;
std::move(callback).Run(installing_status,
std::move(installing_registration));
TRACE_EVENT_ASYNC_END2(
- "ServiceWorker",
- "ServiceWorkerStorage::FindRegistrationForDocument",
- callback_id,
- "Status", ServiceWorkerDatabase::StatusToString(status),
+ "ServiceWorker", "ServiceWorkerStorage::FindRegistrationForDocument",
+ callback_id, "Status", ServiceWorkerDatabase::StatusToString(status),
"Info",
- (installing_status == SERVICE_WORKER_OK) ?
- "Installing registration is found" :
- "Any registrations are not found");
+ (installing_status == blink::ServiceWorkerStatusCode::kOk)
+ ? "Installing registration is found"
+ : "Any registrations are not found");
return;
}
@@ -1201,9 +1222,10 @@ void ServiceWorkerStorage::DidFindRegistrationForPattern(
if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
scoped_refptr<ServiceWorkerRegistration> installing_registration =
FindInstallingRegistrationForPattern(scope);
- ServiceWorkerStatusCode installing_status =
- installing_registration ? SERVICE_WORKER_OK
- : SERVICE_WORKER_ERROR_NOT_FOUND;
+ blink::ServiceWorkerStatusCode installing_status =
+ installing_registration
+ ? blink::ServiceWorkerStatusCode::kOk
+ : blink::ServiceWorkerStatusCode::kErrorNotFound;
std::move(callback).Run(installing_status,
std::move(installing_registration));
return;
@@ -1243,7 +1265,7 @@ void ServiceWorkerStorage::ReturnFoundRegistration(
DCHECK(!resources.empty());
scoped_refptr<ServiceWorkerRegistration> registration =
GetOrCreateRegistration(data, resources);
- CompleteFindNow(std::move(registration), SERVICE_WORKER_OK,
+ CompleteFindNow(std::move(registration), blink::ServiceWorkerStatusCode::kOk,
std::move(callback));
}
@@ -1284,7 +1306,8 @@ void ServiceWorkerStorage::DidGetRegistrationsForOrigin(
registrations.push_back(registration.second);
}
- std::move(callback).Run(SERVICE_WORKER_OK, std::move(registrations));
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk,
+ std::move(registrations));
}
void ServiceWorkerStorage::DidGetAllRegistrationsInfos(
@@ -1359,7 +1382,7 @@ void ServiceWorkerStorage::DidGetAllRegistrationsInfos(
infos.push_back(registration.second->GetInfo());
}
- std::move(callback).Run(SERVICE_WORKER_OK, infos);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk, infos);
}
void ServiceWorkerStorage::DidStoreRegistration(
@@ -1393,7 +1416,7 @@ void ServiceWorkerStorage::DidStoreRegistration(
context_->NotifyRegistrationStored(new_version.registration_id,
new_version.scope);
- std::move(callback).Run(SERVICE_WORKER_OK);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk);
if (!context_->GetLiveVersion(deleted_version.version_id))
StartPurgingResources(newly_purgeable_resources);
@@ -1431,7 +1454,7 @@ void ServiceWorkerStorage::DidDeleteRegistration(
}
if (origin_state == OriginState::kDelete)
registered_origins_.erase(params->origin);
- std::move(params->callback).Run(SERVICE_WORKER_OK);
+ std::move(params->callback).Run(blink::ServiceWorkerStatusCode::kOk);
if (!context_->GetLiveVersion(deleted_version.version_id))
StartPurgingResources(newly_purgeable_resources);
@@ -2112,13 +2135,13 @@ void ServiceWorkerStorage::DidDeleteDiskCache(StatusCallback callback,
LOG(ERROR) << "Failed to delete the diskcache.";
ServiceWorkerMetrics::RecordDeleteAndStartOverResult(
ServiceWorkerMetrics::DELETE_DISK_CACHE_ERROR);
- std::move(callback).Run(SERVICE_WORKER_ERROR_FAILED);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorFailed);
return;
}
DVLOG(1) << "Deleted ServiceWorkerDiskCache successfully.";
ServiceWorkerMetrics::RecordDeleteAndStartOverResult(
ServiceWorkerMetrics::DELETE_OK);
- std::move(callback).Run(SERVICE_WORKER_OK);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk);
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_storage.h b/chromium/content/browser/service_worker/service_worker_storage.h
index 88a1c291efb..722ba4e9f42 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.h
+++ b/chromium/content/browser/service_worker/service_worker_storage.h
@@ -25,7 +25,7 @@
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/content_export.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
namespace base {
@@ -69,30 +69,30 @@ FORWARD_DECLARE_TEST(ServiceWorkerResourceStorageDiskTest,
// disabled and all subsequent requests are aborted until the context core is
// restarted.
class CONTENT_EXPORT ServiceWorkerStorage
- : public ServiceWorkerVersion::Listener {
+ : public ServiceWorkerVersion::Observer {
public:
using ResourceList = std::vector<ServiceWorkerDatabase::ResourceRecord>;
using StatusCallback =
- base::OnceCallback<void(ServiceWorkerStatusCode status)>;
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode status)>;
using FindRegistrationCallback = base::OnceCallback<void(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration)>;
using GetRegistrationsCallback = base::OnceCallback<void(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
registrations)>;
using GetRegistrationsInfosCallback = base::OnceCallback<void(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& registrations)>;
using GetUserDataCallback =
base::OnceCallback<void(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status)>;
+ blink::ServiceWorkerStatusCode status)>;
using GetUserKeysAndDataCallback = base::OnceCallback<void(
const base::flat_map<std::string, std::string>& data_map,
- ServiceWorkerStatusCode status)>;
+ blink::ServiceWorkerStatusCode status)>;
using GetUserDataForAllRegistrationsCallback = base::OnceCallback<void(
const std::vector<std::pair<int64_t, std::string>>& user_data,
- ServiceWorkerStatusCode status)>;
+ blink::ServiceWorkerStatusCode status)>;
~ServiceWorkerStorage() override;
@@ -110,9 +110,10 @@ class CONTENT_EXPORT ServiceWorkerStorage
// Finds registration for |document_url| or |pattern| or |registration_id|.
// The Find methods will find stored and initially installing registrations.
- // Returns SERVICE_WORKER_OK with non-null registration if registration
- // is found, or returns SERVICE_WORKER_ERROR_NOT_FOUND if no matching
- // registration is found. The FindRegistrationForPattern method is
+ // Returns blink::ServiceWorkerStatusCode::kOk with non-null
+ // registration if registration is found, or returns
+ // blink::ServiceWorkerStatusCode::kErrorNotFound if no
+ // matching registration is found. The FindRegistrationForPattern method is
// guaranteed to return asynchronously. However, the methods to find
// for |document_url| or |registration_id| may complete immediately
// (the callback may be called prior to the method returning) or
@@ -259,10 +260,9 @@ class CONTENT_EXPORT ServiceWorkerStorage
// ServiceWorkerRegistration.
void NotifyInstallingRegistration(
ServiceWorkerRegistration* registration);
- void NotifyDoneInstallingRegistration(
- ServiceWorkerRegistration* registration,
- ServiceWorkerVersion* version,
- ServiceWorkerStatusCode status);
+ void NotifyDoneInstallingRegistration(ServiceWorkerRegistration* registration,
+ ServiceWorkerVersion* version,
+ blink::ServiceWorkerStatusCode status);
void NotifyUninstallingRegistration(ServiceWorkerRegistration* registration);
void NotifyDoneUninstallingRegistration(
ServiceWorkerRegistration* registration);
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 1c69543d47c..babac6c2096 100644
--- a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -14,7 +14,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
@@ -23,7 +23,6 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_client.h"
#include "content/public/common/origin_util.h"
@@ -40,6 +39,7 @@
#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/origin_trials/origin_trial_policy.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -68,30 +68,30 @@ const uint8_t kTestPublicKey[] = {
0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
};
-void StatusAndQuitCallback(ServiceWorkerStatusCode* result,
+void StatusAndQuitCallback(blink::ServiceWorkerStatusCode* result,
const base::Closure& quit_closure,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
*result = status;
quit_closure.Run();
}
void StatusCallback(bool* was_called,
- ServiceWorkerStatusCode* result,
- ServiceWorkerStatusCode status) {
+ base::Optional<blink::ServiceWorkerStatusCode>* result,
+ blink::ServiceWorkerStatusCode status) {
*was_called = true;
*result = status;
}
ServiceWorkerStorage::StatusCallback MakeStatusCallback(
bool* was_called,
- ServiceWorkerStatusCode* result) {
+ base::Optional<blink::ServiceWorkerStatusCode>* result) {
return base::BindOnce(&StatusCallback, was_called, result);
}
void FindCallback(bool* was_called,
- ServiceWorkerStatusCode* result,
+ base::Optional<blink::ServiceWorkerStatusCode>* result,
scoped_refptr<ServiceWorkerRegistration>* found,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
*was_called = true;
*result = status;
@@ -100,16 +100,16 @@ void FindCallback(bool* was_called,
ServiceWorkerStorage::FindRegistrationCallback MakeFindCallback(
bool* was_called,
- ServiceWorkerStatusCode* result,
+ base::Optional<blink::ServiceWorkerStatusCode>* result,
scoped_refptr<ServiceWorkerRegistration>* found) {
return base::BindOnce(&FindCallback, was_called, result, found);
}
void GetAllCallback(
bool* was_called,
- ServiceWorkerStatusCode* result,
+ base::Optional<blink::ServiceWorkerStatusCode>* result,
std::vector<scoped_refptr<ServiceWorkerRegistration>>* all_out,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<scoped_refptr<ServiceWorkerRegistration>>& all) {
*was_called = true;
*result = status;
@@ -118,9 +118,9 @@ void GetAllCallback(
void GetAllInfosCallback(
bool* was_called,
- ServiceWorkerStatusCode* result,
+ base::Optional<blink::ServiceWorkerStatusCode>* result,
std::vector<ServiceWorkerRegistrationInfo>* all_out,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& all) {
*was_called = true;
*result = status;
@@ -129,7 +129,7 @@ void GetAllInfosCallback(
ServiceWorkerStorage::GetRegistrationsCallback MakeGetRegistrationsCallback(
bool* was_called,
- ServiceWorkerStatusCode* status,
+ base::Optional<blink::ServiceWorkerStatusCode>* status,
std::vector<scoped_refptr<ServiceWorkerRegistration>>* all) {
return base::BindOnce(&GetAllCallback, was_called, status, all);
}
@@ -137,16 +137,17 @@ ServiceWorkerStorage::GetRegistrationsCallback MakeGetRegistrationsCallback(
ServiceWorkerStorage::GetRegistrationsInfosCallback
MakeGetRegistrationsInfosCallback(
bool* was_called,
- ServiceWorkerStatusCode* status,
+ base::Optional<blink::ServiceWorkerStatusCode>* status,
std::vector<ServiceWorkerRegistrationInfo>* all) {
return base::BindOnce(&GetAllInfosCallback, was_called, status, all);
}
-void GetUserDataCallback(bool* was_called,
- std::vector<std::string>* data_out,
- ServiceWorkerStatusCode* status_out,
- const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
+void GetUserDataCallback(
+ bool* was_called,
+ std::vector<std::string>* data_out,
+ base::Optional<blink::ServiceWorkerStatusCode>* status_out,
+ const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status) {
*was_called = true;
*data_out = data;
*status_out = status;
@@ -155,9 +156,9 @@ void GetUserDataCallback(bool* was_called,
void GetUserDataForAllRegistrationsCallback(
bool* was_called,
std::vector<std::pair<int64_t, std::string>>* data_out,
- ServiceWorkerStatusCode* status_out,
+ base::Optional<blink::ServiceWorkerStatusCode>* status_out,
const std::vector<std::pair<int64_t, std::string>>& data,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
*was_called = true;
*data_out = data;
*status_out = status;
@@ -339,8 +340,8 @@ class ServiceWorkerStorageTest : public testing::Test {
ServiceWorkerDatabase* database,
std::set<int64_t>* purgeable_ids,
bool* was_called,
- ServiceWorkerStatusCode* result,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode* result,
+ blink::ServiceWorkerStatusCode status) {
*was_called = true;
*result = status;
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -378,151 +379,153 @@ class ServiceWorkerStorageTest : public testing::Test {
return registration;
}
- ServiceWorkerStatusCode StoreRegistration(
+ blink::ServiceWorkerStatusCode StoreRegistration(
scoped_refptr<ServiceWorkerRegistration> registration,
scoped_refptr<ServiceWorkerVersion> version) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->StoreRegistration(registration.get(),
version.get(),
MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode DeleteRegistration(int64_t registration_id,
- const GURL& origin) {
+ blink::ServiceWorkerStatusCode DeleteRegistration(int64_t registration_id,
+ const GURL& origin) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->DeleteRegistration(
registration_id, origin, MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode GetAllRegistrationsInfos(
+ blink::ServiceWorkerStatusCode GetAllRegistrationsInfos(
std::vector<ServiceWorkerRegistrationInfo>* registrations) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->GetAllRegistrationsInfos(
MakeGetRegistrationsInfosCallback(&was_called, &result, registrations));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode GetRegistrationsForOrigin(
+ blink::ServiceWorkerStatusCode GetRegistrationsForOrigin(
const GURL& origin,
std::vector<scoped_refptr<ServiceWorkerRegistration>>* registrations) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->GetRegistrationsForOrigin(
origin,
MakeGetRegistrationsCallback(&was_called, &result, registrations));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode GetUserData(int64_t registration_id,
- const std::vector<std::string>& keys,
- std::vector<std::string>* data) {
+ blink::ServiceWorkerStatusCode GetUserData(
+ int64_t registration_id,
+ const std::vector<std::string>& keys,
+ std::vector<std::string>* data) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->GetUserData(
registration_id, keys,
base::BindOnce(&GetUserDataCallback, &was_called, data, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode GetUserDataByKeyPrefix(
+ blink::ServiceWorkerStatusCode GetUserDataByKeyPrefix(
int64_t registration_id,
const std::string& key_prefix,
std::vector<std::string>* data) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->GetUserDataByKeyPrefix(
registration_id, key_prefix,
base::BindOnce(&GetUserDataCallback, &was_called, data, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode StoreUserData(
+ blink::ServiceWorkerStatusCode StoreUserData(
int64_t registration_id,
const GURL& origin,
const std::vector<std::pair<std::string, std::string>>& key_value_pairs) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->StoreUserData(registration_id, origin, key_value_pairs,
MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode ClearUserData(int64_t registration_id,
- const std::vector<std::string>& keys) {
+ blink::ServiceWorkerStatusCode ClearUserData(
+ int64_t registration_id,
+ const std::vector<std::string>& keys) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->ClearUserData(registration_id, keys,
MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode ClearUserDataByKeyPrefixes(
+ blink::ServiceWorkerStatusCode ClearUserDataByKeyPrefixes(
int64_t registration_id,
const std::vector<std::string>& key_prefixes) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->ClearUserDataByKeyPrefixes(
registration_id, key_prefixes,
MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode GetUserDataForAllRegistrations(
+ blink::ServiceWorkerStatusCode GetUserDataForAllRegistrations(
const std::string& key,
std::vector<std::pair<int64_t, std::string>>* data) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->GetUserDataForAllRegistrations(
key, base::BindOnce(&GetUserDataForAllRegistrationsCallback,
&was_called, data, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode UpdateToActiveState(
+ blink::ServiceWorkerStatusCode UpdateToActiveState(
scoped_refptr<ServiceWorkerRegistration> registration) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->UpdateToActiveState(registration.get(),
MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
void UpdateLastUpdateCheckTime(
@@ -531,55 +534,55 @@ class ServiceWorkerStorageTest : public testing::Test {
base::RunLoop().RunUntilIdle();
}
- ServiceWorkerStatusCode FindRegistrationForDocument(
+ blink::ServiceWorkerStatusCode FindRegistrationForDocument(
const GURL& document_url,
scoped_refptr<ServiceWorkerRegistration>* registration) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->FindRegistrationForDocument(
document_url, MakeFindCallback(&was_called, &result, registration));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode FindRegistrationForPattern(
+ blink::ServiceWorkerStatusCode FindRegistrationForPattern(
const GURL& scope,
scoped_refptr<ServiceWorkerRegistration>* registration) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->FindRegistrationForPattern(
scope, MakeFindCallback(&was_called, &result, registration));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode FindRegistrationForId(
+ blink::ServiceWorkerStatusCode FindRegistrationForId(
int64_t registration_id,
const GURL& origin,
scoped_refptr<ServiceWorkerRegistration>* registration) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->FindRegistrationForId(
registration_id, origin,
MakeFindCallback(&was_called, &result, registration));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
- ServiceWorkerStatusCode FindRegistrationForIdOnly(
+ blink::ServiceWorkerStatusCode FindRegistrationForIdOnly(
int64_t registration_id,
scoped_refptr<ServiceWorkerRegistration>* registration) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> result;
storage()->FindRegistrationForIdOnly(
registration_id, MakeFindCallback(&was_called, &result, registration));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
- return result;
+ return result.value();
}
// Directly writes a registration using
@@ -616,24 +619,24 @@ TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
storage()->Disable();
scoped_refptr<ServiceWorkerRegistration> found_registration;
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
FindRegistrationForPattern(kScope, &found_registration));
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
&found_registration));
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
FindRegistrationForIdOnly(kRegistrationId, &found_registration));
EXPECT_FALSE(storage()->GetUninstallingRegistration(kScope.GetOrigin()));
std::vector<scoped_refptr<ServiceWorkerRegistration>> found_registrations;
EXPECT_EQ(
- SERVICE_WORKER_ERROR_ABORT,
+ blink::ServiceWorkerStatusCode::kErrorAbort,
GetRegistrationsForOrigin(kScope.GetOrigin(), &found_registrations));
std::vector<ServiceWorkerRegistrationInfo> all_registrations;
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
GetAllRegistrationsInfos(&all_registrations));
blink::mojom::ServiceWorkerRegistrationOptions options;
@@ -643,12 +646,13 @@ TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
context()->AsWeakPtr());
scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
live_registration.get(), kScript, kVersionId, context()->AsWeakPtr());
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
StoreRegistration(live_registration, live_version));
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT, UpdateToActiveState(live_registration));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
+ UpdateToActiveState(live_registration));
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
// Response reader and writer created by the disabled storage should fail to
@@ -663,19 +667,19 @@ TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
const std::string kUserDataKey = "key";
std::vector<std::string> user_data_out;
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
GetUserData(kRegistrationId, {kUserDataKey}, &user_data_out));
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
GetUserDataByKeyPrefix(kRegistrationId, "prefix", &user_data_out));
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
StoreUserData(kRegistrationId, kScope.GetOrigin(),
{{kUserDataKey, "foo"}}));
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
ClearUserData(kRegistrationId, {kUserDataKey}));
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
ClearUserDataByKeyPrefixes(kRegistrationId, {"prefix"}));
std::vector<std::pair<int64_t, std::string>> data_list_out;
- EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
GetUserDataForAllRegistrations(kUserDataKey, &data_list_out));
// Next available ids should be invalid.
@@ -705,17 +709,17 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
scoped_refptr<ServiceWorkerRegistration> found_registration;
// We shouldn't find anything without having stored anything.
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
EXPECT_FALSE(found_registration.get());
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
FindRegistrationForPattern(kScope, &found_registration));
EXPECT_FALSE(found_registration.get());
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
- FindRegistrationForId(
- kRegistrationId, kScope.GetOrigin(), &found_registration));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
+ FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
+ &found_registration));
EXPECT_FALSE(found_registration.get());
std::vector<ResourceRecord> resources;
@@ -738,11 +742,11 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
std::set<blink::mojom::WebFeature>(used_features));
live_registration->SetWaitingVersion(live_version);
live_registration->set_last_update_check(kYesterday);
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
StoreRegistration(live_registration, live_version));
// Now we should find it and get the live ptr back immediately.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
EXPECT_EQ(live_registration, found_registration);
EXPECT_EQ(kResource1Size + kResource2Size,
@@ -754,22 +758,22 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
found_registration = nullptr;
// But FindRegistrationForPattern is always async.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForPattern(kScope, &found_registration));
EXPECT_EQ(live_registration, found_registration);
found_registration = nullptr;
// Can be found by id too.
- EXPECT_EQ(SERVICE_WORKER_OK,
- FindRegistrationForId(
- kRegistrationId, kScope.GetOrigin(), &found_registration));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
+ &found_registration));
ASSERT_TRUE(found_registration.get());
EXPECT_EQ(kRegistrationId, found_registration->id());
EXPECT_EQ(live_registration, found_registration);
found_registration = nullptr;
// Can be found by just the id too.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForIdOnly(kRegistrationId, &found_registration));
ASSERT_TRUE(found_registration.get());
EXPECT_EQ(kRegistrationId, found_registration->id());
@@ -780,7 +784,7 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
live_registration = nullptr;
// Now FindRegistrationForDocument should be async.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
ASSERT_TRUE(found_registration.get());
EXPECT_EQ(kRegistrationId, found_registration->id());
@@ -791,7 +795,8 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
EXPECT_EQ(kResource1Size + kResource2Size,
found_registration->resources_total_size_bytes());
std::vector<ServiceWorkerRegistrationInfo> all_registrations;
- EXPECT_EQ(SERVICE_WORKER_OK, GetAllRegistrationsInfos(&all_registrations));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ GetAllRegistrationsInfos(&all_registrations));
EXPECT_EQ(1u, all_registrations.size());
ServiceWorkerRegistrationInfo info = all_registrations[0];
EXPECT_EQ(kResource1Size + kResource2Size, info.stored_version_size_bytes);
@@ -801,12 +806,12 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
std::vector<scoped_refptr<ServiceWorkerRegistration>>
registrations_for_origin;
EXPECT_EQ(
- SERVICE_WORKER_OK,
+ blink::ServiceWorkerStatusCode::kOk,
GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
EXPECT_EQ(1u, registrations_for_origin.size());
registrations_for_origin.clear();
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
&registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
@@ -817,7 +822,7 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
live_version = nullptr;
// And FindRegistrationForPattern is always async.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForPattern(kScope, &found_registration));
ASSERT_TRUE(found_registration.get());
EXPECT_EQ(kRegistrationId, found_registration->id());
@@ -834,7 +839,8 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
temp_version->SetStatus(ServiceWorkerVersion::ACTIVATED);
found_registration->SetActiveVersion(temp_version);
temp_version = nullptr;
- EXPECT_EQ(SERVICE_WORKER_OK, UpdateToActiveState(found_registration));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ UpdateToActiveState(found_registration));
found_registration->set_last_update_check(kToday);
UpdateLastUpdateCheckTime(found_registration.get());
@@ -844,13 +850,13 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
scoped_refptr<ServiceWorkerRegistration> unstored_registration =
new ServiceWorkerRegistration(options, kRegistrationId + 1,
context()->AsWeakPtr());
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
UpdateToActiveState(unstored_registration));
unstored_registration = nullptr;
// The Find methods should return a registration with an active version
// and the expected update time.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
ASSERT_TRUE(found_registration.get());
EXPECT_EQ(kRegistrationId, found_registration->id());
@@ -863,21 +869,21 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
// Delete from storage but with a instance still live.
EXPECT_TRUE(context()->GetLiveVersion(kRegistrationId));
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
EXPECT_TRUE(context()->GetLiveVersion(kRegistrationId));
// Should no longer be found.
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
- FindRegistrationForId(
- kRegistrationId, kScope.GetOrigin(), &found_registration));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
+ FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
+ &found_registration));
EXPECT_FALSE(found_registration.get());
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
FindRegistrationForIdOnly(kRegistrationId, &found_registration));
EXPECT_FALSE(found_registration.get());
// Deleting an unstored registration should succeed.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
DeleteRegistration(kRegistrationId + 1, kScope.GetOrigin()));
}
@@ -902,35 +908,36 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
live_registration->SetWaitingVersion(live_version);
// Should not be findable, including by GetAllRegistrationsInfos.
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
- FindRegistrationForId(
- kRegistrationId, kScope.GetOrigin(), &found_registration));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
+ FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
+ &found_registration));
EXPECT_FALSE(found_registration.get());
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
FindRegistrationForIdOnly(kRegistrationId, &found_registration));
EXPECT_FALSE(found_registration.get());
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
EXPECT_FALSE(found_registration.get());
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
FindRegistrationForPattern(kScope, &found_registration));
EXPECT_FALSE(found_registration.get());
std::vector<ServiceWorkerRegistrationInfo> all_registrations;
- EXPECT_EQ(SERVICE_WORKER_OK, GetAllRegistrationsInfos(&all_registrations));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ GetAllRegistrationsInfos(&all_registrations));
EXPECT_TRUE(all_registrations.empty());
std::vector<scoped_refptr<ServiceWorkerRegistration>>
registrations_for_origin;
EXPECT_EQ(
- SERVICE_WORKER_OK,
+ blink::ServiceWorkerStatusCode::kOk,
GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
&registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
@@ -939,74 +946,76 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
storage()->NotifyInstallingRegistration(live_registration.get());
// Now should be findable.
- EXPECT_EQ(SERVICE_WORKER_OK,
- FindRegistrationForId(
- kRegistrationId, kScope.GetOrigin(), &found_registration));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
+ &found_registration));
EXPECT_EQ(live_registration, found_registration);
found_registration = nullptr;
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForIdOnly(kRegistrationId, &found_registration));
EXPECT_EQ(live_registration, found_registration);
found_registration = nullptr;
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
EXPECT_EQ(live_registration, found_registration);
found_registration = nullptr;
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForPattern(kScope, &found_registration));
EXPECT_EQ(live_registration, found_registration);
found_registration = nullptr;
- EXPECT_EQ(SERVICE_WORKER_OK, GetAllRegistrationsInfos(&all_registrations));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ GetAllRegistrationsInfos(&all_registrations));
EXPECT_EQ(1u, all_registrations.size());
all_registrations.clear();
// Finding by origin should provide the same result if origin is kScope.
EXPECT_EQ(
- SERVICE_WORKER_OK,
+ blink::ServiceWorkerStatusCode::kOk,
GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
EXPECT_EQ(1u, registrations_for_origin.size());
registrations_for_origin.clear();
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
&registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
// Notify storage of installation no longer happening.
- storage()->NotifyDoneInstallingRegistration(live_registration.get(), nullptr,
- SERVICE_WORKER_OK);
+ storage()->NotifyDoneInstallingRegistration(
+ live_registration.get(), nullptr, blink::ServiceWorkerStatusCode::kOk);
// Once again, should not be findable.
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
- FindRegistrationForId(
- kRegistrationId, kScope.GetOrigin(), &found_registration));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
+ FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
+ &found_registration));
EXPECT_FALSE(found_registration.get());
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
FindRegistrationForIdOnly(kRegistrationId, &found_registration));
EXPECT_FALSE(found_registration.get());
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
EXPECT_FALSE(found_registration.get());
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
FindRegistrationForPattern(kScope, &found_registration));
EXPECT_FALSE(found_registration.get());
- EXPECT_EQ(SERVICE_WORKER_OK, GetAllRegistrationsInfos(&all_registrations));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ GetAllRegistrationsInfos(&all_registrations));
EXPECT_TRUE(all_registrations.empty());
EXPECT_EQ(
- SERVICE_WORKER_OK,
+ blink::ServiceWorkerStatusCode::kOk,
GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
&registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
@@ -1020,7 +1029,7 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
// Store a registration.
scoped_refptr<ServiceWorkerRegistration> live_registration =
CreateLiveRegistrationAndVersion(kScope, kScript);
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
StoreRegistration(live_registration,
live_registration->waiting_version()));
const int64_t kRegistrationId = live_registration->id();
@@ -1028,149 +1037,151 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
// Store user data associated with the registration.
std::vector<std::string> data_out;
EXPECT_EQ(
- SERVICE_WORKER_OK,
+ blink::ServiceWorkerStatusCode::kOk,
StoreUserData(kRegistrationId, kScope.GetOrigin(), {{"key", "data"}}));
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetUserData(kRegistrationId, {"key"}, &data_out));
ASSERT_EQ(1u, data_out.size());
EXPECT_EQ("data", data_out[0]);
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
GetUserData(kRegistrationId, {"unknown_key"}, &data_out));
std::vector<std::pair<int64_t, std::string>> data_list_out;
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetUserDataForAllRegistrations("key", &data_list_out));
ASSERT_EQ(1u, data_list_out.size());
EXPECT_EQ(kRegistrationId, data_list_out[0].first);
EXPECT_EQ("data", data_list_out[0].second);
data_list_out.clear();
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetUserDataForAllRegistrations("unknown_key", &data_list_out));
EXPECT_EQ(0u, data_list_out.size());
- EXPECT_EQ(SERVICE_WORKER_OK, ClearUserData(kRegistrationId, {"key"}));
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ ClearUserData(kRegistrationId, {"key"}));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
GetUserData(kRegistrationId, {"key"}, &data_out));
// Write/overwrite multiple user data keys.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
StoreUserData(
kRegistrationId, kScope.GetOrigin(),
{{"key", "overwrite"}, {"key3", "data3"}, {"key4", "data4"}}));
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
GetUserData(kRegistrationId, {"key2"}, &data_out));
EXPECT_TRUE(data_out.empty());
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetUserData(kRegistrationId, {"key", "key3", "key4"}, &data_out));
ASSERT_EQ(3u, data_out.size());
EXPECT_EQ("overwrite", data_out[0]);
EXPECT_EQ("data3", data_out[1]);
EXPECT_EQ("data4", data_out[2]);
// Multiple gets fail if one is not found.
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
GetUserData(kRegistrationId, {"key", "key2"}, &data_out));
EXPECT_TRUE(data_out.empty());
// Delete multiple user data keys, even if some are not found.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
ClearUserData(kRegistrationId, {"key", "key2", "key3"}));
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
GetUserData(kRegistrationId, {"key"}, &data_out));
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
GetUserData(kRegistrationId, {"key2"}, &data_out));
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
GetUserData(kRegistrationId, {"key3"}, &data_out));
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetUserData(kRegistrationId, {"key4"}, &data_out));
ASSERT_EQ(1u, data_out.size());
EXPECT_EQ("data4", data_out[0]);
// Get/delete multiple user data keys by prefixes.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
StoreUserData(kRegistrationId, kScope.GetOrigin(),
{{"prefixA", "data1"},
{"prefixA2", "data2"},
{"prefixB", "data3"},
{"prefixC", "data4"}}));
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetUserDataByKeyPrefix(kRegistrationId, "prefix", &data_out));
ASSERT_EQ(4u, data_out.size());
EXPECT_EQ("data1", data_out[0]);
EXPECT_EQ("data2", data_out[1]);
EXPECT_EQ("data3", data_out[2]);
EXPECT_EQ("data4", data_out[3]);
- EXPECT_EQ(SERVICE_WORKER_OK, ClearUserDataByKeyPrefixes(
- kRegistrationId, {"prefixA", "prefixC"}));
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(
+ blink::ServiceWorkerStatusCode::kOk,
+ ClearUserDataByKeyPrefixes(kRegistrationId, {"prefixA", "prefixC"}));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetUserDataByKeyPrefix(kRegistrationId, "prefix", &data_out));
ASSERT_EQ(1u, data_out.size());
EXPECT_EQ("data3", data_out[0]);
// User data should be deleted when the associated registration is deleted.
ASSERT_EQ(
- SERVICE_WORKER_OK,
+ blink::ServiceWorkerStatusCode::kOk,
StoreUserData(kRegistrationId, kScope.GetOrigin(), {{"key", "data"}}));
- ASSERT_EQ(SERVICE_WORKER_OK,
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetUserData(kRegistrationId, {"key"}, &data_out));
ASSERT_EQ(1u, data_out.size());
ASSERT_EQ("data", data_out[0]);
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
GetUserData(kRegistrationId, {"key"}, &data_out));
data_list_out.clear();
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetUserDataForAllRegistrations("key", &data_list_out));
EXPECT_EQ(0u, data_list_out.size());
// Data access with an invalid registration id should be failed.
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
StoreUserData(blink::mojom::kInvalidServiceWorkerRegistrationId,
kScope.GetOrigin(), {{"key", "data"}}));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
GetUserData(blink::mojom::kInvalidServiceWorkerRegistrationId,
{"key"}, &data_out));
EXPECT_EQ(
- SERVICE_WORKER_ERROR_FAILED,
+ blink::ServiceWorkerStatusCode::kErrorFailed,
GetUserDataByKeyPrefix(blink::mojom::kInvalidServiceWorkerRegistrationId,
"prefix", &data_out));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
ClearUserData(blink::mojom::kInvalidServiceWorkerRegistrationId,
{"key"}));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
ClearUserDataByKeyPrefixes(
blink::mojom::kInvalidServiceWorkerRegistrationId, {"prefix"}));
// Data access with an empty key should be failed.
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
StoreUserData(kRegistrationId, kScope.GetOrigin(),
std::vector<std::pair<std::string, std::string>>()));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
StoreUserData(kRegistrationId, kScope.GetOrigin(),
{{std::string(), "data"}}));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
StoreUserData(kRegistrationId, kScope.GetOrigin(),
{{std::string(), "data"}, {"key", "data"}}));
EXPECT_EQ(
- SERVICE_WORKER_ERROR_FAILED,
+ blink::ServiceWorkerStatusCode::kErrorFailed,
GetUserData(kRegistrationId, std::vector<std::string>(), &data_out));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
GetUserDataByKeyPrefix(kRegistrationId, std::string(), &data_out));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
GetUserData(kRegistrationId, {std::string()}, &data_out));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
GetUserData(kRegistrationId, {std::string(), "key"}, &data_out));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
ClearUserData(kRegistrationId, std::vector<std::string>()));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
ClearUserData(kRegistrationId, {std::string()}));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
ClearUserData(kRegistrationId, {std::string(), "key"}));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
ClearUserDataByKeyPrefixes(kRegistrationId, {}));
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
ClearUserDataByKeyPrefixes(kRegistrationId, {std::string()}));
data_list_out.clear();
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
GetUserDataForAllRegistrations(std::string(), &data_list_out));
}
@@ -1178,7 +1189,7 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
// called.
TEST_F(ServiceWorkerStorageTest, StoreUserData_BeforeInitialize) {
const int kRegistrationId = 0;
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
StoreUserData(kRegistrationId, GURL("https://example.com"),
{{"key", "data"}}));
}
@@ -1186,23 +1197,24 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData_BeforeInitialize) {
TEST_F(ServiceWorkerStorageTest, GetUserData_BeforeInitialize) {
const int kRegistrationId = 0;
std::vector<std::string> data_out;
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
GetUserData(kRegistrationId, {"key"}, &data_out));
- EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
GetUserDataByKeyPrefix(kRegistrationId, "prefix", &data_out));
}
TEST_F(ServiceWorkerStorageTest, ClearUserData_BeforeInitialize) {
const int kRegistrationId = 0;
- EXPECT_EQ(SERVICE_WORKER_OK, ClearUserData(kRegistrationId, {"key"}));
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ ClearUserData(kRegistrationId, {"key"}));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
ClearUserDataByKeyPrefixes(kRegistrationId, {"prefix"}));
}
TEST_F(ServiceWorkerStorageTest,
GetUserDataForAllRegistrations_BeforeInitialize) {
std::vector<std::pair<int64_t, std::string>> data_list_out;
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
GetUserDataForAllRegistrations("key", &data_list_out));
EXPECT_TRUE(data_list_out.empty());
}
@@ -1257,7 +1269,7 @@ class ServiceWorkerResourceStorageTest : public ServiceWorkerStorageTest {
// Storing the registration/version should take the resources ids out
// of the uncommitted list.
EXPECT_EQ(
- SERVICE_WORKER_OK,
+ blink::ServiceWorkerStatusCode::kOk,
StoreRegistration(registration_, registration_->waiting_version()));
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -1349,7 +1361,8 @@ TEST_F(ServiceWorkerResourceStorageTest,
TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ blink::ServiceWorkerStatusCode result =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
std::set<int64_t> verify_ids;
registration_->SetWaitingVersion(nullptr);
@@ -1365,7 +1378,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
&result));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(was_called);
- EXPECT_EQ(SERVICE_WORKER_OK, result);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
EXPECT_EQ(2u, verify_ids.size());
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -1378,7 +1391,8 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ blink::ServiceWorkerStatusCode result =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
std::set<int64_t> verify_ids;
// Deleting the registration should result in the resources being added to the
@@ -1391,7 +1405,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
&result));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(was_called);
- EXPECT_EQ(SERVICE_WORKER_OK, result);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
EXPECT_EQ(2u, verify_ids.size());
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -1404,7 +1418,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
// Doom the version, now it happens.
registration_->waiting_version()->Doom();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, result);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
EXPECT_EQ(2u, verify_ids.size());
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -1427,7 +1441,8 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
registration_->active_version()->AddControllee(host.get());
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ blink::ServiceWorkerStatusCode result =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
std::set<int64_t> verify_ids;
// Deleting the registration should move the resources to the purgeable list
@@ -1439,7 +1454,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
&result));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(was_called);
- EXPECT_EQ(SERVICE_WORKER_OK, result);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
EXPECT_EQ(2u, verify_ids.size());
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -1475,7 +1490,8 @@ TEST_F(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
registration_->active_version()->AddControllee(host.get());
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ blink::ServiceWorkerStatusCode result =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
std::set<int64_t> verify_ids;
// Deleting the registration should move the resources to the purgeable list
@@ -1487,7 +1503,7 @@ TEST_F(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
&result));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(was_called);
- EXPECT_EQ(SERVICE_WORKER_OK, result);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
EXPECT_EQ(2u, verify_ids.size());
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -1549,12 +1565,13 @@ TEST_F(ServiceWorkerResourceStorageDiskTest, DeleteAndStartOver) {
ASSERT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));
base::RunLoop run_loop;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
storage()->DeleteAndStartOver(
base::BindOnce(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
run_loop.Run();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
EXPECT_TRUE(storage()->IsDisabled());
EXPECT_FALSE(base::DirectoryExists(storage()->GetDiskCachePath()));
EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
@@ -1574,12 +1591,13 @@ TEST_F(ServiceWorkerResourceStorageDiskTest,
ASSERT_TRUE(base::PathExists(file_path));
base::RunLoop run_loop;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
storage()->DeleteAndStartOver(
base::BindOnce(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
run_loop.Run();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
EXPECT_TRUE(storage()->IsDisabled());
EXPECT_FALSE(base::DirectoryExists(storage()->GetDiskCachePath()));
EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
@@ -1600,19 +1618,20 @@ TEST_F(ServiceWorkerResourceStorageDiskTest,
ASSERT_TRUE(base::PathExists(file_path));
base::RunLoop run_loop;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorNotFound;
storage()->DeleteAndStartOver(
base::BindOnce(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
run_loop.Run();
#if defined(OS_WIN)
// On Windows, deleting the directory containing an opened file should fail.
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed, status);
EXPECT_TRUE(storage()->IsDisabled());
EXPECT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
EXPECT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));
#else
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
EXPECT_TRUE(storage()->IsDisabled());
EXPECT_FALSE(base::DirectoryExists(storage()->GetDiskCachePath()));
EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
@@ -1631,7 +1650,8 @@ TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
registration_->active_version()->AddControllee(host.get());
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ blink::ServiceWorkerStatusCode result =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
std::set<int64_t> verify_ids;
// Make an updated registration.
@@ -1655,7 +1675,7 @@ TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
&result));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(was_called);
- EXPECT_EQ(SERVICE_WORKER_OK, result);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
EXPECT_EQ(2u, verify_ids.size());
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -1708,32 +1728,32 @@ TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
storage()->NotifyInstallingRegistration(live_registration3.get());
// Find a registration among installing ones.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
EXPECT_EQ(live_registration2, found_registration);
found_registration = nullptr;
// Store registrations.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
StoreRegistration(live_registration1,
live_registration1->waiting_version()));
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
StoreRegistration(live_registration2,
live_registration2->waiting_version()));
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
StoreRegistration(live_registration3,
live_registration3->waiting_version()));
// Notify storage of installations no longer happening.
- storage()->NotifyDoneInstallingRegistration(live_registration1.get(), nullptr,
- SERVICE_WORKER_OK);
- storage()->NotifyDoneInstallingRegistration(live_registration2.get(), nullptr,
- SERVICE_WORKER_OK);
- storage()->NotifyDoneInstallingRegistration(live_registration3.get(), nullptr,
- SERVICE_WORKER_OK);
+ storage()->NotifyDoneInstallingRegistration(
+ live_registration1.get(), nullptr, blink::ServiceWorkerStatusCode::kOk);
+ storage()->NotifyDoneInstallingRegistration(
+ live_registration2.get(), nullptr, blink::ServiceWorkerStatusCode::kOk);
+ storage()->NotifyDoneInstallingRegistration(
+ live_registration3.get(), nullptr, blink::ServiceWorkerStatusCode::kOk);
// Find a registration among installed ones.
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
EXPECT_EQ(live_registration2, found_registration);
}
@@ -1780,13 +1800,13 @@ TEST_F(ServiceWorkerStorageTest, OriginTrialsAbsentEntryAndEmptyEntry) {
scoped_refptr<ServiceWorkerRegistration> found_registration;
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(scope1, &found_registration));
ASSERT_TRUE(found_registration->active_version());
// origin_trial_tokens must be unset.
EXPECT_FALSE(found_registration->active_version()->origin_trial_tokens());
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(scope2, &found_registration));
ASSERT_TRUE(found_registration->active_version());
// Empty origin_trial_tokens must exist.
@@ -1901,7 +1921,8 @@ TEST_F(ServiceWorkerStorageOriginTrialsDiskTest, FromMainScript) {
version->SetStatus(ServiceWorkerVersion::INSTALLED);
registration->SetActiveVersion(version);
- EXPECT_EQ(SERVICE_WORKER_OK, StoreRegistration(registration, version));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ StoreRegistration(registration, version));
// Simulate browser shutdown and restart.
registration = nullptr;
@@ -1910,7 +1931,7 @@ TEST_F(ServiceWorkerStorageOriginTrialsDiskTest, FromMainScript) {
LazyInitialize();
scoped_refptr<ServiceWorkerRegistration> found_registration;
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(kScope, &found_registration));
ASSERT_TRUE(found_registration->active_version());
const blink::TrialTokenValidator::FeatureToTokensMap& found_tokens =
@@ -1940,7 +1961,7 @@ TEST_F(ServiceWorkerStorageTest, AbsentNavigationPreloadState) {
WriteRegistration(data1, resources1);
scoped_refptr<ServiceWorkerRegistration> found_registration;
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(scope1, &found_registration));
const blink::mojom::NavigationPreloadState& registration_state =
found_registration->navigation_preload_state();
@@ -1980,7 +2001,7 @@ TEST_F(ServiceWorkerStorageDiskTest, RegisteredOriginCount) {
// Store all registrations.
for (const auto& registration : registrations) {
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
StoreRegistration(registration, registration->waiting_version()));
}
@@ -2017,7 +2038,8 @@ TEST_F(ServiceWorkerStorageDiskTest, DisabledNavigationPreloadState) {
registration->SetActiveVersion(version);
registration->EnableNavigationPreload(false);
- EXPECT_EQ(SERVICE_WORKER_OK, StoreRegistration(registration, version));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ StoreRegistration(registration, version));
// Simulate browser shutdown and restart.
registration = nullptr;
@@ -2026,7 +2048,7 @@ TEST_F(ServiceWorkerStorageDiskTest, DisabledNavigationPreloadState) {
LazyInitialize();
scoped_refptr<ServiceWorkerRegistration> found_registration;
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(kScope, &found_registration));
const blink::mojom::NavigationPreloadState& registration_state =
found_registration->navigation_preload_state();
@@ -2054,7 +2076,8 @@ TEST_F(ServiceWorkerStorageDiskTest, EnabledNavigationPreloadState) {
registration->EnableNavigationPreload(true);
registration->SetNavigationPreloadHeader(kHeaderValue);
- EXPECT_EQ(SERVICE_WORKER_OK, StoreRegistration(registration, version));
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
+ StoreRegistration(registration, version));
// Simulate browser shutdown and restart.
registration = nullptr;
@@ -2063,7 +2086,7 @@ TEST_F(ServiceWorkerStorageDiskTest, EnabledNavigationPreloadState) {
LazyInitialize();
scoped_refptr<ServiceWorkerRegistration> found_registration;
- EXPECT_EQ(SERVICE_WORKER_OK,
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
FindRegistrationForDocument(kScope, &found_registration));
const blink::mojom::NavigationPreloadState& registration_state =
found_registration->navigation_preload_state();
diff --git a/chromium/content/browser/service_worker/service_worker_test_utils.cc b/chromium/content/browser/service_worker/service_worker_test_utils.cc
index d01073ccaeb..384440dc50c 100644
--- a/chromium/content/browser/service_worker/service_worker_test_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_test_utils.cc
@@ -13,20 +13,73 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_database.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
-#include "content/common/service_worker/service_worker_provider.mojom.h"
#include "content/public/common/child_process_host.h"
#include "net/base/io_buffer.h"
#include "net/base/test_completion_callback.h"
#include "net/http/http_response_info.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
namespace {
+// A mock SharedURLLoaderFactory that always fails to start.
+// TODO(bashi): Make this factory not to fail when unit tests actually need
+// this to be working.
+class MockSharedURLLoaderFactory final
+ : public network::SharedURLLoaderFactory {
+ public:
+ MockSharedURLLoaderFactory() = default;
+
+ // network::mojom::URLLoaderFactory:
+ void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& url_request,
+ network::mojom::URLLoaderClientPtr client,
+ const net::MutableNetworkTrafficAnnotationTag&
+ traffic_annotation) override {
+ client->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_NOT_IMPLEMENTED));
+ }
+ void Clone(network::mojom::URLLoaderFactoryRequest request) override {
+ NOTREACHED();
+ }
+
+ // network::SharedURLLoaderFactory:
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override {
+ NOTREACHED();
+ return nullptr;
+ }
+
+ private:
+ friend class base::RefCounted<MockSharedURLLoaderFactory>;
+
+ ~MockSharedURLLoaderFactory() override = default;
+
+ DISALLOW_COPY_AND_ASSIGN(MockSharedURLLoaderFactory);
+};
+
+// Returns MockSharedURLLoaderFactory.
+class MockSharedURLLoaderFactoryInfo final
+ : public network::SharedURLLoaderFactoryInfo {
+ public:
+ MockSharedURLLoaderFactoryInfo() = default;
+ ~MockSharedURLLoaderFactoryInfo() override = default;
+
+ protected:
+ scoped_refptr<network::SharedURLLoaderFactory> CreateFactory() override {
+ return base::MakeRefCounted<MockSharedURLLoaderFactory>();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockSharedURLLoaderFactoryInfo);
+};
+
void OnWriteBodyInfoToDiskCache(
std::unique_ptr<ServiceWorkerResponseWriter> writer,
const std::string& body,
@@ -90,11 +143,12 @@ ServiceWorkerRemoteProviderEndpoint::ServiceWorkerRemoteProviderEndpoint(
ServiceWorkerRemoteProviderEndpoint::~ServiceWorkerRemoteProviderEndpoint() {}
void ServiceWorkerRemoteProviderEndpoint::BindWithProviderHostInfo(
- content::ServiceWorkerProviderHostInfo* info) {
+ mojom::ServiceWorkerProviderHostInfoPtr* info) {
mojom::ServiceWorkerContainerAssociatedPtr client_ptr;
client_request_ = mojo::MakeRequestAssociatedWithDedicatedPipe(&client_ptr);
- info->client_ptr_info = client_ptr.PassInterface();
- info->host_request = mojo::MakeRequestAssociatedWithDedicatedPipe(&host_ptr_);
+ (*info)->client_ptr_info = client_ptr.PassInterface();
+ (*info)->host_request =
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&host_ptr_);
}
void ServiceWorkerRemoteProviderEndpoint::BindWithProviderInfo(
@@ -103,58 +157,57 @@ void ServiceWorkerRemoteProviderEndpoint::BindWithProviderInfo(
host_ptr_.Bind(std::move(info->host_ptr_info));
}
+mojom::ServiceWorkerProviderHostInfoPtr CreateProviderHostInfoForWindow(
+ int provider_id,
+ int route_id) {
+ return mojom::ServiceWorkerProviderHostInfo::New(
+ provider_id, route_id,
+ blink::mojom::ServiceWorkerProviderType::kForWindow,
+ true /* is_parent_frame_secure */, nullptr /* host_request */,
+ nullptr /* client_ptr_info */);
+}
+
std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow(
int process_id,
int provider_id,
bool is_parent_frame_secure,
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerRemoteProviderEndpoint* output_endpoint) {
- ServiceWorkerProviderHostInfo info(
- provider_id, 1 /* route_id */,
- blink::mojom::ServiceWorkerProviderType::kForWindow,
- is_parent_frame_secure);
+ mojom::ServiceWorkerProviderHostInfoPtr info =
+ CreateProviderHostInfoForWindow(provider_id, 1 /* route_id */);
+ info->is_parent_frame_secure = is_parent_frame_secure;
output_endpoint->BindWithProviderHostInfo(&info);
return ServiceWorkerProviderHost::Create(process_id, std::move(info),
- std::move(context), nullptr);
+ std::move(context));
}
-std::unique_ptr<ServiceWorkerProviderHost>
+base::WeakPtr<ServiceWorkerProviderHost>
CreateProviderHostForServiceWorkerContext(
int process_id,
bool is_parent_frame_secure,
ServiceWorkerVersion* hosted_version,
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerRemoteProviderEndpoint* output_endpoint) {
- ServiceWorkerProviderHostInfo info(
- kInvalidServiceWorkerProviderId, MSG_ROUTING_NONE,
- blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
- is_parent_frame_secure);
- std::unique_ptr<ServiceWorkerProviderHost> host =
- ServiceWorkerProviderHost::PreCreateForController(std::move(context));
+ auto provider_info = mojom::ServiceWorkerProviderInfoForStartWorker::New();
+ base::WeakPtr<ServiceWorkerProviderHost> host =
+ ServiceWorkerProviderHost::PreCreateForController(
+ std::move(context), base::WrapRefCounted(hosted_version),
+ &provider_info);
+
host->SetDocumentUrl(hosted_version->script_url());
- mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info =
- host->CompleteStartWorkerPreparation(
- process_id, hosted_version, nullptr /* non_network_loader_factory */);
+
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory;
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ loader_factory = network::SharedURLLoaderFactory::Create(
+ std::make_unique<MockSharedURLLoaderFactoryInfo>());
+ }
+
+ provider_info = host->CompleteStartWorkerPreparation(
+ process_id, loader_factory, std::move(provider_info));
output_endpoint->BindWithProviderInfo(std::move(provider_info));
return host;
}
-std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostWithDispatcherHost(
- int process_id,
- int provider_id,
- base::WeakPtr<ServiceWorkerContextCore> context,
- int route_id,
- ServiceWorkerDispatcherHost* dispatcher_host,
- ServiceWorkerRemoteProviderEndpoint* output_endpoint) {
- ServiceWorkerProviderHostInfo info(
- provider_id, route_id,
- blink::mojom::ServiceWorkerProviderType::kForWindow, true);
- output_endpoint->BindWithProviderHostInfo(&info);
- return ServiceWorkerProviderHost::Create(process_id, std::move(info),
- std::move(context),
- dispatcher_host->AsWeakPtr());
-}
-
ServiceWorkerDatabase::ResourceRecord WriteToDiskCacheSync(
ServiceWorkerStorage* storage,
const GURL& script_url,
diff --git a/chromium/content/browser/service_worker/service_worker_test_utils.h b/chromium/content/browser/service_worker/service_worker_test_utils.h
index 859b06d488f..7b550c6efd0 100644
--- a/chromium/content/browser/service_worker/service_worker_test_utils.h
+++ b/chromium/content/browser/service_worker/service_worker_test_utils.h
@@ -27,35 +27,35 @@ class HttpResponseInfo;
namespace content {
class ServiceWorkerContextCore;
-class ServiceWorkerDispatcherHost;
class ServiceWorkerProviderHost;
class ServiceWorkerStorage;
class ServiceWorkerVersion;
-struct ServiceWorkerProviderHostInfo;
template <typename Arg>
void ReceiveResult(BrowserThread::ID run_quit_thread,
const base::Closure& quit,
- Arg* out, Arg actual) {
+ base::Optional<Arg>* out,
+ Arg actual) {
*out = actual;
if (!quit.is_null())
BrowserThread::PostTask(run_quit_thread, FROM_HERE, quit);
}
-template <typename Arg> base::Callback<void(Arg)>
-CreateReceiver(BrowserThread::ID run_quit_thread,
- const base::Closure& quit, Arg* out) {
- return base::Bind(&ReceiveResult<Arg>, run_quit_thread, quit, out);
+template <typename Arg>
+base::OnceCallback<void(Arg)> CreateReceiver(BrowserThread::ID run_quit_thread,
+ const base::RepeatingClosure& quit,
+ base::Optional<Arg>* out) {
+ return base::BindOnce(&ReceiveResult<Arg>, run_quit_thread, quit, out);
}
template <typename Arg>
-base::Callback<void(Arg)> CreateReceiverOnCurrentThread(
- Arg* out,
+base::OnceCallback<void(Arg)> CreateReceiverOnCurrentThread(
+ base::Optional<Arg>* out,
const base::Closure& quit = base::Closure()) {
BrowserThread::ID id;
bool ret = BrowserThread::GetCurrentThreadIdentifier(&id);
DCHECK(ret);
- return base::Bind(&ReceiveResult<Arg>, id, quit, out);
+ return CreateReceiver(id, quit, out);
}
// Container for keeping the Mojo connection to the service worker provider on
@@ -67,7 +67,7 @@ class ServiceWorkerRemoteProviderEndpoint {
ServiceWorkerRemoteProviderEndpoint&& other);
~ServiceWorkerRemoteProviderEndpoint();
- void BindWithProviderHostInfo(ServiceWorkerProviderHostInfo* info);
+ void BindWithProviderHostInfo(mojom::ServiceWorkerProviderHostInfoPtr* info);
void BindWithProviderInfo(
mojom::ServiceWorkerProviderInfoForStartWorkerPtr info);
@@ -90,6 +90,10 @@ class ServiceWorkerRemoteProviderEndpoint {
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRemoteProviderEndpoint);
};
+mojom::ServiceWorkerProviderHostInfoPtr CreateProviderHostInfoForWindow(
+ int provider_id,
+ int route_id);
+
std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow(
int process_id,
int provider_id,
@@ -97,7 +101,7 @@ std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow(
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerRemoteProviderEndpoint* output_endpoint);
-std::unique_ptr<ServiceWorkerProviderHost>
+base::WeakPtr<ServiceWorkerProviderHost>
CreateProviderHostForServiceWorkerContext(
int process_id,
bool is_parent_frame_secure,
@@ -105,14 +109,6 @@ CreateProviderHostForServiceWorkerContext(
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerRemoteProviderEndpoint* output_endpoint);
-std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostWithDispatcherHost(
- int process_id,
- int provider_id,
- base::WeakPtr<ServiceWorkerContextCore> context,
- int route_id,
- ServiceWorkerDispatcherHost* dispatcher_host,
- ServiceWorkerRemoteProviderEndpoint* output_endpoint);
-
// Writes the script down to |storage| synchronously. This should not be used in
// base::RunLoop since base::RunLoop is used internally to wait for completing
// all of tasks. If it's in another base::RunLoop, consider to use
diff --git a/chromium/content/browser/service_worker/service_worker_type_converters.cc b/chromium/content/browser/service_worker/service_worker_type_converters.cc
index 4bdb3cc82af..163959c53b5 100644
--- a/chromium/content/browser/service_worker/service_worker_type_converters.cc
+++ b/chromium/content/browser/service_worker/service_worker_type_converters.cc
@@ -34,20 +34,4 @@ TypeConverter<blink::mojom::ServiceWorkerState,
return blink::mojom::ServiceWorkerState::kUnknown;
}
-content::ServiceWorkerStatusCode
-TypeConverter<content::ServiceWorkerStatusCode,
- blink::mojom::ServiceWorkerEventStatus>::
- Convert(blink::mojom::ServiceWorkerEventStatus status) {
- switch (status) {
- case blink::mojom::ServiceWorkerEventStatus::COMPLETED:
- return content::SERVICE_WORKER_OK;
- case blink::mojom::ServiceWorkerEventStatus::REJECTED:
- return content::SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED;
- case blink::mojom::ServiceWorkerEventStatus::ABORTED:
- return content::SERVICE_WORKER_ERROR_ABORT;
- }
- NOTREACHED() << status;
- return content::SERVICE_WORKER_ERROR_FAILED;
-}
-
} // namespace mojo
diff --git a/chromium/content/browser/service_worker/service_worker_type_converters.h b/chromium/content/browser/service_worker/service_worker_type_converters.h
index 207ef89cc3c..cd53395549a 100644
--- a/chromium/content/browser/service_worker/service_worker_type_converters.h
+++ b/chromium/content/browser/service_worker/service_worker_type_converters.h
@@ -2,12 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STATE_CONVERTERS_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STATE_CONVERTERS_H_
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_TYPE_CONVERTERS_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_TYPE_CONVERTERS_H_
#include "content/browser/service_worker/service_worker_version.h"
-#include "content/common/service_worker/service_worker_status_code.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_state.mojom.h"
namespace mojo {
@@ -19,13 +17,6 @@ struct CONTENT_EXPORT TypeConverter<blink::mojom::ServiceWorkerState,
content::ServiceWorkerVersion::Status status);
};
-template <>
-struct CONTENT_EXPORT TypeConverter<content::ServiceWorkerStatusCode,
- blink::mojom::ServiceWorkerEventStatus> {
- static content::ServiceWorkerStatusCode Convert(
- blink::mojom::ServiceWorkerEventStatus status);
-};
-
} // namespace mojo
-#endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_STATE_CONVERTERS_H_
+#endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TYPE_CONVERTERS_H_
diff --git a/chromium/content/browser/service_worker/service_worker_unregister_job.cc b/chromium/content/browser/service_worker/service_worker_unregister_job.cc
index 64eb79e375d..9b063838484 100644
--- a/chromium/content/browser/service_worker/service_worker_unregister_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_unregister_job.cc
@@ -40,7 +40,7 @@ void ServiceWorkerUnregisterJob::Start() {
void ServiceWorkerUnregisterJob::Abort() {
CompleteInternal(blink::mojom::kInvalidServiceWorkerRegistrationId,
- SERVICE_WORKER_ERROR_ABORT);
+ blink::ServiceWorkerStatusCode::kErrorAbort);
}
bool ServiceWorkerUnregisterJob::Equals(
@@ -55,16 +55,17 @@ RegistrationJobType ServiceWorkerUnregisterJob::GetType() const {
}
void ServiceWorkerUnregisterJob::OnRegistrationFound(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
- if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
+ if (status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
DCHECK(!registration.get());
Complete(blink::mojom::kInvalidServiceWorkerRegistrationId,
- SERVICE_WORKER_ERROR_NOT_FOUND);
+ blink::ServiceWorkerStatusCode::kErrorNotFound);
return;
}
- if (status != SERVICE_WORKER_OK || registration->is_uninstalling()) {
+ if (status != blink::ServiceWorkerStatusCode::kOk ||
+ registration->is_uninstalling()) {
Complete(blink::mojom::kInvalidServiceWorkerRegistrationId, status);
return;
}
@@ -72,29 +73,30 @@ void ServiceWorkerUnregisterJob::OnRegistrationFound(
// TODO: "7. If registration.updatePromise is not null..."
// "8. Resolve promise."
- ResolvePromise(registration->id(), SERVICE_WORKER_OK);
+ ResolvePromise(registration->id(), blink::ServiceWorkerStatusCode::kOk);
registration->ClearWhenReady();
- Complete(registration->id(), SERVICE_WORKER_OK);
+ Complete(registration->id(), blink::ServiceWorkerStatusCode::kOk);
}
-void ServiceWorkerUnregisterJob::Complete(int64_t registration_id,
- ServiceWorkerStatusCode status) {
+void ServiceWorkerUnregisterJob::Complete(
+ int64_t registration_id,
+ blink::ServiceWorkerStatusCode status) {
CompleteInternal(registration_id, status);
context_->job_coordinator()->FinishJob(pattern_, this);
}
void ServiceWorkerUnregisterJob::CompleteInternal(
int64_t registration_id,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
if (!is_promise_resolved_)
ResolvePromise(registration_id, status);
}
void ServiceWorkerUnregisterJob::ResolvePromise(
int64_t registration_id,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
DCHECK(!is_promise_resolved_);
is_promise_resolved_ = true;
for (UnregistrationCallback& callback : callbacks_)
diff --git a/chromium/content/browser/service_worker/service_worker_unregister_job.h b/chromium/content/browser/service_worker/service_worker_unregister_job.h
index 0ded1bb3cd1..1c86888aa76 100644
--- a/chromium/content/browser/service_worker/service_worker_unregister_job.h
+++ b/chromium/content/browser/service_worker/service_worker_unregister_job.h
@@ -13,7 +13,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_register_job_base.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
namespace content {
@@ -29,7 +29,7 @@ class ServiceWorkerRegistration;
class ServiceWorkerUnregisterJob : public ServiceWorkerRegisterJobBase {
public:
typedef base::OnceCallback<void(int64_t registration_id,
- ServiceWorkerStatusCode status)>
+ blink::ServiceWorkerStatusCode status)>
UnregistrationCallback;
ServiceWorkerUnregisterJob(base::WeakPtr<ServiceWorkerContextCore> context,
@@ -48,12 +48,13 @@ class ServiceWorkerUnregisterJob : public ServiceWorkerRegisterJobBase {
private:
void OnRegistrationFound(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
- void Complete(int64_t registration_id, ServiceWorkerStatusCode status);
+ void Complete(int64_t registration_id, blink::ServiceWorkerStatusCode status);
void CompleteInternal(int64_t registration_id,
- ServiceWorkerStatusCode status);
- void ResolvePromise(int64_t registration_id, ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
+ void ResolvePromise(int64_t registration_id,
+ blink::ServiceWorkerStatusCode status);
base::WeakPtr<ServiceWorkerContextCore> context_;
const GURL pattern_;
diff --git a/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc b/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc
index 67c69af0b3c..52fc1fc8fe3 100644
--- a/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc
@@ -39,7 +39,10 @@ void ServiceWorkerURLJobWrapper::FallbackToNetwork() {
void ServiceWorkerURLJobWrapper::FallbackToNetworkOrRenderer() {
if (url_loader_job_) {
- url_loader_job_->FallbackToNetworkOrRenderer();
+ // Fallback to renderer is used when CORS checks need to be performed on the
+ // request. CORS doesn't apply to navigations, and |url_loader_job_| is for
+ // navigations, so just use FallbackToNetwork().
+ url_loader_job_->FallbackToNetwork();
} else {
url_request_job_->FallbackToNetworkOrRenderer();
}
@@ -62,11 +65,10 @@ bool ServiceWorkerURLJobWrapper::ShouldFallbackToNetwork() {
}
void ServiceWorkerURLJobWrapper::FailDueToLostController() {
- if (url_loader_job_) {
- url_loader_job_->FailDueToLostController();
- } else {
- url_request_job_->FailDueToLostController();
- }
+ // This function is only called for subresource requests, so it can't
+ // be called for |url_loader_job_|, which is for navigations.
+ DCHECK(!url_loader_job_);
+ url_request_job_->FailDueToLostController();
}
bool ServiceWorkerURLJobWrapper::WasCanceled() const {
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 0405cdb5dfa..c40adc1c9bb 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
@@ -106,12 +106,6 @@ net::NetLogEventType RequestJobResultToNetEventType(
return n::SERVICE_WORKER_ERROR_BAD_DELEGATE;
case m::REQUEST_JOB_ERROR_REQUEST_BODY_BLOB_FAILED:
return n::SERVICE_WORKER_ERROR_REQUEST_BODY_BLOB_FAILED;
- // We can't log if there's no request; fallthrough.
- case m::REQUEST_JOB_ERROR_NO_REQUEST:
- // Obsolete types; fallthrough.
- case m::REQUEST_JOB_ERROR_DESTROYED:
- case m::REQUEST_JOB_ERROR_DESTROYED_WITH_BLOB:
- case m::REQUEST_JOB_ERROR_DESTROYED_WITH_STREAM:
// Invalid type.
case m::NUM_REQUEST_JOB_RESULT_TYPES:
NOTREACHED() << result;
@@ -662,7 +656,7 @@ void ServiceWorkerURLRequestJob::DidPrepareFetchEvent(
}
void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
@@ -685,7 +679,7 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
return;
}
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_FETCH_EVENT_DISPATCH);
if (IsMainResourceLoad()) {
// Using the service worker failed, so fallback to network.
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 9d25a9c5a9b..5c8f00e1ee7 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
@@ -23,8 +23,7 @@
#include "content/browser/service_worker/service_worker_response_type.h"
#include "content/browser/service_worker/service_worker_url_job_wrapper.h"
#include "content/common/content_export.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
@@ -37,6 +36,7 @@
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "storage/common/blob_storage/blob_storage_constants.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
namespace net {
@@ -188,7 +188,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
// For FORWARD_TO_SERVICE_WORKER case.
void DidPrepareFetchEvent(scoped_refptr<ServiceWorkerVersion> version);
void DidDispatchFetchEvent(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
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 094bfb5e5f4..ce237a44d28 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
@@ -14,7 +14,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -31,7 +31,6 @@
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/service_worker_messages.h"
-#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/blob_handle.h"
@@ -61,6 +60,7 @@
#include "storage/browser/blob/blob_url_request_job_factory.h"
#include "storage/common/blob_storage/blob_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h"
@@ -156,8 +156,8 @@ std::unique_ptr<ServiceWorkerHeaderMap> MakeHeaders() {
return headers;
}
-void SaveStatusCallback(ServiceWorkerStatusCode* out_status,
- ServiceWorkerStatusCode status) {
+void SaveStatusCallback(blink::ServiceWorkerStatusCode* out_status,
+ blink::ServiceWorkerStatusCode status) {
*out_status = status;
}
@@ -231,13 +231,13 @@ class ServiceWorkerURLRequestJobTest
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
// Make the registration findable via storage functions.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
helper_->context()->storage()->StoreRegistration(
registration_.get(),
version_.get(),
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(SERVICE_WORKER_OK, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
// Create a controlled client.
std::unique_ptr<ServiceWorkerProviderHost> provider_host =
@@ -497,7 +497,7 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
const GURL& scope,
const GURL& script_url,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -508,7 +508,7 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
scope_ = scope;
script_url_ = script_url;
pause_after_download_ = pause_after_download;
- start_worker_request_ = std::move(dispatcher_request);
+ start_worker_request_ = std::move(service_worker_request);
controller_request_ = std::move(controller_request);
start_worker_instance_host_ = std::move(instance_host);
provider_info_ = std::move(provider_info);
@@ -518,10 +518,10 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
void OnFetchEvent(
int embedded_worker_id,
const network::ResourceRequest& /* request */,
- mojom::FetchEventPreloadHandlePtr preload_handle,
+ blink::mojom::FetchEventPreloadHandlePtr preload_handle,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback) override {
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
+ override {
embedded_worker_id_ = embedded_worker_id;
response_callback_ = std::move(response_callback);
finish_callback_ = std::move(finish_callback);
@@ -533,7 +533,7 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
GURL scope_;
GURL script_url_;
bool pause_after_download_;
- mojom::ServiceWorkerEventDispatcherRequest start_worker_request_;
+ mojom::ServiceWorkerRequest start_worker_request_;
mojom::ControllerServiceWorkerRequest controller_request_;
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
start_worker_instance_host_;
@@ -541,9 +541,8 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info_;
int embedded_worker_id_ = 0;
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_;
- mojom::FetchEventPreloadHandlePtr preload_handle_;
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback_;
+ blink::mojom::FetchEventPreloadHandlePtr preload_handle_;
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback_;
ServiceWorkerURLRequestJobTest* test_;
DISALLOW_COPY_AND_ASSIGN(DelayHelper);
};
@@ -554,14 +553,15 @@ TEST_F(ServiceWorkerURLRequestJobTest,
DelayHelper* helper = static_cast<DelayHelper*>(helper_.get());
// Start the worker before the navigation.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ blink::ServiceWorkerStatusCode status =
+ blink::ServiceWorkerStatusCode::kErrorFailed;
base::HistogramTester histogram_tester;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
base::BindOnce(&SaveStatusCallback, &status));
base::RunLoop().RunUntilIdle();
helper->CompleteStartWorker();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
// Do the navigation.
SetUpNavigationPreloadTest(RESOURCE_TYPE_MAIN_FRAME);
@@ -696,10 +696,10 @@ class ProviderDeleteHelper : public EmbeddedWorkerTestHelper {
void OnFetchEvent(
int /* embedded_worker_id */,
const network::ResourceRequest& /* request */,
- mojom::FetchEventPreloadHandlePtr /* preload_handle */,
+ blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback) override {
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
+ override {
context()->RemoveProviderHost(mock_render_process_id(), kProviderID);
response_callback->OnResponse(
ServiceWorkerResponse(
@@ -786,10 +786,10 @@ class BlobResponder : public EmbeddedWorkerTestHelper {
void OnFetchEvent(
int /* embedded_worker_id */,
const network::ResourceRequest& /* request */,
- mojom::FetchEventPreloadHandlePtr /* preload_handle */,
+ blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback) override {
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
+ override {
response_callback->OnResponse(
ServiceWorkerResponse(
std::make_unique<std::vector<GURL>>(), 200, "OK",
@@ -887,10 +887,10 @@ class StreamResponder : public EmbeddedWorkerTestHelper {
void OnFetchEvent(
int /* embedded_worker_id */,
const network::ResourceRequest& /* request */,
- mojom::FetchEventPreloadHandlePtr /* preload_handle */,
+ blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback) override {
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
+ override {
ASSERT_FALSE(stream_handle_.is_null());
response_callback->OnResponseStream(
ServiceWorkerResponse(
@@ -1277,10 +1277,10 @@ class FailFetchHelper : public EmbeddedWorkerTestHelper {
void OnFetchEvent(
int embedded_worker_id,
const network::ResourceRequest& /* request */,
- mojom::FetchEventPreloadHandlePtr /* preload_handle */,
+ blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
mojom::ServiceWorkerFetchResponseCallbackPtr /* response_callback */,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback) override {
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
+ override {
SimulateWorkerStopped(embedded_worker_id);
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::ABORTED,
@@ -1370,10 +1370,10 @@ class EarlyResponseHelper : public EmbeddedWorkerTestHelper {
void OnFetchEvent(
int /* embedded_worker_id */,
const network::ResourceRequest& /* request */,
- mojom::FetchEventPreloadHandlePtr /* preload_handle */,
+ blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback) override {
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
+ override {
finish_callback_ = std::move(finish_callback);
response_callback->OnResponse(
ServiceWorkerResponse(
@@ -1390,8 +1390,7 @@ class EarlyResponseHelper : public EmbeddedWorkerTestHelper {
}
private:
- mojom::ServiceWorkerEventDispatcher::DispatchFetchEventCallback
- finish_callback_;
+ mojom::ServiceWorker::DispatchFetchEventCallback finish_callback_;
DISALLOW_COPY_AND_ASSIGN(EarlyResponseHelper);
};
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
index bfe78b055f3..8d58920080e 100644
--- a/chromium/content/browser/service_worker/service_worker_version.cc
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -30,7 +30,6 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_installed_scripts_sender.h"
#include "content/browser/service_worker/service_worker_registration.h"
-#include "content/browser/service_worker/service_worker_type_converters.h"
#include "content/common/service_worker/embedded_worker.mojom.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_utils.h"
@@ -44,6 +43,8 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+#include "third_party/blink/public/common/service_worker/service_worker_type_converters.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
@@ -62,9 +63,6 @@ constexpr base::TimeDelta kRequestTimeout = base::TimeDelta::FromMinutes(5);
// Time to wait until stopping an idle worker.
constexpr base::TimeDelta kIdleWorkerTimeout = base::TimeDelta::FromSeconds(30);
-// Timeout for waiting for a response to a ping.
-constexpr base::TimeDelta kPingTimeout = base::TimeDelta::FromSeconds(30);
-
// Default delay for scheduled update.
constexpr base::TimeDelta kUpdateDelay = base::TimeDelta::FromSeconds(1);
@@ -98,13 +96,14 @@ void RunCallbacks(ServiceWorkerVersion* version,
// An adapter to run a |callback| after StartWorker.
void RunCallbackAfterStartWorker(base::WeakPtr<ServiceWorkerVersion> version,
ServiceWorkerVersion::StatusCallback callback,
- ServiceWorkerStatusCode status) {
- if (status == SERVICE_WORKER_OK &&
+ blink::ServiceWorkerStatusCode status) {
+ if (status == blink::ServiceWorkerStatusCode::kOk &&
version->running_status() != EmbeddedWorkerStatus::RUNNING) {
// We've tried to start the worker (and it has succeeded), but
// it looks it's not running yet.
NOTREACHED() << "The worker's not running after successful StartWorker";
- std::move(callback).Run(SERVICE_WORKER_ERROR_START_WORKER_FAILED);
+ std::move(callback).Run(
+ blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed);
return;
}
std::move(callback).Run(status);
@@ -146,8 +145,7 @@ int NextTraceId() {
return trace_id;
}
-void OnEventDispatcherConnectionError(
- base::WeakPtr<EmbeddedWorkerInstance> embedded_worker) {
+void OnConnectionError(base::WeakPtr<EmbeddedWorkerInstance> embedded_worker) {
if (!embedded_worker)
return;
@@ -165,30 +163,12 @@ void OnEventDispatcherConnectionError(
}
}
-// In S13nServiceWorker, |loader_factory| is the factory to use loading new
-// scripts from network (or other sources, e.g., for chrome-extension:// URLs).
-mojom::ServiceWorkerProviderInfoForStartWorkerPtr
-CompleteProviderHostPreparation(
- ServiceWorkerVersion* version,
- std::unique_ptr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<ServiceWorkerContextCore> context,
- int process_id,
- scoped_refptr<network::SharedURLLoaderFactory> loader_factory) {
- // Caller should ensure |context| is alive when completing StartWorker
- // preparation.
- DCHECK(context);
- auto info = provider_host->CompleteStartWorkerPreparation(
- process_id, version, std::move(loader_factory));
- context->AddProviderHost(std::move(provider_host));
- return info;
-}
-
void OnOpenWindowFinished(
blink::mojom::ServiceWorkerHost::OpenNewTabCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
blink::mojom::ServiceWorkerClientInfoPtr client_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const bool success = (status == SERVICE_WORKER_OK);
+ const bool success = (status == blink::ServiceWorkerStatusCode::kOk);
base::Optional<std::string> error_msg;
if (!success) {
DCHECK(!client_info);
@@ -210,7 +190,8 @@ void DidShowPaymentHandlerWindow(
base::BindOnce(&OnOpenWindowFinished, std::move(callback)),
render_process_id, render_frame_id);
} else {
- OnOpenWindowFinished(std::move(callback), SERVICE_WORKER_ERROR_FAILED,
+ OnOpenWindowFinished(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorFailed,
nullptr /* client_info */);
}
}
@@ -226,10 +207,10 @@ void DidGetClients(
void DidNavigateClient(
blink::mojom::ServiceWorkerHost::NavigateClientCallback callback,
const GURL& url,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
blink::mojom::ServiceWorkerClientInfoPtr client) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const bool success = (status == SERVICE_WORKER_OK);
+ const bool success = (status == blink::ServiceWorkerStatusCode::kOk);
base::Optional<std::string> error_msg;
if (!success) {
DCHECK(!client);
@@ -262,57 +243,6 @@ base::TimeDelta ServiceWorkerVersion::GetTickDuration(
return tick_clock_->NowTicks() - time;
}
-// A controller for periodically sending a ping to the worker to see
-// if the worker is not stalling.
-class ServiceWorkerVersion::PingController {
- public:
- explicit PingController(ServiceWorkerVersion* version) : version_(version) {}
- ~PingController() {}
-
- void Activate() { ping_state_ = PINGING; }
-
- void Deactivate() {
- ClearTick(&ping_time_);
- ping_state_ = NOT_PINGING;
- }
-
- void OnPongReceived() { ClearTick(&ping_time_); }
-
- bool IsTimedOut() { return ping_state_ == PING_TIMED_OUT; }
-
- // Checks ping status. This is supposed to be called periodically.
- // This may call:
- // - OnPingTimeout() if the worker hasn't reponded within a certain period.
- // - PingWorker() if we're running ping timer and can send next ping.
- void CheckPingStatus() {
- if (version_->GetTickDuration(ping_time_) > kPingTimeout) {
- ping_state_ = PING_TIMED_OUT;
- version_->OnPingTimeout();
- return;
- }
-
- // Check if we want to send a next ping.
- if (ping_state_ != PINGING || !ping_time_.is_null())
- return;
-
- version_->PingWorker();
- version_->RestartTick(&ping_time_);
- }
-
- void SimulateTimeoutForTesting() {
- version_->PingWorker();
- ping_state_ = PING_TIMED_OUT;
- version_->OnPingTimeout();
- }
-
- private:
- enum PingState { NOT_PINGING, PINGING, PING_TIMED_OUT };
- ServiceWorkerVersion* version_; // Not owned.
- base::TimeTicks ping_time_;
- PingState ping_state_ = NOT_PINGING;
- DISALLOW_COPY_AND_ASSIGN(PingController);
-};
-
ServiceWorkerVersion::ServiceWorkerVersion(
ServiceWorkerRegistration* registration,
const GURL& script_url,
@@ -330,7 +260,7 @@ ServiceWorkerVersion::ServiceWorkerVersion(
script_cache_map_(this, context),
tick_clock_(base::DefaultTickClock::GetInstance()),
clock_(base::DefaultClock::GetInstance()),
- ping_controller_(new PingController(this)),
+ ping_controller_(this),
validator_(std::make_unique<blink::TrialTokenValidator>()),
weak_factory_(this) {
DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId, version_id);
@@ -351,7 +281,8 @@ ServiceWorkerVersion::~ServiceWorkerVersion() {
// RecordStartWorkerResult must be the first element of start_callbacks_.
StatusCallback record_start_worker_result = std::move(start_callbacks_[0]);
start_callbacks_.clear();
- std::move(record_start_worker_result).Run(SERVICE_WORKER_ERROR_ABORT);
+ std::move(record_start_worker_result)
+ .Run(blink::ServiceWorkerStatusCode::kErrorAbort);
}
if (context_)
@@ -418,14 +349,14 @@ void ServiceWorkerVersion::SetStatus(Status status) {
}
// OnVersionStateChanged() invokes updates of the status using state
- // change IPC at ServiceWorkerHandle (for JS-land on renderer process) and
+ // change IPC at ServiceWorkerObjectHost (for JS-land on renderer process) and
// ServiceWorkerContextCore (for devtools and serviceworker-internals).
// This should be done before using the new status by
// |status_change_callbacks_| which sends the IPC for resolving the .ready
// property.
// TODO(shimazu): Clarify the dependency of OnVersionStateChanged and
// |status_change_callbacks_|
- for (auto& observer : listeners_)
+ for (auto& observer : observers_)
observer.OnVersionStateChanged(this);
std::vector<base::OnceClosure> callbacks;
@@ -494,24 +425,25 @@ void ServiceWorkerVersion::StartWorker(ServiceWorkerMetrics::EventType purpose,
if (!context_) {
RecordStartWorkerResult(purpose, status_, kInvalidTraceId,
is_browser_startup_complete,
- SERVICE_WORKER_ERROR_ABORT);
- RunSoon(base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT));
+ blink::ServiceWorkerStatusCode::kErrorAbort);
+ RunSoon(base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorAbort));
return;
}
if (is_redundant()) {
RecordStartWorkerResult(purpose, status_, kInvalidTraceId,
is_browser_startup_complete,
- SERVICE_WORKER_ERROR_REDUNDANT);
- RunSoon(
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_REDUNDANT));
+ blink::ServiceWorkerStatusCode::kErrorRedundant);
+ RunSoon(base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorRedundant));
return;
}
if (!IsStartWorkerAllowed()) {
RecordStartWorkerResult(purpose, status_, kInvalidTraceId,
is_browser_startup_complete,
- SERVICE_WORKER_ERROR_DISALLOWED);
- RunSoon(
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_DISALLOWED));
+ blink::ServiceWorkerStatusCode::kErrorDisallowed);
+ RunSoon(base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorDisallowed));
return;
}
@@ -602,6 +534,7 @@ int ServiceWorkerVersion::StartRequestWithCustomTimeout(
DCHECK(event_type == ServiceWorkerMetrics::EventType::INSTALL ||
event_type == ServiceWorkerMetrics::EventType::ACTIVATE ||
event_type == ServiceWorkerMetrics::EventType::MESSAGE ||
+ event_type == ServiceWorkerMetrics::EventType::EXTERNAL_REQUEST ||
status() == ACTIVATED)
<< "Event of type " << static_cast<int>(event_type)
<< " can only be dispatched to an active worker: " << status();
@@ -637,6 +570,9 @@ int ServiceWorkerVersion::StartRequestWithCustomTimeout(
bool ServiceWorkerVersion::StartExternalRequest(
const std::string& request_uuid) {
+ if (running_status() == EmbeddedWorkerStatus::STARTING)
+ return pending_external_requests_.insert(request_uuid).second;
+
// It's possible that the renderer is lying or the version started stopping
// right around the time of the IPC.
if (running_status() != EmbeddedWorkerStatus::RUNNING)
@@ -660,13 +596,12 @@ bool ServiceWorkerVersion::FinishRequest(int request_id,
if (!request)
return false;
if (event_recorder_)
- event_recorder_->RecordEventHandledStatus(request->event_type, was_handled);
+ event_recorder_->RecordEventHandledStatus(request->event_type);
ServiceWorkerMetrics::RecordEventDuration(
request->event_type, tick_clock_->NowTicks() - request->start_time_ticks,
was_handled);
ServiceWorkerMetrics::RecordEventDispatchingDelay(
- request->event_type, dispatch_event_time - request->start_time,
- site_for_uma());
+ request->event_type, dispatch_event_time - request->start_time);
RestartTick(&idle_time_);
TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request",
@@ -681,6 +616,9 @@ bool ServiceWorkerVersion::FinishRequest(int request_id,
bool ServiceWorkerVersion::FinishExternalRequest(
const std::string& request_uuid) {
+ if (running_status() == EmbeddedWorkerStatus::STARTING)
+ return pending_external_requests_.erase(request_uuid) > 0u;
+
// It's possible that the renderer is lying or the version started stopping
// right around the time of the IPC.
if (running_status() != EmbeddedWorkerStatus::RUNNING)
@@ -703,7 +641,7 @@ bool ServiceWorkerVersion::FinishExternalRequest(
ServiceWorkerVersion::SimpleEventCallback
ServiceWorkerVersion::CreateSimpleEventCallback(int request_id) {
// The weak reference to |this| is safe because storage of the callbacks, the
- // inflight responses of the ServiceWorkerEventDispatcher, is owned by |this|.
+ // inflight responses of mojom::ServiceWorker messages, is owned by |this|.
return base::BindOnce(&ServiceWorkerVersion::OnSimpleEventFinished,
base::Unretained(this), request_id);
}
@@ -713,7 +651,7 @@ void ServiceWorkerVersion::RunAfterStartWorker(
StatusCallback callback) {
if (running_status() == EmbeddedWorkerStatus::RUNNING) {
DCHECK(start_callbacks_.empty());
- std::move(callback).Run(SERVICE_WORKER_OK);
+ std::move(callback).Run(blink::ServiceWorkerStatusCode::kOk);
return;
}
StartWorker(purpose,
@@ -767,19 +705,20 @@ void ServiceWorkerVersion::OnStreamResponseFinished() {
OnNoWorkInBrowser();
}
-void ServiceWorkerVersion::AddListener(Listener* listener) {
- listeners_.AddObserver(listener);
+void ServiceWorkerVersion::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
}
-void ServiceWorkerVersion::RemoveListener(Listener* listener) {
- listeners_.RemoveObserver(listener);
+void ServiceWorkerVersion::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
}
-void ServiceWorkerVersion::ReportError(ServiceWorkerStatusCode status,
+void ServiceWorkerVersion::ReportError(blink::ServiceWorkerStatusCode status,
const std::string& status_message) {
if (status_message.empty()) {
- OnReportException(base::UTF8ToUTF16(ServiceWorkerStatusToString(status)),
- -1, -1, GURL());
+ OnReportException(
+ base::UTF8ToUTF16(blink::ServiceWorkerStatusToString(status)), -1, -1,
+ GURL());
} else {
OnReportException(base::UTF8ToUTF16(status_message), -1, -1, GURL());
}
@@ -791,7 +730,7 @@ void ServiceWorkerVersion::ReportForceUpdateToDevTools() {
}
void ServiceWorkerVersion::SetStartWorkerStatusCode(
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
start_worker_status_ = status;
}
@@ -822,6 +761,22 @@ void ServiceWorkerVersion::Doom() {
context_->storage()->PurgeResources(resources);
}
+void ServiceWorkerVersion::SetToPauseAfterDownload(base::OnceClosure callback) {
+ pause_after_download_callback_ = std::move(callback);
+}
+
+void ServiceWorkerVersion::SetToNotPauseAfterDownload() {
+ pause_after_download_callback_.Reset();
+}
+
+void ServiceWorkerVersion::OnMainScriptLoaded() {
+ if (!pause_after_download_callback_)
+ return;
+ // The callback can destroy |this|, so protect it first.
+ auto protect = base::WrapRefCounted(this);
+ std::move(pause_after_download_callback_).Run();
+}
+
void ServiceWorkerVersion::SetValidOriginTrialTokens(
const blink::TrialTokenValidator::FeatureToTokensMap& tokens) {
origin_trial_tokens_ = validator_->GetValidTokens(
@@ -880,12 +835,12 @@ void ServiceWorkerVersion::SetMainScriptHttpResponseInfo(
url::Origin::Create(scope()), http_info.headers.get(), clock_->Now());
}
- for (auto& observer : listeners_)
+ for (auto& observer : observers_)
observer.OnMainScriptHttpResponseInfoSet(this);
}
void ServiceWorkerVersion::SimulatePingTimeoutForTesting() {
- ping_controller_->SimulateTimeoutForTesting();
+ ping_controller_.SimulateTimeoutForTesting();
}
void ServiceWorkerVersion::SetTickClockForTesting(
@@ -934,26 +889,42 @@ ServiceWorkerVersion::InflightRequest::InflightRequest(
ServiceWorkerVersion::InflightRequest::~InflightRequest() {}
-void ServiceWorkerVersion::OnThreadStarted() {
+void ServiceWorkerVersion::OnScriptEvaluationStart() {
DCHECK_EQ(EmbeddedWorkerStatus::STARTING, running_status());
// Activate ping/pong now that JavaScript execution will start.
- ping_controller_->Activate();
+ ping_controller_.Activate();
}
void ServiceWorkerVersion::OnStarting() {
- for (auto& observer : listeners_)
+ for (auto& observer : observers_)
observer.OnRunningStateChanged(this);
}
-void ServiceWorkerVersion::OnStarted() {
+void ServiceWorkerVersion::OnStarted(
+ blink::mojom::ServiceWorkerStartStatus start_status) {
DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status());
RestartTick(&idle_time_);
+ // TODO(falken): This maps kAbruptCompletion to kErrorScriptEvaluated, which
+ // most start callbacks will consider to be a failure. But the worker thread
+ // is running, and the spec considers it a success, so the callbacks should
+ // change to treat kErrorScriptEvaluated as success, or use
+ // ServiceWorkerStartStatus directly.
+ blink::ServiceWorkerStatusCode status =
+ mojo::ConvertTo<blink::ServiceWorkerStatusCode>(start_status);
+
// Fire all start callbacks.
scoped_refptr<ServiceWorkerVersion> protect(this);
- FinishStartWorker(SERVICE_WORKER_OK);
- for (auto& observer : listeners_)
+ FinishStartWorker(status);
+ for (auto& observer : observers_)
observer.OnRunningStateChanged(this);
+
+ if (!pending_external_requests_.empty()) {
+ std::set<std::string> pending_external_requests;
+ std::swap(pending_external_requests_, pending_external_requests);
+ for (const std::string& request_uuid : pending_external_requests)
+ StartExternalRequest(request_uuid);
+ }
}
void ServiceWorkerVersion::OnStopping() {
@@ -968,7 +939,7 @@ void ServiceWorkerVersion::OnStopping() {
// worker stops, the timer is disabled. The interval will be reset to normal
// when the worker starts up again.
SetTimeoutTimerInterval(kStopWorkerTimeout);
- for (auto& observer : listeners_)
+ for (auto& observer : observers_)
observer.OnRunningStateChanged(this);
}
@@ -991,19 +962,8 @@ void ServiceWorkerVersion::OnDetached(EmbeddedWorkerStatus old_status) {
OnStoppedInternal(old_status);
}
-void ServiceWorkerVersion::OnScriptLoaded() {
- DCHECK(GetMainScriptHttpResponseInfo());
- if (IsInstalled(status()))
- UMA_HISTOGRAM_BOOLEAN("ServiceWorker.ScriptLoadSuccess", true);
-}
-
-void ServiceWorkerVersion::OnScriptLoadFailed() {
- if (IsInstalled(status()))
- UMA_HISTOGRAM_BOOLEAN("ServiceWorker.ScriptLoadSuccess", false);
-}
-
void ServiceWorkerVersion::OnRegisteredToDevToolsManager() {
- for (auto& observer : listeners_)
+ for (auto& observer : observers_)
observer.OnDevToolsRoutingIdChanged(this);
}
@@ -1012,7 +972,7 @@ void ServiceWorkerVersion::OnReportException(
int line_number,
int column_number,
const GURL& source_url) {
- for (auto& observer : listeners_) {
+ for (auto& observer : observers_) {
observer.OnErrorReported(this, error_message, line_number, column_number,
source_url);
}
@@ -1023,15 +983,14 @@ void ServiceWorkerVersion::OnReportConsoleMessage(int source_identifier,
const base::string16& message,
int line_number,
const GURL& source_url) {
- for (auto& observer : listeners_) {
+ for (auto& observer : observers_) {
observer.OnReportConsoleMessage(this, source_identifier, message_level,
message, line_number, source_url);
}
}
-void ServiceWorkerVersion::OnStartSentAndScriptEvaluated(
- ServiceWorkerStatusCode status) {
- if (status != SERVICE_WORKER_OK) {
+void ServiceWorkerVersion::OnStartSent(blink::ServiceWorkerStatusCode status) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
scoped_refptr<ServiceWorkerVersion> protect(this);
FinishStartWorker(DeduceStartWorkerFailureReason(status));
}
@@ -1161,6 +1120,12 @@ void ServiceWorkerVersion::PostMessageToClient(
binding_.Close();
return;
}
+ if (!provider_host->is_execution_ready()) {
+ mojo::ReportBadMessage(
+ "Received Client#postMessage() request for a reserved client.");
+ binding_.Close();
+ return;
+ }
provider_host->PostMessageToClient(this, std::move(message));
}
@@ -1301,8 +1266,8 @@ void ServiceWorkerVersion::OnSetCachedMetadataFinished(int64_t callback_id,
TRACE_EVENT_ASYNC_END1("ServiceWorker",
"ServiceWorkerVersion::SetCachedMetadata", callback_id,
"result", result);
- for (auto& listener : listeners_)
- listener.OnCachedMetadataUpdated(this, size);
+ for (auto& observer : observers_)
+ observer.OnCachedMetadataUpdated(this, size);
}
void ServiceWorkerVersion::OnClearCachedMetadataFinished(int64_t callback_id,
@@ -1310,8 +1275,8 @@ void ServiceWorkerVersion::OnClearCachedMetadataFinished(int64_t callback_id,
TRACE_EVENT_ASYNC_END1("ServiceWorker",
"ServiceWorkerVersion::ClearCachedMetadata",
callback_id, "result", result);
- for (auto& listener : listeners_)
- listener.OnCachedMetadataUpdated(this, 0);
+ for (auto& observer : observers_)
+ observer.OnCachedMetadataUpdated(this, 0);
}
void ServiceWorkerVersion::OpenWindow(
@@ -1369,7 +1334,8 @@ void ServiceWorkerVersion::OnSimpleEventFinished(
status == blink::mojom::ServiceWorkerEventStatus::COMPLETED,
dispatch_event_time);
- std::move(callback).Run(mojo::ConvertTo<ServiceWorkerStatusCode>(status));
+ std::move(callback).Run(
+ mojo::ConvertTo<blink::ServiceWorkerStatusCode>(status));
}
void ServiceWorkerVersion::CountFeature(blink::mojom::WebFeature feature) {
@@ -1394,8 +1360,21 @@ bool ServiceWorkerVersion::IsInstalled(ServiceWorkerVersion::Status status) {
return false;
}
+void ServiceWorkerVersion::IncrementPendingUpdateHintCount() {
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+ pending_update_hint_count_++;
+}
+
+void ServiceWorkerVersion::DecrementPendingUpdateHintCount() {
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK_GT(pending_update_hint_count_, 0);
+ pending_update_hint_count_--;
+ if (pending_update_hint_count_ == 0)
+ ScheduleUpdate();
+}
+
void ServiceWorkerVersion::OnPongFromWorker() {
- ping_controller_->OnPongReceived();
+ ping_controller_.OnPongReceived();
}
void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
@@ -1403,10 +1382,10 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
Status prestart_status,
bool is_browser_startup_complete,
StatusCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
scoped_refptr<ServiceWorkerRegistration> protect = registration;
- if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
+ if (status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
// When the registration has already been deleted from the storage but its
// active worker is still controlling clients, the event should be
// dispatched on the worker. However, the storage cannot find the
@@ -1414,22 +1393,23 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
protect = context_->GetLiveRegistration(registration_id_);
if (protect) {
DCHECK(protect->is_deleted());
- status = SERVICE_WORKER_OK;
+ status = blink::ServiceWorkerStatusCode::kOk;
}
}
- if (status != SERVICE_WORKER_OK) {
+ if (status != blink::ServiceWorkerStatusCode::kOk) {
RecordStartWorkerResult(purpose, prestart_status, kInvalidTraceId,
is_browser_startup_complete, status);
- RunSoon(base::BindOnce(std::move(callback),
- SERVICE_WORKER_ERROR_START_WORKER_FAILED));
+ RunSoon(base::BindOnce(
+ std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed));
return;
}
if (is_redundant()) {
RecordStartWorkerResult(purpose, prestart_status, kInvalidTraceId,
is_browser_startup_complete,
- SERVICE_WORKER_ERROR_REDUNDANT);
- RunSoon(
- base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_REDUNDANT));
+ blink::ServiceWorkerStatusCode::kErrorRedundant);
+ RunSoon(base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kErrorRedundant));
return;
}
@@ -1437,7 +1417,8 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
switch (running_status()) {
case EmbeddedWorkerStatus::RUNNING:
- RunSoon(base::BindOnce(std::move(callback), SERVICE_WORKER_OK));
+ RunSoon(base::BindOnce(std::move(callback),
+ blink::ServiceWorkerStatusCode::kOk));
return;
case EmbeddedWorkerStatus::STARTING:
DCHECK(!start_callbacks_.empty());
@@ -1464,7 +1445,9 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
start_callbacks_.push_back(base::BindOnce(
[](StatusCallback callback,
scoped_refptr<ServiceWorkerRegistration> protect,
- ServiceWorkerStatusCode status) { std::move(callback).Run(status); },
+ blink::ServiceWorkerStatusCode status) {
+ std::move(callback).Run(status);
+ },
std::move(callback), protect));
if (running_status() == EmbeddedWorkerStatus::STOPPED)
@@ -1473,16 +1456,18 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
}
void ServiceWorkerVersion::StartWorkerInternal() {
+ DCHECK(context_);
DCHECK_EQ(EmbeddedWorkerStatus::STOPPED, running_status());
DCHECK(inflight_requests_.IsEmpty());
DCHECK(request_timeouts_.empty());
DCHECK(start_worker_first_purpose_);
- if (!ServiceWorkerMetrics::ShouldExcludeSiteFromHistogram(site_for_uma_)) {
+ if (!ServiceWorkerMetrics::ShouldExcludeSiteFromHistogram(site_for_uma_) &&
+ start_worker_first_purpose_.value() ==
+ ServiceWorkerMetrics::EventType::NAVIGATION_HINT) {
DCHECK(!event_recorder_);
event_recorder_ =
- std::make_unique<ServiceWorkerMetrics::ScopedEventRecorder>(
- start_worker_first_purpose_.value());
+ std::make_unique<ServiceWorkerMetrics::ScopedEventRecorder>();
}
// We don't clear |start_worker_first_purpose_| here but clear in
// FinishStartWorker. This is because StartWorkerInternal may be called
@@ -1491,18 +1476,19 @@ void ServiceWorkerVersion::StartWorkerInternal() {
StartTimeoutTimer();
idle_timer_fired_in_renderer_ = false;
- std::unique_ptr<ServiceWorkerProviderHost> provider_host =
- ServiceWorkerProviderHost::PreCreateForController(context());
- provider_host_ = provider_host->AsWeakPtr();
+ auto provider_info = mojom::ServiceWorkerProviderInfoForStartWorker::New();
+ provider_host_ = ServiceWorkerProviderHost::PreCreateForController(
+ context(), base::WrapRefCounted(this), &provider_info);
auto params = mojom::EmbeddedWorkerStartParams::New();
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_;
+ params->pause_after_download = pause_after_download();
- if (IsInstalled(status()) && !pause_after_download_) {
+ if (IsInstalled(status())) {
+ DCHECK(!params->pause_after_download);
DCHECK(!installed_scripts_sender_);
installed_scripts_sender_ =
std::make_unique<ServiceWorkerInstalledScriptsSender>(this);
@@ -1511,23 +1497,23 @@ void ServiceWorkerVersion::StartWorkerInternal() {
installed_scripts_sender_->Start();
}
- params->dispatcher_request = mojo::MakeRequest(&event_dispatcher_);
+ params->service_worker_request = mojo::MakeRequest(&service_worker_ptr_);
// TODO(horo): These CHECKs are for debugging crbug.com/759938.
- CHECK(event_dispatcher_.is_bound());
- CHECK(params->dispatcher_request.is_pending());
- event_dispatcher_.set_connection_error_handler(base::BindOnce(
- &OnEventDispatcherConnectionError, embedded_worker_->AsWeakPtr()));
+ CHECK(service_worker_ptr_.is_bound());
+ CHECK(params->service_worker_request.is_pending());
+ service_worker_ptr_.set_connection_error_handler(
+ base::BindOnce(&OnConnectionError, embedded_worker_->AsWeakPtr()));
blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host;
binding_.Close();
binding_.Bind(mojo::MakeRequest(&service_worker_host));
ServiceWorkerRegistration* registration =
context_->GetLiveRegistration(registration_id_);
DCHECK(registration);
- provider_host->SetDocumentUrl(script_url());
- event_dispatcher_->InitializeGlobalScope(
+ provider_host_->SetDocumentUrl(script_url());
+ service_worker_ptr_->InitializeGlobalScope(
std::move(service_worker_host),
- provider_host->CreateServiceWorkerRegistrationObjectInfo(
- scoped_refptr<ServiceWorkerRegistration>(registration)));
+ provider_host_->CreateServiceWorkerRegistrationObjectInfo(
+ base::WrapRefCounted(registration)));
// S13nServiceWorker:
if (!controller_request_.is_pending()) {
@@ -1536,13 +1522,11 @@ void ServiceWorkerVersion::StartWorkerInternal() {
}
params->controller_request = std::move(controller_request_);
+ params->provider_info = std::move(provider_info);
+
embedded_worker_->Start(
std::move(params),
- // Unretained is used here because the callback will be owned by
- // |embedded_worker_| whose owner is |this|.
- base::BindOnce(&CompleteProviderHostPreparation, base::Unretained(this),
- std::move(provider_host), context()),
- base::BindOnce(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated,
+ base::BindOnce(&ServiceWorkerVersion::OnStartSent,
weak_factory_.GetWeakPtr()));
}
@@ -1561,8 +1545,8 @@ void ServiceWorkerVersion::StartTimeoutTimer() {
// The worker is starting up and not yet idle.
ClearTick(&idle_time_);
- // Ping will be activated in OnScriptLoaded.
- ping_controller_->Deactivate();
+ // Ping will be activated in OnScriptEvaluationStart.
+ ping_controller_.Deactivate();
timeout_timer_.Start(FROM_HERE, kTimeoutTimerDelay, this,
&ServiceWorkerVersion::OnTimeoutTimer);
@@ -1608,7 +1592,8 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
ServiceWorkerMetrics::RecordWorkerStopped(
ServiceWorkerMetrics::StopStatus::TIMEOUT);
}
- ReportError(SERVICE_WORKER_ERROR_TIMEOUT, "DETACH_STALLED_IN_STOPPING");
+ ReportError(blink::ServiceWorkerStatusCode::kErrorTimeout,
+ "DETACH_STALLED_IN_STOPPING");
// Detach the worker. Remove |this| as a listener first; otherwise
// OnStoppedInternal might try to restart before the new worker
@@ -1643,7 +1628,7 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
running_status() == EmbeddedWorkerStatus::STOPPING)
<< static_cast<int>(running_status());
scoped_refptr<ServiceWorkerVersion> protect(this);
- FinishStartWorker(SERVICE_WORKER_ERROR_TIMEOUT);
+ FinishStartWorker(blink::ServiceWorkerStatusCode::kErrorTimeout);
if (running_status() == EmbeddedWorkerStatus::STARTING)
embedded_worker_->Stop();
return;
@@ -1674,29 +1659,31 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
// The worker has been idle for longer than a certain period.
// S13nServiceWorker: The idle timer is implemented on the renderer, so we can
// skip this check.
- if (!ServiceWorkerUtils::IsServicificationEnabled() &&
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled() &&
GetTickDuration(idle_time_) > kIdleWorkerTimeout) {
StopWorkerIfIdle(false /* requested_from_renderer */);
return;
}
// Check ping status.
- ping_controller_->CheckPingStatus();
+ ping_controller_.CheckPingStatus();
}
void ServiceWorkerVersion::PingWorker() {
// TODO(horo): This CHECK is for debugging crbug.com/759938.
CHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
running_status() == EmbeddedWorkerStatus::RUNNING);
- // base::Unretained here is safe because event_dispatcher is owned by |this|.
- event_dispatcher()->Ping(base::BindOnce(
- &ServiceWorkerVersion::OnPongFromWorker, base::Unretained(this)));
+ // base::Unretained here is safe because endpoint() is owned by
+ // |this|.
+ endpoint()->Ping(base::BindOnce(&ServiceWorkerVersion::OnPongFromWorker,
+ base::Unretained(this)));
}
void ServiceWorkerVersion::OnPingTimeout() {
DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
running_status() == EmbeddedWorkerStatus::RUNNING);
- // TODO(falken): Change the error code to SERVICE_WORKER_ERROR_TIMEOUT.
+ // TODO(falken): Change the error code to
+ // blink::ServiceWorkerStatusCode::kErrorTimeout.
embedded_worker_->AddMessageToConsole(blink::WebConsoleMessage::kLevelVerbose,
kNotRespondingErrorMesage);
StopWorkerIfIdle(false /* requested_from_renderer */);
@@ -1709,19 +1696,19 @@ void ServiceWorkerVersion::StopWorkerIfIdle(bool requested_from_renderer) {
return;
}
- if (!ServiceWorkerUtils::IsServicificationEnabled()) {
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
// StopWorkerIfIdle() may be called for two reasons: "idle-timeout" or
// "ping-timeout". For idle-timeout (i.e. ping hasn't timed out), check if
// the worker really is idle.
- if (!ping_controller_->IsTimedOut() && HasWorkInBrowser())
+ if (!ping_controller_.IsTimedOut() && HasWorkInBrowser())
return;
embedded_worker_->StopIfNotAttachedToDevTools();
return;
}
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
// Ping timeout
- if (ping_controller_->IsTimedOut()) {
+ if (ping_controller_.IsTimedOut()) {
DCHECK(!requested_from_renderer);
embedded_worker_->StopIfNotAttachedToDevTools();
return;
@@ -1753,11 +1740,11 @@ void ServiceWorkerVersion::RecordStartWorkerResult(
Status prestart_status,
int trace_id,
bool is_browser_startup_complete,
- ServiceWorkerStatusCode status) {
+ blink::ServiceWorkerStatusCode status) {
if (trace_id != kInvalidTraceId) {
TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::StartWorker",
trace_id, "Status",
- ServiceWorkerStatusToString(status));
+ blink::ServiceWorkerStatusToString(status));
}
base::TimeTicks start_time = start_time_;
ClearTick(&start_time_);
@@ -1772,14 +1759,14 @@ void ServiceWorkerVersion::RecordStartWorkerResult(
ServiceWorkerMetrics::RecordStartWorkerStatus(status, purpose,
IsInstalled(prestart_status));
- if (status == SERVICE_WORKER_OK && !start_time.is_null() &&
+ if (status == blink::ServiceWorkerStatusCode::kOk && !start_time.is_null() &&
!skip_recording_startup_time_) {
ServiceWorkerMetrics::RecordStartWorkerTime(
GetTickDuration(start_time), IsInstalled(prestart_status),
embedded_worker_->start_situation(), purpose);
}
- if (status != SERVICE_WORKER_ERROR_TIMEOUT)
+ if (status != blink::ServiceWorkerStatusCode::kErrorTimeout)
return;
EmbeddedWorkerInstance::StartingPhase phase =
EmbeddedWorkerInstance::NOT_STARTING;
@@ -1811,7 +1798,8 @@ bool ServiceWorkerVersion::MaybeTimeoutRequest(
TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request",
request, "Error", "Timeout");
- std::move(request->error_callback).Run(SERVICE_WORKER_ERROR_TIMEOUT);
+ std::move(request->error_callback)
+ .Run(blink::ServiceWorkerStatusCode::kErrorTimeout);
inflight_requests_.Remove(info.id);
return true;
}
@@ -1832,27 +1820,28 @@ void ServiceWorkerVersion::SetAllRequestExpirations(
request_timeouts_.swap(new_timeouts);
}
-ServiceWorkerStatusCode ServiceWorkerVersion::DeduceStartWorkerFailureReason(
- ServiceWorkerStatusCode default_code) {
- if (ping_controller_->IsTimedOut())
- return SERVICE_WORKER_ERROR_TIMEOUT;
+blink::ServiceWorkerStatusCode
+ServiceWorkerVersion::DeduceStartWorkerFailureReason(
+ blink::ServiceWorkerStatusCode default_code) {
+ if (ping_controller_.IsTimedOut())
+ return blink::ServiceWorkerStatusCode::kErrorTimeout;
- if (start_worker_status_ != SERVICE_WORKER_OK)
+ if (start_worker_status_ != blink::ServiceWorkerStatusCode::kOk)
return start_worker_status_;
const net::URLRequestStatus& main_script_status =
script_cache_map()->main_script_status();
if (main_script_status.status() != net::URLRequestStatus::SUCCESS) {
if (net::IsCertificateError(main_script_status.error()))
- return SERVICE_WORKER_ERROR_SECURITY;
+ return blink::ServiceWorkerStatusCode::kErrorSecurity;
switch (main_script_status.error()) {
case net::ERR_INSECURE_RESPONSE:
case net::ERR_UNSAFE_REDIRECT:
- return SERVICE_WORKER_ERROR_SECURITY;
+ return blink::ServiceWorkerStatusCode::kErrorSecurity;
case net::ERR_ABORTED:
- return SERVICE_WORKER_ERROR_ABORT;
+ return blink::ServiceWorkerStatusCode::kErrorAbort;
default:
- return SERVICE_WORKER_ERROR_NETWORK;
+ return blink::ServiceWorkerStatusCode::kErrorNetwork;
}
}
@@ -1875,7 +1864,7 @@ void ServiceWorkerVersion::MarkIfStale() {
}
void ServiceWorkerVersion::FoundRegistrationForUpdate(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
if (!context_)
return;
@@ -1886,7 +1875,8 @@ void ServiceWorkerVersion::FoundRegistrationForUpdate(
is_update_scheduled_ = false;
}
- if (status != SERVICE_WORKER_OK || registration->active_version() != this)
+ if (status != blink::ServiceWorkerStatusCode::kOk ||
+ registration->active_version() != this)
return;
context_->UpdateServiceWorker(registration.get(),
false /* force_bypass_cache */);
@@ -1907,8 +1897,8 @@ void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
if (is_redundant() || in_dtor_) {
// This worker will be destroyed soon.
should_restart = false;
- } else if (ping_controller_->IsTimedOut()) {
- // This worker is unresponsive and restart may fail.
+ } else if (ping_controller_.IsTimedOut()) {
+ // This worker exhausted its time to run, don't let it restart.
should_restart = false;
} else if (old_status == EmbeddedWorkerStatus::STARTING) {
// This worker unexpectedly stopped because start failed. Attempting to
@@ -1935,7 +1925,7 @@ void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
if (!should_restart) {
// Let all start callbacks fail.
FinishStartWorker(DeduceStartWorkerFailureReason(
- SERVICE_WORKER_ERROR_START_WORKER_FAILED));
+ blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed));
}
// Let all message callbacks fail (this will also fire and clear all
@@ -1947,19 +1937,20 @@ void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request",
iter.GetCurrentValue(), "Error", "Worker Stopped");
std::move(iter.GetCurrentValue()->error_callback)
- .Run(SERVICE_WORKER_ERROR_FAILED);
+ .Run(blink::ServiceWorkerStatusCode::kErrorFailed);
iter.Advance();
}
inflight_requests_.Clear();
request_timeouts_.clear();
external_request_uuid_to_request_id_.clear();
- event_dispatcher_.reset();
+ service_worker_ptr_.reset();
controller_ptr_.reset();
DCHECK(!controller_request_.is_pending());
installed_scripts_sender_.reset();
binding_.Close();
+ pending_external_requests_.clear();
- for (auto& observer : listeners_)
+ for (auto& observer : observers_)
observer.OnRunningStateChanged(this);
if (should_restart) {
StartWorkerInternal();
@@ -1968,34 +1959,35 @@ void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
}
}
-void ServiceWorkerVersion::FinishStartWorker(ServiceWorkerStatusCode status) {
+void ServiceWorkerVersion::FinishStartWorker(
+ blink::ServiceWorkerStatusCode status) {
start_worker_first_purpose_ = base::nullopt;
RunCallbacks(this, &start_callbacks_, status);
}
void ServiceWorkerVersion::CleanUpExternalRequest(
const std::string& request_uuid,
- ServiceWorkerStatusCode status) {
- if (status == SERVICE_WORKER_OK)
+ blink::ServiceWorkerStatusCode status) {
+ if (status == blink::ServiceWorkerStatusCode::kOk)
return;
external_request_uuid_to_request_id_.erase(request_uuid);
}
void ServiceWorkerVersion::OnNoWorkInBrowser() {
DCHECK(!HasWorkInBrowser());
- if (!ServiceWorkerUtils::IsServicificationEnabled()) {
- for (auto& observer : listeners_)
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ for (auto& observer : observers_)
observer.OnNoWork(this);
return;
}
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
if (!idle_timer_fired_in_renderer_ &&
running_status() != EmbeddedWorkerStatus::STOPPED) {
return;
}
- for (auto& observer : listeners_)
+ for (auto& observer : observers_)
observer.OnNoWork(this);
idle_timer_fired_in_renderer_ = false;
}
@@ -2027,7 +2019,7 @@ bool ServiceWorkerVersion::IsStartWorkerAllowed() const {
void ServiceWorkerVersion::NotifyControlleeAdded(
const std::string& uuid,
const ServiceWorkerClientInfo& info) {
- for (auto& observer : listeners_)
+ for (auto& observer : observers_)
observer.OnControlleeAdded(this, uuid, info);
}
@@ -2037,11 +2029,11 @@ void ServiceWorkerVersion::NotifyControlleeRemoved(const std::string& uuid) {
// instead of an observer callback, if it has dangerous side-effects like
// destroying the caller.
auto protect = base::WrapRefCounted(this);
- for (auto& observer : listeners_)
+ for (auto& observer : observers_)
observer.OnControlleeRemoved(this, uuid);
if (!HasControllee()) {
RestartTick(&no_controllees_time_);
- for (auto& observer : listeners_)
+ for (auto& observer : observers_)
observer.OnNoControllees(this);
}
}
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
index ce8fec41aaa..8549a667e3c 100644
--- a/chromium/content/browser/service_worker/service_worker_version.h
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -33,16 +33,17 @@
#include "content/browser/service_worker/service_worker_client_utils.h"
#include "content/browser/service_worker/service_worker_context_request_handler.h"
#include "content/browser/service_worker/service_worker_metrics.h"
+#include "content/browser/service_worker/service_worker_ping_controller.h"
#include "content/browser/service_worker/service_worker_script_cache_map.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/controller_service_worker.mojom.h"
-#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
-#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/common/service_worker/service_worker.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
#include "ipc/ipc_message.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
@@ -111,7 +112,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
public base::RefCounted<ServiceWorkerVersion>,
public EmbeddedWorkerInstance::Listener {
public:
- using StatusCallback = base::OnceCallback<void(ServiceWorkerStatusCode)>;
+ using StatusCallback =
+ base::OnceCallback<void(blink::ServiceWorkerStatusCode)>;
using SimpleEventCallback =
base::OnceCallback<void(blink::mojom::ServiceWorkerEventStatus,
base::Time)>;
@@ -142,7 +144,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
DOES_NOT_EXIST,
};
- class Listener {
+ class Observer {
public:
virtual void OnRunningStateChanged(ServiceWorkerVersion* version) {}
virtual void OnVersionStateChanged(ServiceWorkerVersion* version) {}
@@ -175,7 +177,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
size_t size) {}
protected:
- virtual ~Listener() {}
+ virtual ~Observer() {}
};
ServiceWorkerVersion(ServiceWorkerRegistration* registration,
@@ -196,7 +198,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
// This status is set to EXISTS or DOES_NOT_EXIST when the install event has
// been executed in a new version or when an installed version is loaded from
- // the storage. When a new version is not installed yet, it is UNKNOW.
+ // the storage. When a new version is not installed yet, it is UNKNOWN.
FetchHandlerExistence fetch_handler_existence() const {
return fetch_handler_existence_;
}
@@ -265,10 +267,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
void StartUpdate();
// Starts the worker if it isn't already running. Calls |callback| with
- // SERVICE_WORKER_OK when the worker started up successfully or if it is
- // already running. Otherwise, calls |callback| with an error code.
- // If the worker is already running, |callback| is executed synchronously
- // (before this method returns). |purpose| is used for UMA.
+ // blink::ServiceWorkerStatusCode::kOk when the worker started
+ // up successfully or if it is already running. Otherwise, calls |callback|
+ // with an error code. If the worker is already running, |callback| is
+ // executed synchronously (before this method returns). |purpose| is used for
+ // UMA.
void RunAfterStartWorker(ServiceWorkerMetrics::EventType purpose,
StatusCallback callback);
@@ -290,10 +293,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Same as StartRequest, but allows the caller to specify a custom timeout for
// the event, as well as the behavior for when the request times out.
- // S13nServiceWorker: |timeout| and |timeout_behavior| don't have any
- // effect. They are just ignored. Timeouts can be added to the
- // mojom::ServiceWorkerEventDispatcher interface instead (see
- // DispatchSyncEvent for an example).
+ //
+ // S13nServiceWorker: |timeout| and |timeout_behavior| don't have any effect.
+ // They are just ignored. Timeouts can be added to the mojom::ServiceWorker
+ // interface instead (see DispatchSyncEvent for an example).
int StartRequestWithCustomTimeout(ServiceWorkerMetrics::EventType event_type,
StatusCallback error_callback,
const base::TimeDelta& timeout,
@@ -321,19 +324,19 @@ class CONTENT_EXPORT ServiceWorkerVersion
bool FinishExternalRequest(const std::string& request_uuid);
// Creates a callback that is to be used for marking simple events dispatched
- // through the ServiceWorkerEventDispatcher as finished for the |request_id|.
+ // through mojom::ServiceWorker as finished for the |request_id|.
// Simple event means those events expecting a response with only a status
- // code and the dispatch time. See service_worker_event_dispatcher.mojom.
+ // code and the dispatch time. See service_worker.mojom.
SimpleEventCallback CreateSimpleEventCallback(int request_id);
// This must be called when the worker is running.
- mojom::ServiceWorkerEventDispatcher* event_dispatcher() {
+ mojom::ServiceWorker* endpoint() {
DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
running_status() == EmbeddedWorkerStatus::RUNNING);
// Temporarily CHECK for debugging https://crbug.com/817981.
- CHECK(event_dispatcher_.is_bound());
- CHECK(event_dispatcher_.get());
- return event_dispatcher_.get();
+ CHECK(service_worker_ptr_.is_bound());
+ CHECK(service_worker_ptr_.get());
+ return service_worker_ptr_.get();
}
// S13nServiceWorker:
@@ -376,21 +379,21 @@ class CONTENT_EXPORT ServiceWorkerVersion
void OnStreamResponseStarted();
void OnStreamResponseFinished();
- // Adds and removes Listeners.
- void AddListener(Listener* listener);
- void RemoveListener(Listener* listener);
+ // Adds and removes Observers.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
ServiceWorkerScriptCacheMap* script_cache_map() { return &script_cache_map_; }
EmbeddedWorkerInstance* embedded_worker() { return embedded_worker_.get(); }
- // Reports the error message to |listeners_|.
- void ReportError(ServiceWorkerStatusCode status,
+ // Reports the error message to |observers_|.
+ void ReportError(blink::ServiceWorkerStatusCode status,
const std::string& status_message);
void ReportForceUpdateToDevTools();
// Sets the status code to pass to StartWorker callbacks if start fails.
- void SetStartWorkerStatusCode(ServiceWorkerStatusCode status);
+ void SetStartWorkerStatusCode(blink::ServiceWorkerStatusCode status);
// Sets this version's status to REDUNDANT and deletes its resources.
void Doom();
@@ -412,10 +415,16 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Used for pausing service worker startup in the renderer in order to do the
// byte-for-byte check.
- bool pause_after_download() const { return pause_after_download_; }
- void set_pause_after_download(bool pause_after_download) {
- pause_after_download_ = pause_after_download;
+ bool pause_after_download() const {
+ return !pause_after_download_callback_.is_null();
}
+ void SetToPauseAfterDownload(base::OnceClosure callback);
+ void SetToNotPauseAfterDownload();
+
+ // For use by EmbeddedWorkerInstance. Called when the main script loaded.
+ // This is only called for new (non-installed) workers. It's used for resuming
+ // a paused worker via ResumeAfterDownload().
+ void OnMainScriptLoaded();
// Returns nullptr if the main script is not loaded yet and:
// 1) The worker is a new one.
@@ -482,12 +491,34 @@ class CONTENT_EXPORT ServiceWorkerVersion
static bool IsInstalled(ServiceWorkerVersion::Status status);
+ // For scheduling Soft Update after main resource requests. We schedule
+ // a Soft Update to happen "soon" after each main resource request, attempting
+ // to do the update after the page load finished. The renderer sends a hint
+ // when it's a good time to update. This is a count of outstanding expected
+ // hints, to handle multiple main resource requests occurring near the same
+ // time.
+ //
+ // On each request that dispatches a fetch event to this worker (or would
+ // have, in the case of a no-fetch event worker), this count is incremented.
+ // When the browser-side provider host receives a hint from the renderer that
+ // it is a good time to update the service worker, the count is decremented.
+ // It is also decremented when if the provider host is destroyed before
+ // receiving the hint.
+ //
+ // When the count transitions from 1 to 0, update is scheduled.
+ void IncrementPendingUpdateHintCount();
+ void DecrementPendingUpdateHintCount();
+
private:
friend class base::RefCounted<ServiceWorkerVersion>;
+ friend class EmbeddedWorkerInstanceTest;
+ friend class ServiceWorkerPingController;
+ friend class ServiceWorkerProviderHostTest;
friend class ServiceWorkerReadFromCacheJobTest;
friend class ServiceWorkerVersionBrowserTest;
friend class service_worker_registration_unittest::
ServiceWorkerActivationTest;
+ friend class service_worker_version_unittest::ServiceWorkerVersionTest;
FRIEND_TEST_ALL_PREFIXES(service_worker_controllee_request_handler_unittest::
ServiceWorkerControlleeRequestHandlerTest,
@@ -495,6 +526,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
FRIEND_TEST_ALL_PREFIXES(service_worker_controllee_request_handler_unittest::
ServiceWorkerControlleeRequestHandlerTest,
FallbackWithNoFetchHandler);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProviderHostTest,
+ DontSetControllerInDestructor);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerJobTest, Register);
FRIEND_TEST_ALL_PREFIXES(
service_worker_version_unittest::ServiceWorkerVersionTest,
@@ -554,8 +587,6 @@ class CONTENT_EXPORT ServiceWorkerVersion
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerURLRequestJobTest, EarlyResponse);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerURLRequestJobTest, CancelRequest);
- class PingController;
-
// Contains timeout info for InflightRequest.
struct InflightRequestTimeoutInfo {
InflightRequestTimeoutInfo(int id,
@@ -608,14 +639,12 @@ class CONTENT_EXPORT ServiceWorkerVersion
base::TimeDelta GetTickDuration(const base::TimeTicks& time) const;
// EmbeddedWorkerInstance::Listener overrides:
- void OnThreadStarted() override;
+ void OnScriptEvaluationStart() override;
void OnStarting() override;
- void OnStarted() override;
+ void OnStarted(blink::mojom::ServiceWorkerStartStatus status) override;
void OnStopping() override;
void OnStopped(EmbeddedWorkerStatus old_status) override;
void OnDetached(EmbeddedWorkerStatus old_status) override;
- void OnScriptLoaded() override;
- void OnScriptLoadFailed() override;
void OnRegisteredToDevToolsManager() override;
void OnReportException(const base::string16& error_message,
int line_number,
@@ -627,7 +656,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
int line_number,
const GURL& source_url) override;
- void OnStartSentAndScriptEvaluated(ServiceWorkerStatusCode status);
+ void OnStartSent(blink::ServiceWorkerStatusCode status);
// Implements blink::mojom::ServiceWorkerHost.
void SetCachedMetadata(const GURL& url,
@@ -666,12 +695,12 @@ class CONTENT_EXPORT ServiceWorkerVersion
Status prestart_status,
bool is_browser_startup_complete,
StatusCallback callback,
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void StartWorkerInternal();
// Callback function for simple events dispatched through mojo interface
- // mojom::ServiceWorkerEventDispatcher. Use CreateSimpleEventCallback() to
+ // mojom::ServiceWorker. Use CreateSimpleEventCallback() to
// create a callback for a given |request_id|.
void OnSimpleEventFinished(int request_id,
blink::mojom::ServiceWorkerEventStatus status,
@@ -684,7 +713,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
void OnTimeoutTimer();
void SetTimeoutTimerInterval(base::TimeDelta interval);
- // Called by PingController for ping protocol.
+ // Called by ServiceWorkerPingController for ping protocol.
void PingWorker();
void OnPingTimeout();
@@ -694,7 +723,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
Status prestart_status,
int trace_id,
bool is_browser_startup_complete,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
bool MaybeTimeoutRequest(const InflightRequestTimeoutInfo& info);
void SetAllRequestExpirations(const base::TimeTicks& expiration);
@@ -702,26 +731,26 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Returns the reason the embedded worker failed to start, using information
// inaccessible to EmbeddedWorkerInstance. Returns |default_code| if it can't
// deduce a reason.
- ServiceWorkerStatusCode DeduceStartWorkerFailureReason(
- ServiceWorkerStatusCode default_code);
+ blink::ServiceWorkerStatusCode DeduceStartWorkerFailureReason(
+ blink::ServiceWorkerStatusCode default_code);
// Sets |stale_time_| if this worker is stale, causing an update to eventually
// occur once the worker stops or is running too long.
void MarkIfStale();
void FoundRegistrationForUpdate(
- ServiceWorkerStatusCode status,
+ blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void OnStoppedInternal(EmbeddedWorkerStatus old_status);
// Resets |start_worker_first_purpose_| and fires and clears all start
// callbacks.
- void FinishStartWorker(ServiceWorkerStatusCode status);
+ void FinishStartWorker(blink::ServiceWorkerStatusCode status);
// Removes any pending external request that has GUID of |request_uuid|.
void CleanUpExternalRequest(const std::string& request_uuid,
- ServiceWorkerStatusCode status);
+ blink::ServiceWorkerStatusCode status);
// Called if no inflight events exist on the browser process.
// Non-S13nServiceWorker: Triggers OnNoWork().
@@ -769,8 +798,12 @@ class CONTENT_EXPORT ServiceWorkerVersion
using RequestUUIDToRequestIDMap = std::map<std::string, int>;
RequestUUIDToRequestIDMap external_request_uuid_to_request_id_;
+ // List of UUIDs of external requests that were issued before this worker
+ // reached RUNNING.
+ std::set<std::string> pending_external_requests_;
+
// Connected to ServiceWorkerContextClient while the worker is running.
- mojom::ServiceWorkerEventDispatcherPtr event_dispatcher_;
+ mojom::ServiceWorkerPtr service_worker_ptr_;
// S13nServiceWorker: connected to the controller service worker.
// |controller_request_| is non-null only when the |controller_ptr_| is
@@ -807,10 +840,14 @@ class CONTENT_EXPORT ServiceWorkerVersion
std::map<std::string, ServiceWorkerProviderHost*> controllee_map_;
// Will be null while shutting down.
base::WeakPtr<ServiceWorkerContextCore> context_;
- base::ObserverList<Listener> listeners_;
+ base::ObserverList<Observer> observers_;
ServiceWorkerScriptCacheMap script_cache_map_;
base::OneShotTimer update_timer_;
+ // For scheduling Soft Update after main resource requests. See
+ // IncrementPendingUpdateHintCount() documentation.
+ int pending_update_hint_count_ = 0;
+
// Starts running in StartWorker and continues until the worker is stopped.
base::RepeatingTimer timeout_timer_;
// Holds the time the worker last started being considered idle.
@@ -833,10 +870,14 @@ class CONTENT_EXPORT ServiceWorkerVersion
bool skip_waiting_ = false;
bool skip_recording_startup_time_ = false;
bool force_bypass_cache_for_scripts_ = false;
- bool pause_after_download_ = false;
bool is_update_scheduled_ = false;
bool in_dtor_ = false;
+ // For service worker update checks. Non-null if pause after download during
+ // startup was requested. Once paused, the callback is run and reset to
+ // null.
+ base::OnceClosure pause_after_download_callback_;
+
std::unique_ptr<net::HttpResponseInfo> main_script_http_info_;
std::unique_ptr<blink::TrialTokenValidator::FeatureToTokensMap>
@@ -844,7 +885,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
// If not OK, the reason that StartWorker failed. Used for
// running |start_callbacks_|.
- ServiceWorkerStatusCode start_worker_status_ = SERVICE_WORKER_OK;
+ blink::ServiceWorkerStatusCode start_worker_status_ =
+ blink::ServiceWorkerStatusCode::kOk;
// The clock used to vend tick time.
const base::TickClock* tick_clock_;
@@ -852,11 +894,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
// The clock used for actual (wall clock) time
base::Clock* clock_;
- std::unique_ptr<PingController> ping_controller_;
+ ServiceWorkerPingController ping_controller_;
- // Used for recording worker activities (e.g., a ratio of handled events)
- // while this service worker is running (i.e., after it starts up until it
- // stops).
+ // Used for recording worker activities while this service worker is running
+ // (i.e., after it starts up until it stops). Created only when the service
+ // worker is speculatively launched for navigation hints.
std::unique_ptr<ServiceWorkerMetrics::ScopedEventRecorder> event_recorder_;
bool stop_when_devtools_detached_ = false;
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 dd8493e736a..2b3f97091de 100644
--- a/chromium/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/time.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
@@ -20,6 +20,7 @@
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
+#include "content/browser/service_worker/service_worker_ping_controller.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/common/service_worker/service_worker_utils.h"
@@ -86,6 +87,10 @@ class TestServiceImpl : public mojom::TestService {
NOTREACHED();
}
+ void DoCrashImmediately(DoCrashImmediatelyCallback callback) override {
+ NOTREACHED();
+ }
+
void CreateFolder(CreateFolderCallback callback) override { NOTREACHED(); }
void GetRequestorName(GetRequestorNameCallback callback) override {
@@ -103,17 +108,17 @@ class TestServiceImpl : public mojom::TestService {
void StartWorker(ServiceWorkerVersion* version,
ServiceWorkerMetrics::EventType purpose) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
version->StartWorker(purpose, CreateReceiverOnCurrentThread(&status));
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version->running_status());
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
}
class ServiceWorkerVersionTest : public testing::Test {
protected:
- struct RunningStateListener : public ServiceWorkerVersion::Listener {
+ struct RunningStateListener : public ServiceWorkerVersion::Observer {
RunningStateListener() : last_status(EmbeddedWorkerStatus::STOPPED) {}
~RunningStateListener() override {}
void OnRunningStateChanged(ServiceWorkerVersion* version) override {
@@ -122,7 +127,7 @@ class ServiceWorkerVersionTest : public testing::Test {
EmbeddedWorkerStatus last_status;
};
- struct CachedMetadataUpdateListener : public ServiceWorkerVersion::Listener {
+ struct CachedMetadataUpdateListener : public ServiceWorkerVersion::Observer {
CachedMetadataUpdateListener() = default;
~CachedMetadataUpdateListener() override = default;
void OnCachedMetadataUpdated(ServiceWorkerVersion* version,
@@ -164,13 +169,13 @@ class ServiceWorkerVersionTest : public testing::Test {
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
// Make the registration findable via storage functions.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
helper_->context()->storage()->StoreRegistration(
registration_.get(),
version_.get(),
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(SERVICE_WORKER_OK, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
}
virtual std::unique_ptr<MessageReceiver> GetMessageReceiver() {
@@ -183,15 +188,22 @@ class ServiceWorkerVersionTest : public testing::Test {
helper_.reset();
}
+ bool IsPingActivated(ServiceWorkerVersion* version) const {
+ return version->ping_controller_.IsActivated();
+ }
+
+ void NotifyScriptEvaluationStart(ServiceWorkerVersion* version) {
+ version->OnScriptEvaluationStart();
+ }
+
void SimulateDispatchEvent(ServiceWorkerMetrics::EventType event_type) {
- ServiceWorkerStatusCode status =
- SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
+ base::Optional<blink::ServiceWorkerStatusCode> status;
// Make sure worker is running.
version_->RunAfterStartWorker(event_type,
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Start request, as if an event is being dispatched.
@@ -203,7 +215,7 @@ class ServiceWorkerVersionTest : public testing::Test {
EXPECT_TRUE(version_->FinishRequest(request_id, true /* was_handled */,
base::Time::Now()));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
}
void SetTickClockForTesting(base::SimpleTestTickClock* tick_clock) {
@@ -233,7 +245,7 @@ class MessageReceiverDisallowStart : public MessageReceiver {
const GURL& scope,
const GURL& script_url,
bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ServiceWorkerRequest service_worker_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
@@ -245,8 +257,8 @@ class MessageReceiverDisallowStart : public MessageReceiver {
instance_host_ptr_map_[embedded_worker_id].Bind(
std::move(instance_host));
// Just keep the connection alive.
- event_dispatcher_request_map_[embedded_worker_id] =
- std::move(dispatcher_request);
+ service_worker_request_map_[embedded_worker_id] =
+ std::move(service_worker_request);
controller_request_map_[embedded_worker_id] =
std::move(controller_request);
break;
@@ -259,7 +271,7 @@ class MessageReceiverDisallowStart : public MessageReceiver {
case StartMode::SUCCEED:
MessageReceiver::OnStartWorker(
embedded_worker_id, service_worker_version_id, scope, script_url,
- pause_after_download, std::move(dispatcher_request),
+ pause_after_download, std::move(service_worker_request),
std::move(controller_request), std::move(instance_host),
std::move(provider_info), std::move(installed_scripts_info));
break;
@@ -286,9 +298,8 @@ class MessageReceiverDisallowStart : public MessageReceiver {
int /* embedded_worker_id */,
mojom::EmbeddedWorkerInstanceHostAssociatedPtr /* instance_host_ptr */>
instance_host_ptr_map_;
- std::map<int /* embedded_worker_id */,
- mojom::ServiceWorkerEventDispatcherRequest>
- event_dispatcher_request_map_;
+ std::map<int /* embedded_worker_id */, mojom::ServiceWorkerRequest>
+ service_worker_request_map_;
std::map<int /* embedded_worker_id */, mojom::ControllerServiceWorkerRequest>
controller_request_map_;
DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStart);
@@ -360,9 +371,9 @@ class ServiceWorkerStallInStoppingTest : public ServiceWorkerVersionTest {
TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
// Call StartWorker() multiple times.
- ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
- ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
- ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status1;
+ base::Optional<blink::ServiceWorkerStatusCode> status2;
+ base::Optional<blink::ServiceWorkerStatusCode> status3;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status1));
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -378,9 +389,9 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
base::RunLoop().RunUntilIdle();
// All should just succeed.
- EXPECT_EQ(SERVICE_WORKER_OK, status1);
- EXPECT_EQ(SERVICE_WORKER_OK, status2);
- EXPECT_EQ(SERVICE_WORKER_OK, status3);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status1.value());
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status2.value());
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status3.value());
{
// Call StopWorker() multiple times.
@@ -399,8 +410,8 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
}
// Start worker again.
- status1 = SERVICE_WORKER_ERROR_FAILED;
- status2 = SERVICE_WORKER_ERROR_FAILED;
+ status1.reset();
+ status2.reset();
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status1));
@@ -423,8 +434,8 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// All should just succeed.
- EXPECT_EQ(SERVICE_WORKER_OK, status1);
- EXPECT_EQ(SERVICE_WORKER_OK, status2);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status1.value());
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status2.value());
EXPECT_TRUE(has_stopped);
}
}
@@ -455,12 +466,12 @@ TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
// Delete the registration.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
helper_->context()->storage()->DeleteRegistration(
registration_->id(), registration_->pattern().GetOrigin(),
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(SERVICE_WORKER_OK, status);
+ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
// The live registration is marked as deleted, but still exists.
ASSERT_TRUE(registration_->is_deleted());
@@ -472,7 +483,6 @@ TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
EXPECT_TRUE(has_stopped);
// Dispatch an event on the unregistered and stopped but still live worker.
- status = SERVICE_WORKER_ERROR_FAILED;
SimulateDispatchEvent(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME);
// The worker should be now started again.
@@ -609,19 +619,17 @@ TEST_F(ServiceWorkerVersionTest, IdleTimeout) {
// Starting and finishing a request resets the idle time.
version_->idle_time_ -= kOneSecond;
idle_time = version_->idle_time_;
- ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
int request_id =
version_->StartRequest(ServiceWorkerMetrics::EventType::SYNC,
CreateReceiverOnCurrentThread(&status));
EXPECT_TRUE(version_->FinishRequest(request_id, true /* was_handled */,
base::Time::Now()));
-
- EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_LT(idle_time, version_->idle_time_);
}
TEST_F(ServiceWorkerVersionTest, SetDevToolsAttached) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
@@ -646,13 +654,13 @@ TEST_F(ServiceWorkerVersionTest, SetDevToolsAttached) {
EXPECT_TRUE(version_->skip_recording_startup_time_);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
TEST_F(ServiceWorkerVersionTest, StoppingBeforeDestruct) {
RunningStateListener listener;
- version_->AddListener(&listener);
+ version_->AddObserver(&listener);
StartWorker(version_.get(), ServiceWorkerMetrics::EventType::UNKNOWN);
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, listener.last_status);
@@ -767,7 +775,7 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_DoNotDeferTimer) {
TEST_F(ServiceWorkerVersionTest, UpdateCachedMetadata) {
CachedMetadataUpdateListener listener;
- version_->AddListener(&listener);
+ version_->AddObserver(&listener);
ASSERT_EQ(0, listener.updated_count);
StartWorker(version_.get(), ServiceWorkerMetrics::EventType::UNKNOWN);
@@ -786,7 +794,7 @@ TEST_F(ServiceWorkerVersionTest, UpdateCachedMetadata) {
version_->script_url());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, listener.updated_count);
- version_->RemoveListener(&listener);
+ version_->RemoveObserver(&listener);
}
TEST_F(ServiceWorkerVersionTest, RestartWorker) {
@@ -794,7 +802,7 @@ TEST_F(ServiceWorkerVersionTest, RestartWorker) {
ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME);
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- ServiceWorkerStatusCode event_status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> event_status;
version_->StartRequest(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
CreateReceiverOnCurrentThread(&event_status));
@@ -802,17 +810,17 @@ TEST_F(ServiceWorkerVersionTest, RestartWorker) {
bool has_stopped = false;
version_->StopWorker(base::BindOnce(&VerifyCalled, &has_stopped));
EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
- ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> start_status;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&start_status));
base::RunLoop().RunUntilIdle();
// All inflight events should have been aborted.
- EXPECT_EQ(event_status, SERVICE_WORKER_ERROR_FAILED);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed, event_status.value());
// The worker should have been stopped.
EXPECT_TRUE(has_stopped);
// The worker should have been successfully re-started after stopped.
- EXPECT_EQ(SERVICE_WORKER_OK, start_status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, start_status.value());
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// SetAllRequestExpirations() after restarting should not crash since all
@@ -827,8 +835,8 @@ class MessageReceiverControlEvents : public MessageReceiver {
void OnExtendableMessageEvent(
mojom::ExtendableMessageEventPtr event,
- mojom::ServiceWorkerEventDispatcher::
- DispatchExtendableMessageEventCallback callback) override {
+ mojom::ServiceWorker::DispatchExtendableMessageEventCallback callback)
+ override {
EXPECT_FALSE(extendable_message_event_callback_);
extendable_message_event_callback_ = std::move(callback);
}
@@ -844,7 +852,7 @@ class MessageReceiverControlEvents : public MessageReceiver {
return !extendable_message_event_callback_.is_null();
}
- mojom::ServiceWorkerEventDispatcher::DispatchExtendableMessageEventCallback
+ mojom::ServiceWorker::DispatchExtendableMessageEventCallback
TakeExtendableMessageEventCallback() {
return std::move(extendable_message_event_callback_);
}
@@ -854,7 +862,7 @@ class MessageReceiverControlEvents : public MessageReceiver {
}
private:
- mojom::ServiceWorkerEventDispatcher::DispatchExtendableMessageEventCallback
+ mojom::ServiceWorker::DispatchExtendableMessageEventCallback
extendable_message_event_callback_;
base::OnceClosure stop_worker_callback_;
};
@@ -872,7 +880,7 @@ class ServiceWorkerRequestTimeoutTest : public ServiceWorkerVersionTest {
->has_extendable_message_event_callback();
}
- mojom::ServiceWorkerEventDispatcher::DispatchExtendableMessageEventCallback
+ mojom::ServiceWorker::DispatchExtendableMessageEventCallback
TakeExtendableMessageEventCallback() {
return static_cast<MessageReceiverControlEvents*>(helper_.get())
->TakeExtendableMessageEventCallback();
@@ -888,8 +896,7 @@ class ServiceWorkerRequestTimeoutTest : public ServiceWorkerVersionTest {
};
TEST_F(ServiceWorkerRequestTimeoutTest, RequestTimeout) {
- ServiceWorkerStatusCode error_status =
- SERVICE_WORKER_ERROR_NETWORK; // dummy value
+ base::Optional<blink::ServiceWorkerStatusCode> error_status;
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
StartWorker(version_.get(),
ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME);
@@ -901,7 +908,7 @@ TEST_F(ServiceWorkerRequestTimeoutTest, RequestTimeout) {
// Dispatch a dummy event whose response will be received by SWVersion.
EXPECT_FALSE(has_extendable_message_event_callback());
- version_->event_dispatcher()->DispatchExtendableMessageEvent(
+ version_->endpoint()->DispatchExtendableMessageEvent(
mojom::ExtendableMessageEvent::New(),
version_->CreateSimpleEventCallback(request_id));
@@ -910,7 +917,7 @@ TEST_F(ServiceWorkerRequestTimeoutTest, RequestTimeout) {
EXPECT_TRUE(has_extendable_message_event_callback());
// Callback has not completed yet.
- EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, error_status);
+ EXPECT_FALSE(error_status);
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Simulate timeout.
@@ -925,7 +932,8 @@ TEST_F(ServiceWorkerRequestTimeoutTest, RequestTimeout) {
// The renderer should have received a StopWorker request.
EXPECT_TRUE(callback);
// The request should have timed out.
- EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, error_status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout,
+ error_status.value());
// Calling FinishRequest should be no-op, since the request timed out.
EXPECT_FALSE(version_->FinishRequest(request_id, true /* was_handled */,
base::Time::Now()));
@@ -943,7 +951,7 @@ TEST_F(ServiceWorkerRequestTimeoutTest, RequestTimeout) {
}
TEST_F(ServiceWorkerVersionTest, RequestNowTimeout) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
+ base::Optional<blink::ServiceWorkerStatusCode> status;
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
StartWorker(version_.get(), ServiceWorkerMetrics::EventType::SYNC);
@@ -957,7 +965,7 @@ TEST_F(ServiceWorkerVersionTest, RequestNowTimeout) {
EXPECT_TRUE(version_->timeout_timer_.IsRunning());
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout, status.value());
EXPECT_FALSE(version_->FinishRequest(request_id, true /* was_handled */,
base::Time::Now()));
@@ -967,7 +975,7 @@ TEST_F(ServiceWorkerVersionTest, RequestNowTimeout) {
}
TEST_F(ServiceWorkerVersionTest, RequestNowTimeoutKill) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
+ base::Optional<blink::ServiceWorkerStatusCode> status;
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
StartWorker(version_.get(), ServiceWorkerMetrics::EventType::SYNC);
@@ -981,7 +989,7 @@ TEST_F(ServiceWorkerVersionTest, RequestNowTimeoutKill) {
EXPECT_TRUE(version_->timeout_timer_.IsRunning());
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout, status.value());
EXPECT_FALSE(version_->FinishRequest(request_id, true /* was_handled */,
base::Time::Now()));
@@ -991,10 +999,8 @@ TEST_F(ServiceWorkerVersionTest, RequestNowTimeoutKill) {
}
TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
- ServiceWorkerStatusCode first_status =
- SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
- ServiceWorkerStatusCode second_status =
- SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
+ base::Optional<blink::ServiceWorkerStatusCode> first_status;
+ base::Optional<blink::ServiceWorkerStatusCode> second_status;
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
StartWorker(version_.get(), ServiceWorkerMetrics::EventType::SYNC);
@@ -1020,15 +1026,16 @@ TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
EXPECT_TRUE(version_->timeout_timer_.IsRunning());
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, first_status);
- EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, second_status);
+ EXPECT_FALSE(first_status);
+ EXPECT_FALSE(second_status);
// Now advance time until the second task timeout should expire.
tick_clock.Advance(base::TimeDelta::FromSeconds(timeout_seconds + 1));
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, first_status);
- EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, second_status);
+ EXPECT_FALSE(first_status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout,
+ second_status.value());
// CONTINUE_ON_TIMEOUT timeouts don't stop the service worker.
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
@@ -1037,8 +1044,10 @@ TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
tick_clock.Advance(base::TimeDelta::FromSeconds(timeout_seconds + 1));
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, first_status);
- EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, second_status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout,
+ first_status.value());
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout,
+ second_status.value());
EXPECT_FALSE(version_->FinishRequest(first_request_id, true /* was_handled */,
base::Time::Now()));
@@ -1051,10 +1060,8 @@ TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
}
TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
- ServiceWorkerStatusCode sync_status =
- SERVICE_WORKER_ERROR_NETWORK; // dummy value
- ServiceWorkerStatusCode fetch_status =
- SERVICE_WORKER_ERROR_NETWORK; // dummy value
+ base::Optional<blink::ServiceWorkerStatusCode> sync_status;
+ base::Optional<blink::ServiceWorkerStatusCode> fetch_status;
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
StartWorker(version_.get(),
ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME);
@@ -1069,14 +1076,14 @@ TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
CreateReceiverOnCurrentThread(&sync_status), base::TimeDelta(),
ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, sync_status);
+ EXPECT_FALSE(sync_status);
// Verify the sync has timed out but not the fetch.
EXPECT_TRUE(version_->timeout_timer_.IsRunning());
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, sync_status);
- EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, fetch_status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout, sync_status.value());
+ EXPECT_FALSE(fetch_status);
// Background sync timeouts don't stop the service worker.
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
@@ -1089,7 +1096,8 @@ TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
version_->SetAllRequestExpirations(base::TimeTicks::Now());
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, fetch_status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout,
+ fetch_status.value());
// Fetch request should no longer exist.
EXPECT_FALSE(version_->FinishRequest(fetch_request_id, true /* was_handled */,
@@ -1100,13 +1108,13 @@ TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
}
TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
+ base::Optional<blink::ServiceWorkerStatusCode> status;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
// Callback has not completed yet.
- EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
+ EXPECT_FALSE(status);
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
// Simulate renderer crash: break EmbeddedWorkerInstance's Mojo connection to
@@ -1115,12 +1123,13 @@ TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
base::RunLoop().RunUntilIdle();
// Callback completed.
- EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed,
+ status.value());
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
}
TEST_F(ServiceWorkerFailToStartTest, Timeout) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
+ base::Optional<blink::ServiceWorkerStatusCode> status;
// Start starting the worker.
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -1128,7 +1137,7 @@ TEST_F(ServiceWorkerFailToStartTest, Timeout) {
base::RunLoop().RunUntilIdle();
// Callback has not completed yet.
- EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
+ EXPECT_FALSE(status);
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
// Simulate timeout.
@@ -1138,7 +1147,7 @@ TEST_F(ServiceWorkerFailToStartTest, Timeout) {
base::TimeDelta::FromMinutes(1);
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout, status.value());
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
}
@@ -1189,7 +1198,7 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
// Worker is now stalled in stopping. Add a start worker request.
- ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
+ base::Optional<blink::ServiceWorkerStatusCode> start_status;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&start_status));
@@ -1201,21 +1210,21 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(has_stopped);
- EXPECT_EQ(SERVICE_WORKER_OK, start_status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, start_status.value());
}
TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
StartWorker(version_.get(), ServiceWorkerMetrics::EventType::SYNC);
- ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
int request_id =
version_->StartRequest(ServiceWorkerMetrics::EventType::SYNC,
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
// Callback has not completed yet.
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_FALSE(status);
// Simulate renderer crash: break EmbeddedWorkerInstance's Mojo connection to
// the renderer-side client.
@@ -1223,7 +1232,7 @@ TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
base::RunLoop().RunUntilIdle();
// Callback completed.
- EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed, status.value());
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
// Request already failed, calling finsh should return false.
@@ -1231,6 +1240,22 @@ TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
base::Time::Now()));
}
+TEST_F(ServiceWorkerVersionTest, PingController) {
+ // Start starting an worker. Ping should not be active.
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ base::DoNothing());
+ EXPECT_FALSE(IsPingActivated(version_.get()));
+
+ // Start script evaluation. Ping should be active.
+ NotifyScriptEvaluationStart(version_.get());
+ EXPECT_TRUE(IsPingActivated(version_.get()));
+
+ // Finish starting the worker. Ping should still be active.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
+ EXPECT_TRUE(IsPingActivated(version_.get()));
+}
+
// Test starting a service worker from a disallowed origin.
TEST_F(ServiceWorkerVersionTest, BadOrigin) {
const GURL scope("bad-origin://www.example.com/test/");
@@ -1244,15 +1269,15 @@ TEST_F(ServiceWorkerVersionTest, BadOrigin) {
GURL("bad-origin://www.example.com/test/service_worker.js"),
helper_->context()->storage()->NewVersionId(),
helper_->context()->AsWeakPtr());
- ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
version->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_DISALLOWED, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorDisallowed, status.value());
}
TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
ServiceWorkerContextCore* context = helper_->context();
int64_t id = version_->version_id();
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -1262,33 +1287,38 @@ TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
EXPECT_EQ(helper_->mock_render_process_id(),
version_->embedded_worker()->process_id());
version_->StopWorker(base::DoNothing());
base::RunLoop().RunUntilIdle();
// Fail once.
+ status.reset();
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(blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed,
+ status.value());
EXPECT_EQ(1, context->GetVersionFailureCount(id));
// Fail again.
+ status.reset();
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed,
+ status.value());
EXPECT_EQ(2, context->GetVersionFailureCount(id));
// Succeed. It should choose the "new process".
+ status.reset();
set_start_mode(MessageReceiverDisallowStart::StartMode::SUCCEED);
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
EXPECT_EQ(helper_->new_render_process_id(),
version_->embedded_worker()->process_id());
EXPECT_EQ(0, context->GetVersionFailureCount(id));
@@ -1297,10 +1327,11 @@ TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
// Start again. It should choose the "existing process" again as we no longer
// force creation of a new process.
+ status.reset();
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
EXPECT_EQ(helper_->mock_render_process_id(),
version_->embedded_worker()->process_id());
version_->StopWorker(base::DoNothing());
@@ -1308,13 +1339,13 @@ TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
}
TEST_F(ServiceWorkerFailToStartTest, RestartStalledWorker) {
- ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
- CreateReceiverOnCurrentThread(&status1));
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
// The default start mode is StartMode::STALL. So the callback of StartWorker
// is not called yet.
- EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status1);
+ EXPECT_FALSE(status);
// Set StartMode::SUCCEED. So the next start worker will be successful.
set_start_mode(MessageReceiverDisallowStart::StartMode::SUCCEED);
@@ -1325,7 +1356,7 @@ TEST_F(ServiceWorkerFailToStartTest, RestartStalledWorker) {
version_->StopWorker(base::BindOnce(&VerifyCalled, &has_stopped));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status1);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
EXPECT_TRUE(has_stopped);
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
@@ -1335,10 +1366,10 @@ class ServiceWorkerNavigationHintUMATest : public ServiceWorkerVersionTest {
ServiceWorkerNavigationHintUMATest() : ServiceWorkerVersionTest() {}
void StartWorker(ServiceWorkerMetrics::EventType purpose) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> status;
version_->StartWorker(purpose, CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
}
void StopWorker() {
@@ -1387,28 +1418,28 @@ TEST_F(ServiceWorkerNavigationHintUMATest, Precision) {
TEST_F(ServiceWorkerNavigationHintUMATest, ConcurrentStart) {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_MAX_VALUE;
- ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::Optional<blink::ServiceWorkerStatusCode> status1;
+ base::Optional<blink::ServiceWorkerStatusCode> status2;
version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
CreateReceiverOnCurrentThread(&status1));
version_->StartWorker(ServiceWorkerMetrics::EventType::NAVIGATION_HINT,
CreateReceiverOnCurrentThread(&status2));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status1);
- EXPECT_EQ(SERVICE_WORKER_OK, status2);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status1.value());
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status2.value());
StopWorker();
// The first purpose of starting worker was not a navigation hint.
histogram_tester_.ExpectTotalCount(kStartHintPrecision, 0);
- status1 = SERVICE_WORKER_ERROR_MAX_VALUE;
- status2 = SERVICE_WORKER_ERROR_MAX_VALUE;
+ status1.reset();
+ status2.reset();
version_->StartWorker(ServiceWorkerMetrics::EventType::NAVIGATION_HINT,
CreateReceiverOnCurrentThread(&status2));
version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
CreateReceiverOnCurrentThread(&status1));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status1);
- EXPECT_EQ(SERVICE_WORKER_OK, status2);
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status1.value());
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status2.value());
SimulateDispatchEvent(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME);
StopWorker();
// The first purpose of starting worker was a navigation hint.
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 7b25cc96dcd..25c0d8f11e2 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
@@ -476,7 +476,8 @@ net::Error ServiceWorkerWriteToCacheJob::NotifyFinishedCaching(
// equivalent, the new version didn't actually install because it already
// exists.
if (net_error == net::OK && !cache_writer_->did_replace()) {
- version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS);
+ version_->SetStartWorkerStatusCode(
+ blink::ServiceWorkerStatusCode::kErrorExists);
version_->script_cache_map()->NotifyFinishedCaching(
url_, size, kIdenticalScriptError, std::string());
} else {
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 1a3a3f2ad9a..46572db78e5 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
@@ -15,12 +15,12 @@
#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/browser/service_worker/service_worker_version.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"
#include "net/base/net_errors.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
+#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace content {
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
index 0b248f1fd2e..516c5b96b1a 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
@@ -210,8 +210,10 @@ class ResponseVerifier : public base::RefCounted<ResponseVerifier> {
public:
ResponseVerifier(std::unique_ptr<ServiceWorkerResponseReader> reader,
const std::string& expected,
- const base::Callback<void(bool)> callback)
- : reader_(reader.release()), expected_(expected), callback_(callback) {}
+ base::OnceCallback<void(bool)> callback)
+ : reader_(reader.release()),
+ expected_(expected),
+ callback_(std::move(callback)) {}
void Start() {
info_buffer_ = new HttpResponseInfoIOBuffer();
@@ -224,12 +226,12 @@ class ResponseVerifier : public base::RefCounted<ResponseVerifier> {
void OnReadInfoComplete(int result) {
if (result < 0) {
- callback_.Run(false);
+ std::move(callback_).Run(false);
return;
}
if (info_buffer_->response_data_size !=
static_cast<int>(expected_.size())) {
- callback_.Run(false);
+ std::move(callback_).Run(false);
return;
}
ReadSomeData();
@@ -243,17 +245,17 @@ class ResponseVerifier : public base::RefCounted<ResponseVerifier> {
void OnReadDataComplete(int result) {
if (result < 0) {
- callback_.Run(false);
+ std::move(callback_).Run(false);
return;
}
if (result == 0) {
- callback_.Run(true);
+ std::move(callback_).Run(true);
return;
}
std::string str(io_buffer_->data(), result);
std::string expect = expected_.substr(bytes_read_, result);
if (str != expect) {
- callback_.Run(false);
+ std::move(callback_).Run(false);
return;
}
bytes_read_ += result;
@@ -266,7 +268,7 @@ class ResponseVerifier : public base::RefCounted<ResponseVerifier> {
std::unique_ptr<ServiceWorkerResponseReader> reader_;
const std::string expected_;
- base::Callback<void(bool)> callback_;
+ base::OnceCallback<void(bool)> callback_;
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_;
scoped_refptr<net::IOBuffer> io_buffer_;
size_t bytes_read_;
@@ -288,13 +290,9 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
base::WeakPtr<ServiceWorkerProviderHost> CreateHostForVersion(
int process_id,
const scoped_refptr<ServiceWorkerVersion>& version) {
- std::unique_ptr<ServiceWorkerProviderHost> host =
- CreateProviderHostForServiceWorkerContext(
- process_id, true /* is_parent_frame_secure */, version.get(),
- context()->AsWeakPtr(), &remote_endpoint_);
- base::WeakPtr<ServiceWorkerProviderHost> host_weakptr = host->AsWeakPtr();
- context()->AddProviderHost(std::move(host));
- return host_weakptr;
+ return CreateProviderHostForServiceWorkerContext(
+ process_id, true /* is_parent_frame_secure */, version.get(),
+ context()->AsWeakPtr(), &remote_endpoint_);
}
void SetUpScriptRequest(int process_id, int provider_id) {
@@ -393,7 +391,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);
+ new_version->SetToPauseAfterDownload(base::DoNothing());
base::WeakPtr<ServiceWorkerProviderHost> host =
CreateHostForVersion(helper_->mock_render_process_id(), new_version);
EXPECT_TRUE(host);
@@ -407,14 +405,14 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
void VerifyResource(int64_t id, const std::string& expected) {
ASSERT_NE(kInvalidServiceWorkerResourceId, id);
- bool is_equal = false;
+ base::Optional<bool> is_equal;
std::unique_ptr<ServiceWorkerResponseReader> reader =
context()->storage()->CreateResponseReader(id);
scoped_refptr<ResponseVerifier> verifier = new ResponseVerifier(
std::move(reader), expected, CreateReceiverOnCurrentThread(&is_equal));
verifier->Start();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(is_equal);
+ EXPECT_TRUE(is_equal.value());
}
ServiceWorkerContextCore* context() const { return helper_->context(); }
diff --git a/chromium/content/browser/shared_worker/OWNERS b/chromium/content/browser/shared_worker/OWNERS
index 595a38572a7..6bda8b5e83f 100644
--- a/chromium/content/browser/shared_worker/OWNERS
+++ b/chromium/content/browser/shared_worker/OWNERS
@@ -1,3 +1,4 @@
+falken@chromium.org
horo@chromium.org
nhiroki@chromium.org
diff --git a/chromium/content/browser/shared_worker/mock_shared_worker.cc b/chromium/content/browser/shared_worker/mock_shared_worker.cc
index 32ce0577fdc..829d18dce64 100644
--- a/chromium/content/browser/shared_worker/mock_shared_worker.cc
+++ b/chromium/content/browser/shared_worker/mock_shared_worker.cc
@@ -4,6 +4,7 @@
#include "content/browser/shared_worker/mock_shared_worker.h"
+#include "content/common/url_loader_factory_bundle.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -97,11 +98,13 @@ void MockSharedWorkerFactory::CreateSharedWorker(
mojom::SharedWorkerInfoPtr info,
bool pause_on_start,
const base::UnguessableToken& devtools_worker_token,
+ const RendererPreferences& renderer_preferences,
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_ptr_info,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
mojom::SharedWorkerHostPtr host,
mojom::SharedWorkerRequest request,
service_manager::mojom::InterfaceProviderPtr interface_provider) {
diff --git a/chromium/content/browser/shared_worker/mock_shared_worker.h b/chromium/content/browser/shared_worker/mock_shared_worker.h
index 791fdb17060..7d99113c488 100644
--- a/chromium/content/browser/shared_worker/mock_shared_worker.h
+++ b/chromium/content/browser/shared_worker/mock_shared_worker.h
@@ -22,6 +22,7 @@
class GURL;
namespace content {
+class URLLoaderFactoryBundleInfo;
class MockSharedWorker : public mojom::SharedWorker {
public:
@@ -66,11 +67,13 @@ class MockSharedWorkerFactory : public mojom::SharedWorkerFactory {
mojom::SharedWorkerInfoPtr info,
bool pause_on_start,
const base::UnguessableToken& devtools_worker_token,
+ const RendererPreferences& renderer_preferences,
blink::mojom::WorkerContentSettingsProxyPtr content_settings,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_ptr_info,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
mojom::SharedWorkerHostPtr host,
mojom::SharedWorkerRequest request,
service_manager::mojom::InterfaceProviderPtr interface_provider) override;
diff --git a/chromium/content/browser/shared_worker/shared_worker_connector_impl.cc b/chromium/content/browser/shared_worker/shared_worker_connector_impl.cc
index 4b08ffd8b66..2fe70f50171 100644
--- a/chromium/content/browser/shared_worker/shared_worker_connector_impl.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_connector_impl.cc
@@ -33,19 +33,31 @@ void SharedWorkerConnectorImpl::Connect(
mojom::SharedWorkerInfoPtr info,
mojom::SharedWorkerClientPtr client,
blink::mojom::SharedWorkerCreationContextType creation_context_type,
- mojo::ScopedMessagePipeHandle message_port) {
+ mojo::ScopedMessagePipeHandle message_port,
+ blink::mojom::BlobURLTokenPtr blob_url_token) {
RenderProcessHost* host = RenderProcessHost::FromID(process_id_);
// The render process was already terminated.
if (!host) {
client->OnScriptLoadFailed();
return;
}
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
+ if (blob_url_token) {
+ if (!info->url.SchemeIsBlob()) {
+ mojo::ReportBadMessage("SWCI_BLOB_URL_TOKEN_FOR_NON_BLOB_URL");
+ return;
+ }
+ blob_url_loader_factory =
+ ChromeBlobStorageContext::URLLoaderFactoryForToken(
+ host->GetBrowserContext(), std::move(blob_url_token));
+ }
SharedWorkerServiceImpl* service =
static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
->GetSharedWorkerService();
service->ConnectToWorker(process_id_, frame_id_, std::move(info),
std::move(client), creation_context_type,
- blink::MessagePortChannel(std::move(message_port)));
+ blink::MessagePortChannel(std::move(message_port)),
+ std::move(blob_url_loader_factory));
}
} // namespace content
diff --git a/chromium/content/browser/shared_worker/shared_worker_connector_impl.h b/chromium/content/browser/shared_worker/shared_worker_connector_impl.h
index 2c609c680d6..bd85820db69 100644
--- a/chromium/content/browser/shared_worker/shared_worker_connector_impl.h
+++ b/chromium/content/browser/shared_worker/shared_worker_connector_impl.h
@@ -27,7 +27,8 @@ class CONTENT_EXPORT SharedWorkerConnectorImpl
mojom::SharedWorkerInfoPtr info,
mojom::SharedWorkerClientPtr client,
blink::mojom::SharedWorkerCreationContextType creation_context_type,
- mojo::ScopedMessagePipeHandle message_port) override;
+ mojo::ScopedMessagePipeHandle message_port,
+ blink::mojom::BlobURLTokenPtr blob_url_token) override;
const int process_id_;
const int frame_id_;
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.cc b/chromium/content/browser/shared_worker/shared_worker_host.cc
index 107d46564b9..407310cc763 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_host.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "base/unguessable_token.h"
#include "content/browser/devtools/shared_worker_devtools_manager.h"
@@ -14,11 +15,14 @@
#include "content/browser/shared_worker/shared_worker_content_settings_proxy_impl.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
#include "content/browser/shared_worker/shared_worker_service_impl.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/common/url_loader_factory_bundle.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/render_process_host.h"
#include "content/public/common/content_client.h"
+#include "services/network/public/cpp/features.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "third_party/blink/public/platform/web_feature.mojom.h"
#include "third_party/blink/public/web/worker_content_settings_proxy.mojom.h"
@@ -121,7 +125,8 @@ void SharedWorkerHost::Start(
mojom::SharedWorkerFactoryPtr factory,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory) {
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
AdvanceTo(Phase::kStarted);
@@ -136,6 +141,11 @@ void SharedWorkerHost::Start(
devtools_handle_ = std::make_unique<ScopedDevToolsHandle>(
this, &pause_on_start, &devtools_worker_token);
+ RendererPreferences renderer_preferences;
+ GetContentClient()->browser()->UpdateRendererPreferencesForWorker(
+ RenderProcessHost::FromID(process_id_)->GetBrowserContext(),
+ &renderer_preferences);
+
// Set up content settings interface.
blink::mojom::WorkerContentSettingsProxyPtr content_settings;
content_settings_ = std::make_unique<SharedWorkerContentSettingsProxyImpl>(
@@ -151,19 +161,60 @@ void SharedWorkerHost::Start(
mojom::kNavigation_SharedWorkerSpec, process_id_,
mojo::MakeRequest(&interface_provider)));
+ // Add the network factory to the bundle to pass to the renderer. The bundle
+ // is only provided (along with |script_loader_factory|) if
+ // NetworkService/S13nSW is enabled.
+ DCHECK(!script_loader_factory || factory_bundle);
+ if (factory_bundle) {
+ network::mojom::URLLoaderFactoryPtrInfo network_factory_info;
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // NetworkService is on: Use the network service.
+ CreateNetworkFactory(mojo::MakeRequest(&network_factory_info));
+ } else {
+ // NetworkService is off: RenderProcessHost gives us a non-NetworkService
+ // network factory.
+ RenderProcessHost::FromID(process_id_)
+ ->CreateURLLoaderFactory(mojo::MakeRequest(&network_factory_info));
+ }
+ DCHECK(!factory_bundle->default_factory_info());
+ factory_bundle->default_factory_info() = std::move(network_factory_info);
+
+ // TODO(falken): We might need to set the default factory to AppCache
+ // instead, as we do for frames, if requests from this shared worker are
+ // supposed to go through AppCache.
+ }
+
// Send the CreateSharedWorker message.
factory_ = std::move(factory);
factory_->CreateSharedWorker(
std::move(info), pause_on_start, devtools_worker_token,
- std::move(content_settings), std::move(service_worker_provider_info),
- std::move(script_loader_factory), std::move(host),
- std::move(worker_request_), std::move(interface_provider));
+ renderer_preferences, std::move(content_settings),
+ std::move(service_worker_provider_info), std::move(script_loader_factory),
+ std::move(factory_bundle), std::move(host), std::move(worker_request_),
+ std::move(interface_provider));
// Monitor the lifetime of the worker.
worker_.set_connection_error_handler(base::BindOnce(
&SharedWorkerHost::OnWorkerConnectionLost, weak_factory_.GetWeakPtr()));
}
+// This is similar to
+// RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve.
+void SharedWorkerHost::CreateNetworkFactory(
+ network::mojom::URLLoaderFactoryRequest request) {
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = process_id_;
+ // TODO(lukasza): https://crbug.com/792546: Start using CORB.
+ params->is_corb_enabled = false;
+
+ service_->storage_partition()->GetNetworkContext()->CreateURLLoaderFactory(
+ std::move(request), std::move(params));
+
+ // TODO(crbug.com/848256): Detect connection error and send a IPC with a new
+ // network factory like UpdateSubresourceLoaderFactories does for frames.
+}
+
void SharedWorkerHost::AllowFileSystem(
const GURL& url,
base::OnceCallback<void(bool)> callback) {
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.h b/chromium/content/browser/shared_worker/shared_worker_host.h
index e6f1f73f997..95f9f2c26fd 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.h
+++ b/chromium/content/browser/shared_worker/shared_worker_host.h
@@ -36,6 +36,7 @@ namespace content {
class SharedWorkerContentSettingsProxyImpl;
class SharedWorkerInstance;
class SharedWorkerServiceImpl;
+class URLLoaderFactoryBundleInfo;
// The SharedWorkerHost is the interface that represents the browser side of
// the browser <-> worker communication channel. This is owned by
@@ -66,7 +67,8 @@ class CONTENT_EXPORT SharedWorkerHost
mojom::SharedWorkerFactoryPtr factory,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory);
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle);
void AllowFileSystem(const GURL& url,
base::OnceCallback<void(bool)> callback);
@@ -137,6 +139,8 @@ class CONTENT_EXPORT SharedWorkerHost
void GetInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
+ void CreateNetworkFactory(network::mojom::URLLoaderFactoryRequest request);
+
void AdvanceTo(Phase phase);
mojo::Binding<mojom::SharedWorkerHost> binding_;
diff --git a/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc b/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc
index a00d44ffb4b..f90a0342ef7 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc
@@ -14,10 +14,14 @@
#include "content/browser/shared_worker/shared_worker_connector_impl.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
#include "content/browser/shared_worker/shared_worker_service_impl.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_storage_partition.h"
#include "content/public/test/test_utils.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/test_support/test_utils.h"
+#include "services/network/test/test_network_context.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "url/origin.h"
@@ -28,7 +32,11 @@ namespace content {
class SharedWorkerHostTest : public testing::Test {
public:
- SharedWorkerHostTest() : service_(nullptr) {}
+ SharedWorkerHostTest()
+ : mock_render_process_host_(&browser_context_),
+ service_(&storage_partition_, nullptr /* service_worker_context */) {
+ storage_partition_.set_network_context(&network_context_);
+ }
base::WeakPtr<SharedWorkerHost> CreateHost() {
GURL url("http://www.example.com/w.js");
@@ -47,7 +55,7 @@ class SharedWorkerHostTest : public testing::Test {
content_security_policy_type, creation_address_space,
creation_context_type);
auto host = std::make_unique<SharedWorkerHost>(
- &service_, std::move(instance), 11 /* dummy process_id */);
+ &service_, std::move(instance), mock_render_process_host_.GetID());
auto weak_host = host->AsWeakPtr();
service_.worker_hosts_.insert(std::move(host));
return weak_host;
@@ -56,7 +64,8 @@ class SharedWorkerHostTest : public testing::Test {
void StartWorker(SharedWorkerHost* host,
mojom::SharedWorkerFactoryPtr factory) {
host->Start(std::move(factory), nullptr /* service_worker_provider_info */,
- {} /* script_loader_factory_info */);
+ {} /* script_loader_factory_info */,
+ nullptr /* factory_bundle */);
}
MessagePortChannel AddClient(SharedWorkerHost* host,
@@ -71,6 +80,11 @@ class SharedWorkerHostTest : public testing::Test {
protected:
TestBrowserThreadBundle test_browser_thread_bundle_;
+ TestStoragePartition storage_partition_;
+ network::TestNetworkContext network_context_;
+ TestBrowserContext browser_context_;
+ MockRenderProcessHost mock_render_process_host_;
+
SharedWorkerServiceImpl service_;
DISALLOW_COPY_AND_ASSIGN(SharedWorkerHostTest);
@@ -181,7 +195,8 @@ TEST_F(SharedWorkerHostTest, TerminateAfterStarting) {
// Start the worker.
host->Start(std::move(factory), nullptr /* service_worker_provider_info */,
- {} /* script_loader_factory_info */);
+ {} /* script_loader_factory_info */,
+ nullptr /* factory_bundle */);
// Add a client.
MockSharedWorkerClient client;
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_loader.cc b/chromium/content/browser/shared_worker/shared_worker_script_loader.cc
index 2a540fac395..81fb3763c49 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader.cc
@@ -6,10 +6,10 @@
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
-#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/resource_context.h"
#include "net/url_request/redirect_util.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
@@ -34,7 +34,7 @@ SharedWorkerScriptLoader::SharedWorkerScriptLoader(
traffic_annotation_(traffic_annotation),
url_loader_client_binding_(this),
weak_factory_(this) {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
if (service_worker_provider_host_) {
service_worker_interceptor_ =
@@ -76,8 +76,6 @@ void SharedWorkerScriptLoader::MaybeStartLoader(
return;
}
- // TODO(falken): Support blob urls.
-
LoadFromNetwork();
}
@@ -96,6 +94,8 @@ void SharedWorkerScriptLoader::LoadFromNetwork() {
// the new URL.
void SharedWorkerScriptLoader::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
"headers was not supported "
@@ -107,7 +107,8 @@ void SharedWorkerScriptLoader::FollowRedirect(
bool should_clear_upload = false;
net::RedirectUtil::UpdateHttpRequest(
resource_request_.url, resource_request_.method, *redirect_info_,
- &resource_request_.headers, &should_clear_upload);
+ modified_request_headers, &resource_request_.headers,
+ &should_clear_upload);
resource_request_.url = redirect_info_->new_url;
resource_request_.method = redirect_info_->new_method;
@@ -151,9 +152,8 @@ void SharedWorkerScriptLoader::ResumeReadingBodyFromNet() {
// calls FollowRedirect(), it can do so.
void SharedWorkerScriptLoader::OnReceiveResponse(
- const network::ResourceResponseHead& response_head,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
- client_->OnReceiveResponse(response_head, std::move(downloaded_file));
+ const network::ResourceResponseHead& response_head) {
+ client_->OnReceiveResponse(response_head);
}
void SharedWorkerScriptLoader::OnReceiveRedirect(
@@ -169,11 +169,6 @@ void SharedWorkerScriptLoader::OnReceiveRedirect(
client_->OnReceiveRedirect(redirect_info, response_head);
}
-void SharedWorkerScriptLoader::OnDataDownloaded(int64_t data_len,
- int64_t encoded_data_len) {
- client_->OnDataDownloaded(data_len, encoded_data_len);
-}
-
void SharedWorkerScriptLoader::OnUploadProgress(
int64_t current_position,
int64_t total_size,
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_loader.h b/chromium/content/browser/shared_worker/shared_worker_script_loader.h
index 3868aedd721..e7eb646e6a3 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader.h
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader.h
@@ -53,7 +53,9 @@ class SharedWorkerScriptLoader : public network::mojom::URLLoader,
~SharedWorkerScriptLoader() override;
// network::mojom::URLLoader:
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
@@ -63,12 +65,10 @@ class SharedWorkerScriptLoader : public network::mojom::URLLoader,
// network::mojom::URLLoaderClient:
void OnReceiveResponse(
- const network::ResourceResponseHead& response_head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override;
+ const network::ResourceResponseHead& response_head) override;
void OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head) override;
- void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc b/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc
index 08260e2484f..6a21c378c48 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc
@@ -10,10 +10,10 @@
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/shared_worker/shared_worker_script_loader.h"
-#include "content/common/service_worker/service_worker_utils.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
namespace content {
@@ -26,7 +26,7 @@ SharedWorkerScriptLoaderFactory::SharedWorkerScriptLoaderFactory(
: service_worker_provider_host_(service_worker_provider_host),
resource_context_(resource_context),
loader_factory_(std::move(loader_factory)) {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
DCHECK_EQ(service_worker_provider_host_->provider_type(),
blink::mojom::ServiceWorkerProviderType::kForSharedWorker);
}
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 8140ae678d3..0727104684b 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -12,13 +12,15 @@
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/task_scheduler/post_task.h"
+#include "content/browser/file_url_loader_factory.h"
#include "content/browser/shared_worker/shared_worker_host.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
#include "content/browser/shared_worker/shared_worker_script_loader_factory.h"
#include "content/browser/storage_partition_impl.h"
+#include "content/browser/url_loader_factory_getter.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/service_worker/service_worker_provider.mojom.h"
-#include "content/common/service_worker/service_worker_utils.h"
#include "content/common/shared_worker/shared_worker_client.mojom.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
@@ -29,6 +31,7 @@
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "url/origin.h"
namespace content {
@@ -39,13 +42,58 @@ bool IsShuttingDown(RenderProcessHost* host) {
host->IsKeepAliveRefCountDisabled();
}
+std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle(
+ int process_id,
+ StoragePartitionImpl* storage_partition,
+ bool file_support) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ ContentBrowserClient::NonNetworkURLLoaderFactoryMap factories;
+ GetContentClient()
+ ->browser()
+ ->RegisterNonNetworkSubresourceURLLoaderFactories(
+ process_id, MSG_ROUTING_NONE, &factories);
+
+ auto factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
+ for (auto& pair : factories) {
+ const std::string& scheme = pair.first;
+ std::unique_ptr<network::mojom::URLLoaderFactory> factory =
+ std::move(pair.second);
+
+ network::mojom::URLLoaderFactoryPtr factory_ptr;
+ mojo::MakeStrongBinding(std::move(factory),
+ mojo::MakeRequest(&factory_ptr));
+ factory_bundle->factories_info().emplace(scheme,
+ factory_ptr.PassInterface());
+ }
+
+ if (file_support) {
+ auto file_factory = std::make_unique<FileURLLoaderFactory>(
+ storage_partition->browser_context()->GetPath(),
+ base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
+ network::mojom::URLLoaderFactoryPtr file_factory_ptr;
+ mojo::MakeStrongBinding(std::move(file_factory),
+ mojo::MakeRequest(&file_factory_ptr));
+ factory_bundle->factories_info().emplace(url::kFileScheme,
+ file_factory_ptr.PassInterface());
+ }
+ return factory_bundle;
+}
+
void CreateScriptLoaderOnIO(
scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
- std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_info,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser_info,
+ std::unique_ptr<URLLoaderFactoryBundleInfo>
+ factory_bundle_for_renderer_info,
scoped_refptr<ServiceWorkerContextWrapper> context,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ blob_url_loader_factory_info,
int process_id,
base::OnceCallback<void(mojom::ServiceWorkerProviderInfoForSharedWorkerPtr,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo)>
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo,
+ std::unique_ptr<URLLoaderFactoryBundleInfo>)>
callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -54,46 +102,54 @@ void CreateScriptLoaderOnIO(
base::WeakPtr<ServiceWorkerProviderHost> host =
context->PreCreateHostForSharedWorker(process_id, &provider_info);
- // Create the factory bundle for loading the script.
- scoped_refptr<URLLoaderFactoryBundle> factory_bundle =
- base::MakeRefCounted<URLLoaderFactoryBundle>(
- std::move(factory_bundle_info));
-
- // Add the network factory to the bundle. The factory from
- // CloneNetworkFactory() doesn't support reconnection to the network service
- // after a crash, but it's OK since it's used for a single shared worker
- // startup.
- network::mojom::URLLoaderFactoryPtr network_factory_ptr;
- loader_factory_getter->CloneNetworkFactory(
- mojo::MakeRequest(&network_factory_ptr));
- factory_bundle->SetDefaultFactory(std::move(network_factory_ptr));
+ // Create the URL loader factory for SharedWorkerScriptLoaderFactory to use to
+ // load the main script.
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
+ if (blob_url_loader_factory_info) {
+ // If we have a blob_url_loader_factory just use that directly rather than
+ // creating a new URLLoaderFactoryBundle.
+ url_loader_factory = network::SharedURLLoaderFactory::Create(
+ std::move(blob_url_loader_factory_info));
+ } else {
+ // Create a factory bundle to use.
+ scoped_refptr<URLLoaderFactoryBundle> factory_bundle =
+ base::MakeRefCounted<URLLoaderFactoryBundle>(
+ std::move(factory_bundle_for_browser_info));
+ url_loader_factory = factory_bundle;
+
+ // Add the network factory to the bundle. The factory from
+ // CloneNetworkFactory() doesn't support reconnection to the network service
+ // after a crash, but it's OK since it's used for a single shared worker
+ // startup.
+ network::mojom::URLLoaderFactoryPtr network_factory_ptr;
+ loader_factory_getter->CloneNetworkFactory(
+ mojo::MakeRequest(&network_factory_ptr));
+ factory_bundle->SetDefaultFactory(std::move(network_factory_ptr));
+ }
// Create the SharedWorkerScriptLoaderFactory.
network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory;
mojo::MakeStrongAssociatedBinding(
std::make_unique<SharedWorkerScriptLoaderFactory>(
context.get(), host->AsWeakPtr(), context->resource_context(),
- std::move(factory_bundle)),
+ std::move(url_loader_factory)),
mojo::MakeRequest(&script_loader_factory));
- // TODO(falken): Also send the factory bundle to the renderer like
- // CommitNavigation does, to be used for subresource requests from the shared
- // worker (SharedWorkerScriptLoaderFactory is only used for the main resource
- // request). However, the restartable network factory should be used in this
- // case.
-
// We continue in StartWorker.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(callback), std::move(provider_info),
- std::move(script_loader_factory)));
+ std::move(script_loader_factory),
+ std::move(factory_bundle_for_renderer_info)));
}
} // namespace
SharedWorkerServiceImpl::SharedWorkerServiceImpl(
+ StoragePartition* storage_partition,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
- : service_worker_context_(std::move(service_worker_context)),
+ : storage_partition_(storage_partition),
+ service_worker_context_(std::move(service_worker_context)),
weak_factory_(this) {}
SharedWorkerServiceImpl::~SharedWorkerServiceImpl() {}
@@ -135,7 +191,8 @@ void SharedWorkerServiceImpl::ConnectToWorker(
mojom::SharedWorkerInfoPtr info,
mojom::SharedWorkerClientPtr client,
blink::mojom::SharedWorkerCreationContextType creation_context_type,
- const blink::MessagePortChannel& message_port) {
+ const blink::MessagePortChannel& message_port,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHostImpl* render_frame_host =
@@ -187,7 +244,7 @@ void SharedWorkerServiceImpl::ConnectToWorker(
}
CreateWorker(std::move(instance), std::move(client), process_id, frame_id,
- message_port);
+ message_port, std::move(blob_url_loader_factory));
}
void SharedWorkerServiceImpl::DestroyHost(SharedWorkerHost* host) {
@@ -210,9 +267,15 @@ void SharedWorkerServiceImpl::CreateWorker(
mojom::SharedWorkerClientPtr client,
int process_id,
int frame_id,
- const blink::MessagePortChannel& message_port) {
+ const blink::MessagePortChannel& message_port,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!blob_url_loader_factory || instance->url().SchemeIsBlob());
+
+ bool constructor_uses_file_url =
+ instance->constructor_origin().scheme() == url::kFileScheme;
+
// Create the host. We need to do this even before starting the worker,
// because we are about to bounce to the IO thread. If another ConnectToWorker
// request arrives in the meantime, it finds and reuses the host instead of
@@ -222,40 +285,37 @@ void SharedWorkerServiceImpl::CreateWorker(
auto weak_host = host->AsWeakPtr();
worker_hosts_.insert(std::move(host));
+ StoragePartitionImpl* storage_partition =
+ service_worker_context_->storage_partition();
// Bounce to the IO thread to setup service worker support in case the request
// for the worker script will need to be intercepted by service workers.
- if (ServiceWorkerUtils::IsServicificationEnabled()) {
- // Set up the factory bundle for non-NetworkService URLs, e.g.,
- // chrome-extension:// URLs.
- ContentBrowserClient::NonNetworkURLLoaderFactoryMap factories;
- GetContentClient()
- ->browser()
- ->RegisterNonNetworkSubresourceURLLoaderFactories(
- process_id, MSG_ROUTING_NONE, &factories);
-
- // TODO(falken): Add FileURLLoaderFactory if the requesting frame is a file
- // resource.
-
- auto factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
- for (auto& pair : factories) {
- const std::string& scheme = pair.first;
- std::unique_ptr<network::mojom::URLLoaderFactory> factory =
- std::move(pair.second);
-
- network::mojom::URLLoaderFactoryPtr factory_ptr;
- mojo::MakeStrongBinding(std::move(factory),
- mojo::MakeRequest(&factory_ptr));
- factory_bundle->factories_info().emplace(scheme,
- factory_ptr.PassInterface());
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ if (!storage_partition) {
+ // The context is shutting down. Just drop the request.
+ return;
}
+ // Set up the factory bundle for non-NetworkService URLs, e.g.,
+ // chrome-extension:// URLs. One factory bundle is consumed by the browser
+ // for SharedWorkerScriptLoaderFactory, and one is sent to the renderer.
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser =
+ CreateFactoryBundle(process_id, storage_partition,
+ constructor_uses_file_url);
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_renderer =
+ CreateFactoryBundle(process_id, storage_partition,
+ constructor_uses_file_url);
+
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&CreateScriptLoaderOnIO,
service_worker_context_->storage_partition()
->url_loader_factory_getter(),
- std::move(factory_bundle), service_worker_context_, process_id,
+ std::move(factory_bundle_for_browser),
+ std::move(factory_bundle_for_renderer), service_worker_context_,
+ blob_url_loader_factory ? blob_url_loader_factory->Clone()
+ : nullptr,
+ process_id,
base::BindOnce(&SharedWorkerServiceImpl::StartWorker,
weak_factory_.GetWeakPtr(), std::move(instance),
weak_host, std::move(client), process_id, frame_id,
@@ -264,7 +324,7 @@ void SharedWorkerServiceImpl::CreateWorker(
}
StartWorker(std::move(instance), weak_host, std::move(client), process_id,
- frame_id, message_port, nullptr, {});
+ frame_id, message_port, nullptr, {}, nullptr);
}
void SharedWorkerServiceImpl::StartWorker(
@@ -277,7 +337,8 @@ void SharedWorkerServiceImpl::StartWorker(
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_info) {
+ script_loader_factory_info,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// The host may already be gone if something forcibly terminated the worker
@@ -304,7 +365,7 @@ void SharedWorkerServiceImpl::StartWorker(
BindInterface(process_host, &factory);
host->Start(std::move(factory), std::move(service_worker_provider_info),
- std::move(script_loader_factory_info));
+ std::move(script_loader_factory_info), std::move(factory_bundle));
host->AddClient(std::move(client), process_id, frame_id, message_port);
}
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 b41bcc2d352..46810fa5d75 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.h
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.h
@@ -29,10 +29,13 @@ class MessagePortChannel;
namespace content {
class SharedWorkerInstance;
class SharedWorkerHost;
+class StoragePartition;
+// Created per StoragePartition.
class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
public:
- explicit SharedWorkerServiceImpl(
+ SharedWorkerServiceImpl(
+ StoragePartition* storage_partition,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
~SharedWorkerServiceImpl() override;
@@ -50,19 +53,24 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
mojom::SharedWorkerInfoPtr info,
mojom::SharedWorkerClientPtr client,
blink::mojom::SharedWorkerCreationContextType creation_context_type,
- const blink::MessagePortChannel& port);
+ const blink::MessagePortChannel& port,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
void DestroyHost(SharedWorkerHost* host);
+ StoragePartition* storage_partition() { return storage_partition_; }
+
private:
friend class SharedWorkerServiceImplTest;
friend class SharedWorkerHostTest;
- void CreateWorker(std::unique_ptr<SharedWorkerInstance> instance,
- mojom::SharedWorkerClientPtr client,
- int process_id,
- int frame_id,
- const blink::MessagePortChannel& message_port);
+ void CreateWorker(
+ std::unique_ptr<SharedWorkerInstance> instance,
+ mojom::SharedWorkerClientPtr client,
+ int process_id,
+ int frame_id,
+ const blink::MessagePortChannel& message_port,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
void StartWorker(std::unique_ptr<SharedWorkerInstance> instance,
base::WeakPtr<SharedWorkerHost> host,
mojom::SharedWorkerClientPtr client,
@@ -72,7 +80,8 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_info);
+ script_loader_factory_info,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle);
// Returns nullptr if there is no such host.
SharedWorkerHost* FindSharedWorkerHost(int process_id, int route_id);
@@ -83,6 +92,8 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
worker_hosts_;
base::OnceClosure terminate_all_workers_callback_;
+ // |storage_partition_| owns |this|.
+ StoragePartition* const storage_partition_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
base::WeakPtrFactory<SharedWorkerServiceImpl> weak_factory_;
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc b/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
index 2afa11622eb..cf56ef37546 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
@@ -114,7 +114,7 @@ void ConnectToSharedWorker(mojom::SharedWorkerConnectorPtr connector,
connector->Connect(std::move(info), std::move(client_proxy),
blink::mojom::SharedWorkerCreationContextType::kSecure,
- std::move(message_pipe.handle1));
+ std::move(message_pipe.handle1), nullptr);
}
} // namespace
diff --git a/chromium/content/browser/shared_worker/worker_browsertest.cc b/chromium/content/browser/shared_worker/worker_browsertest.cc
index 179376232af..9c7ffc1364b 100644
--- a/chromium/content/browser/shared_worker/worker_browsertest.cc
+++ b/chromium/content/browser/shared_worker/worker_browsertest.cc
@@ -4,12 +4,14 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
+#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/client_certificate_delegate.h"
@@ -22,6 +24,7 @@
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "net/base/escape.h"
+#include "net/base/filename_util.h"
#include "net/ssl/ssl_server_config.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
@@ -64,20 +67,32 @@ class WorkerTest : public ContentBrowserTest {
int select_certificate_count() const { return select_certificate_count_; }
+ GURL GetTestFileURL(const std::string& test_case) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ base::FilePath path;
+ EXPECT_TRUE(base::PathService::Get(content::DIR_TEST_DATA, &path));
+ path = path.AppendASCII("workers").AppendASCII(test_case);
+ return net::FilePathToFileURL(path);
+ }
+
GURL GetTestURL(const std::string& test_case, const std::string& query) {
std::string url_string = "/workers/" + test_case + "?" + query;
return embedded_test_server()->GetURL(url_string);
}
- void RunTest(Shell* window, const GURL& url) {
- const base::string16 expected_title = base::ASCIIToUTF16("OK");
- TitleWatcher title_watcher(window->web_contents(), expected_title);
+ void RunTest(Shell* window, const GURL& url, bool expect_failure = false) {
+ const base::string16 ok_title = base::ASCIIToUTF16("OK");
+ const base::string16 fail_title = base::ASCIIToUTF16("FAIL");
+ TitleWatcher title_watcher(window->web_contents(), ok_title);
+ title_watcher.AlsoWaitForTitle(fail_title);
NavigateToURL(window, url);
base::string16 final_title = title_watcher.WaitAndGetTitle();
- EXPECT_EQ(expected_title, final_title);
+ EXPECT_EQ(expect_failure ? fail_title : ok_title, final_title);
}
- void RunTest(const GURL& url) { RunTest(shell(), url); }
+ void RunTest(const GURL& url, bool expect_failure = false) {
+ RunTest(shell(), url, expect_failure);
+ }
static void QuitUIMessageLoop(base::Callback<void()> callback) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(callback));
@@ -103,6 +118,18 @@ IN_PROC_BROWSER_TEST_F(WorkerTest, SingleWorker) {
RunTest(GetTestURL("single_worker.html", std::string()));
}
+IN_PROC_BROWSER_TEST_F(WorkerTest, SingleWorkerFromFile) {
+ RunTest(GetTestFileURL("single_worker.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(WorkerTest, HttpPageCantCreateFileWorker) {
+ GURL url = GetTestURL(
+ "single_worker.html",
+ "workerUrl=" + net::EscapeQueryParamValue(
+ GetTestFileURL("worker_common.js").spec(), true));
+ RunTest(url, /*expect_failure=*/true);
+}
+
IN_PROC_BROWSER_TEST_F(WorkerTest, MultipleWorkers) {
RunTest(GetTestURL("multi_worker.html", std::string()));
}
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index b34db8034e1..bf59f2d42ca 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -85,6 +85,11 @@ bool SiteInstanceImpl::ShouldAssignSiteForURL(const GURL& url) {
return GetContentClient()->browser()->ShouldAssignSiteForURL(url);
}
+// static
+bool SiteInstanceImpl::IsOriginLockASite(const GURL& lock_url) {
+ return lock_url.has_scheme() && lock_url.has_host();
+}
+
int32_t SiteInstanceImpl::GetId() {
return id_;
}
@@ -444,10 +449,41 @@ GURL SiteInstance::GetSiteForURL(BrowserContext* browser_context,
// This is useful for cases like file URLs.
if (!origin.unique()) {
// Prefer to use the scheme of |origin| rather than |url|, to correctly
- // cover blob: and filesystem: URIs (see also https://crbug.com/697111).
+ // cover blob:file: and filesystem:file: URIs (see also
+ // https://crbug.com/697111).
DCHECK(!origin.scheme().empty());
return GURL(origin.scheme() + ":");
} else if (url.has_scheme()) {
+ // In some cases, it is not safe to use just the scheme as a site URL, as
+ // that might allow two URLs created by different sites to share a process.
+ // See https://crbug.com/863623 and https://crbug.com/863069.
+ //
+ // TODO(alexmos,creis): This should eventually be expanded to certain other
+ // schemes, such as file:.
+ // TODO(creis): This currently causes problems with tests on Android and
+ // Android WebView. For now, skip it when Site Isolation is not enabled,
+ // since there's no need to isolate data and blob URLs from each other in
+ // that case.
+ bool is_site_isolation_enabled =
+ SiteIsolationPolicy::UseDedicatedProcessesForAllSites() ||
+ SiteIsolationPolicy::AreIsolatedOriginsEnabled();
+ if (is_site_isolation_enabled &&
+ (url.SchemeIsBlob() || url.scheme() == url::kDataScheme)) {
+ // We get here for blob URLs of form blob:null/guid. Use the full URL
+ // with the guid in that case, which isolates all blob URLs with unique
+ // origins from each other. We also get here for browser-initiated
+ // navigations to data URLs, which have a unique origin and should only
+ // share a process when they are identical. Remove hash from the URL in
+ // either case, since same-document navigations shouldn't use a different
+ // site URL.
+ if (url.has_ref()) {
+ GURL::Replacements replacements;
+ replacements.ClearRef();
+ url = url.ReplaceComponents(replacements);
+ }
+ return url;
+ }
+
DCHECK(!url.scheme().empty());
return GURL(url.scheme() + ":");
}
@@ -544,13 +580,6 @@ void SiteInstanceImpl::RenderProcessHostDestroyed(RenderProcessHost* host) {
process_ = nullptr;
}
-void SiteInstanceImpl::RenderProcessWillExit(RenderProcessHost* host) {
- // TODO(nick): http://crbug.com/575400 - RenderProcessWillExit might not serve
- // any purpose here.
- for (auto& observer : observers_)
- observer.RenderProcessGone(this);
-}
-
void SiteInstanceImpl::RenderProcessExited(
RenderProcessHost* host,
const ChildProcessTerminationInfo& info) {
@@ -587,7 +616,7 @@ void SiteInstanceImpl::LockToOriginIfNeeded() {
// strong protection. If only some sites are isolated, we need
// additional logic to prevent the non-isolated sites from requesting
// resources for isolated sites. https://crbug.com/509125
- policy->LockToOrigin(process_->GetID(), site_);
+ process_->LockToOrigin(site_);
break;
}
case CheckOriginLockResult::HAS_WRONG_LOCK:
diff --git a/chromium/content/browser/site_instance_impl.h b/chromium/content/browser/site_instance_impl.h
index 4e96a2383e2..f2fa8e198bd 100644
--- a/chromium/content/browser/site_instance_impl.h
+++ b/chromium/content/browser/site_instance_impl.h
@@ -39,6 +39,12 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
const GURL& url);
static bool ShouldAssignSiteForURL(const GURL& url);
+ // Returns whether |lock_url| is at least at the granularity of a site (i.e.,
+ // a scheme plus eTLD+1, like https://google.com). Also returns true if the
+ // lock is to a more specific origin (e.g., https://accounts.google.com), but
+ // not if the lock is empty or applies to an entire scheme (e.g., file://).
+ static bool IsOriginLockASite(const GURL& lock_url);
+
// See SiteInstance::IsSameWebSite.
// This version allows comparing URLs without converting them to effective
// URLs first, which is useful for avoiding OOPIFs when otherwise same-site
@@ -223,7 +229,6 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// RenderProcessHostObserver implementation.
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
- void RenderProcessWillExit(RenderProcessHost* host) override;
void RenderProcessExited(RenderProcessHost* host,
const ChildProcessTerminationInfo& info) override;
diff --git a/chromium/content/browser/site_instance_impl_unittest.cc b/chromium/content/browser/site_instance_impl_unittest.cc
index effcb936cb2..66159134d65 100644
--- a/chromium/content/browser/site_instance_impl_unittest.cc
+++ b/chromium/content/browser/site_instance_impl_unittest.cc
@@ -25,6 +25,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/webui/content_web_ui_controller_factory.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
+#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_features.h"
@@ -42,6 +43,13 @@
#include "url/url_util.h"
namespace content {
+namespace {
+
+GURL GetWebUIURL(std::string host) {
+ return GURL(std::string(kChromeUIScheme) + "://" + host);
+}
+
+} // namespace
const char kPrivilegedScheme[] = "privileged";
@@ -212,41 +220,6 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
// contents is now deleted, along with instance and browsing_instance
}
-// Test that NavigationEntries with SiteInstances can be cloned, but that their
-// SiteInstances can be changed afterwards. Also tests that the ref counts are
-// updated properly after the change.
-TEST_F(SiteInstanceTest, CloneNavigationEntry) {
- const GURL url("test:foo");
-
- std::unique_ptr<NavigationEntryImpl> e1 =
- base::WrapUnique(new NavigationEntryImpl(
- SiteInstanceImpl::Create(nullptr), url, Referrer(), base::string16(),
- ui::PAGE_TRANSITION_LINK, false,
- nullptr /* blob_url_loader_factory */));
-
- // Clone the entry.
- std::unique_ptr<NavigationEntryImpl> e2 = e1->Clone();
-
- // Should be able to change the SiteInstance of the cloned entry.
- e2->set_site_instance(SiteInstanceImpl::Create(nullptr));
-
- EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
- EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-
- // The first SiteInstance and BrowsingInstance should go away after resetting
- // e1, since e2 should no longer be referencing it.
- e1.reset();
- 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, browser_client()->GetAndClearSiteInstanceDeleteCount());
- EXPECT_EQ(1, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-
- DrainMessageLoop();
-}
-
// Test to ensure GetProcess returns and creates processes correctly.
TEST_F(SiteInstanceTest, GetProcess) {
// Ensure that GetProcess returns a process.
@@ -343,12 +316,25 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
EXPECT_EQ("file", site_url.scheme());
EXPECT_FALSE(site_url.has_host());
- // Data URLs should include the scheme.
+ // Data URLs should include the whole URL, except for the hash, when Site
+ // Isolation is enabled. Otherwise they just include the scheme.
test_url = GURL("data:text/html,foo");
site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
- EXPECT_EQ(GURL("data:"), site_url);
+ if (AreAllSitesIsolatedForTesting())
+ EXPECT_EQ(test_url, site_url);
+ else
+ EXPECT_EQ(GURL("data:"), site_url);
EXPECT_EQ("data", site_url.scheme());
EXPECT_FALSE(site_url.has_host());
+ test_url = GURL("data:text/html,foo#bar");
+ site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ EXPECT_FALSE(site_url.has_ref());
+ if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_NE(test_url, site_url);
+ EXPECT_TRUE(site_url.EqualsIgnoringRef(test_url));
+ } else {
+ EXPECT_EQ(GURL("data:"), site_url);
+ }
// Javascript URLs should include the scheme.
test_url = GURL("javascript:foo();");
@@ -371,6 +357,25 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
EXPECT_EQ("file", site_url.scheme());
EXPECT_FALSE(site_url.has_host());
+ // Blob URLs created from a unique origin use the full URL as the site URL
+ // when Site Isolation is enabled, except for the hash. Otherwise they just
+ // include the scheme.
+ test_url = GURL("blob:null/1029e5a4-2983-4b90-a585-ed217563acfeb");
+ site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ if (AreAllSitesIsolatedForTesting())
+ EXPECT_EQ(test_url, site_url);
+ else
+ EXPECT_EQ(GURL("blob:"), site_url);
+ test_url = GURL("blob:null/1029e5a4-2983-4b90-a585-ed217563acfeb#foo");
+ site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
+ EXPECT_FALSE(site_url.has_ref());
+ if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_NE(test_url, site_url);
+ EXPECT_TRUE(site_url.EqualsIgnoringRef(test_url));
+ } else {
+ EXPECT_EQ(GURL("blob:"), site_url);
+ }
+
// Private domains are preserved, appspot being such a site.
test_url = GURL(
"blob:http://www.example.appspot.com:44/"
@@ -621,6 +626,7 @@ static scoped_refptr<SiteInstanceImpl> CreateSiteInstance(
// Test to ensure that pages that require certain privileges are grouped
// in processes with similar pages.
+// TODO(nasko): Remove. See https://crbug.com/847127.
TEST_F(SiteInstanceTest, ProcessSharingByType) {
// This test shouldn't run with --site-per-process mode, which prohibits
// the renderer process reuse this test explicitly exercises.
@@ -660,13 +666,13 @@ TEST_F(SiteInstanceTest, ProcessSharingByType) {
extension2_instance->GetProcess());
// Create some WebUI instances and make sure they share a process.
- scoped_refptr<SiteInstanceImpl> webui1_instance(CreateSiteInstance(
- browser_context.get(), GURL(kChromeUIScheme + std::string("://gpu"))));
- policy->GrantWebUIBindings(webui1_instance->GetProcess()->GetID());
+ scoped_refptr<SiteInstanceImpl> webui1_instance(
+ CreateSiteInstance(browser_context.get(), GetWebUIURL(kChromeUIGpuHost)));
+ policy->GrantWebUIBindings(webui1_instance->GetProcess()->GetID(),
+ BINDINGS_POLICY_WEB_UI);
scoped_refptr<SiteInstanceImpl> webui2_instance(CreateSiteInstance(
- browser_context.get(),
- GURL(kChromeUIScheme + std::string("://media-internals"))));
+ browser_context.get(), GetWebUIURL(kChromeUIMediaInternalsHost)));
std::unique_ptr<RenderProcessHost> dom_host(webui1_instance->GetProcess());
EXPECT_EQ(webui1_instance->GetProcess(), webui2_instance->GetProcess());
@@ -724,7 +730,7 @@ TEST_F(SiteInstanceTest, HasWrongProcessForURL) {
// Simulate granting WebUI bindings for the process.
ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
- webui_host->GetID());
+ webui_host->GetID(), BINDINGS_POLICY_WEB_UI);
EXPECT_TRUE(webui_instance->HasProcess());
EXPECT_FALSE(webui_instance->HasWrongProcessForURL(webui_url));
@@ -1024,7 +1030,7 @@ TEST_F(SiteInstanceTest, IsValidIsolatedOrigin) {
// Scheme must be HTTP or HTTPS.
EXPECT_FALSE(IsolatedOriginUtil::IsValidIsolatedOrigin(
- url::Origin::Create(GURL(kChromeUIScheme + std::string("://gpu")))));
+ url::Origin::Create(GetWebUIURL(kChromeUIGpuHost))));
EXPECT_TRUE(IsolatedOriginUtil::IsValidIsolatedOrigin(
url::Origin::Create(GURL("http://a.com"))));
EXPECT_TRUE(IsolatedOriginUtil::IsValidIsolatedOrigin(
@@ -1233,4 +1239,17 @@ TEST_F(SiteInstanceTest, OriginalURL) {
SetBrowserClientForTesting(regular_client);
}
+TEST_F(SiteInstanceTest, IsOriginLockASite) {
+ EXPECT_FALSE(SiteInstanceImpl::IsOriginLockASite(GURL("http://")));
+ EXPECT_FALSE(SiteInstanceImpl::IsOriginLockASite(GURL("")));
+ EXPECT_FALSE(SiteInstanceImpl::IsOriginLockASite(GURL("google.com")));
+ EXPECT_FALSE(SiteInstanceImpl::IsOriginLockASite(GURL("http:")));
+ EXPECT_FALSE(SiteInstanceImpl::IsOriginLockASite(GURL("chrome:")));
+
+ EXPECT_TRUE(SiteInstanceImpl::IsOriginLockASite(GURL("http://foo.com")));
+ EXPECT_TRUE(SiteInstanceImpl::IsOriginLockASite(GURL("http://bar.foo.com")));
+ EXPECT_TRUE(SiteInstanceImpl::IsOriginLockASite(
+ GURL("http://user:pass@google.com:99/foo;bar?q=a#ref")));
+}
+
} // namespace content
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index 569aa71cfe3..69281841aca 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -33,7 +33,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/test_timeouts.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -79,6 +79,7 @@
#include "content/public/common/use_zoom_for_dsf_policy.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
@@ -231,16 +232,6 @@ double GetFrameDeviceScaleFactor(const ToRenderFrameHost& adapter) {
return device_scale_factor;
}
-// This helper accounts for Android devices which use page scale factor
-// different from 1.0. Coordinate targeting needs to be adjusted before
-// hit testing.
-double GetPageScaleFactor(Shell* shell) {
- return RenderWidgetHostImpl::From(
- shell->web_contents()->GetRenderViewHost()->GetWidget())
- ->last_frame_metadata()
- .page_scale_factor;
-}
-
class RedirectNotificationObserver : public NotificationObserver {
public:
// Register to listen for notifications of the given type from either a
@@ -539,6 +530,16 @@ void CheckFrameDepth(unsigned int expected_depth, FrameTreeNode* node) {
node->current_frame_host()->GetProcess()->GetFrameDepth());
}
+void GenerateTapDownGesture(RenderWidgetHost* rwh) {
+ blink::WebGestureEvent gesture_tap_down(
+ blink::WebGestureEvent::kGestureTapDown,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests(),
+ blink::kWebGestureDeviceTouchscreen);
+ gesture_tap_down.is_source_touch_event_set_non_blocking = true;
+ rwh->ForwardGestureEvent(gesture_tap_down);
+}
+
} // namespace
//
@@ -1062,7 +1063,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
->GetRenderWidgetHost()
->GetView());
- WaitForChildFrameSurfaceReady(nested_iframe_node->current_frame_host());
+ RenderFrameSubmissionObserver frame_observer(nested_iframe_node);
+ frame_observer.WaitForMetadataChange();
// Verify that applying a CSS scale transform does not impact the size of the
// content of the nested iframe.
@@ -1117,6 +1119,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ViewBoundsInNestedFrameTest) {
GURL site_url(embedded_test_server()->GetURL(
"a.com", "/frame_tree/page_with_positioned_frame.html"));
NavigateFrameToURL(parent_iframe_node, site_url);
+ RenderFrameSubmissionObserver frame_observer(shell()->web_contents());
EXPECT_EQ(
" Site A ------------ proxies for B\n"
@@ -1132,9 +1135,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ViewBoundsInNestedFrameTest) {
nested_iframe_node->current_frame_host()
->GetRenderWidgetHost()
->GetView());
- WaitForChildFrameSurfaceReady(nested_iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(
+ nested_iframe_node->current_frame_host());
- float scale_factor = GetPageScaleFactor(shell());
+ float scale_factor =
+ frame_observer.LastRenderFrameMetadata().page_scale_factor;
// Get the view bounds of the nested iframe, which should account for the
// relative offset of its direct parent within the root frame.
@@ -1159,7 +1164,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ViewBoundsInNestedFrameTest) {
scroll_event.delta_y = -30.0f;
scroll_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
rwhv_root->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
-
filter->WaitForRect();
// The precise amount of scroll for the first view position update is not
@@ -1182,26 +1186,23 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
->GetFrameTree()
->root();
ASSERT_EQ(1U, root->child_count());
- RenderWidgetHost* root_rwh =
- root->current_frame_host()->GetRenderWidgetHost();
FrameTreeNode* child_iframe_node = root->child_at(0);
RenderWidgetHost* child_rwh =
child_iframe_node->current_frame_host()->GetRenderWidgetHost();
- RenderWidgetHostViewBase* child_rwhv =
- static_cast<RenderWidgetHostViewBase*>(child_rwh->GetView());
-
- // If wheel scroll latching is enabled, the fling start won't bubble since
- // its corresponding GSB hasn't bubbled.
+ // The fling start won't bubble since its corresponding GSB hasn't bubbled.
InputEventAckWaiter gesture_fling_start_ack_observer(
- (child_rwhv->wheel_scroll_latching_enabled() ? child_rwh : root_rwh),
- blink::WebInputEvent::kGestureFlingStart);
+ child_rwh, blink::WebInputEvent::kGestureFlingStart);
- WaitForChildFrameSurfaceReady(child_iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(
+ child_iframe_node->current_frame_host());
gesture_fling_start_ack_observer.Reset();
+
+ GenerateTapDownGesture(child_rwh);
+
// Send a GSB, GSU, GFS sequence and verify that the GFS bubbles.
blink::WebGestureEvent gesture_scroll_begin(
blink::WebGestureEvent::kGestureScrollBegin,
@@ -1305,7 +1306,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScrollBubblingFromOOPIFTest) {
->GetRenderWidgetHost()
->GetView());
- WaitForChildFrameSurfaceReady(nested_iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(
+ nested_iframe_node->current_frame_host());
// Save the original offset as a point of reference.
filter->WaitForRect();
@@ -1327,17 +1329,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScrollBubblingFromOOPIFTest) {
scroll_event.has_precise_scrolling_deltas = true;
rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- if (rwhv_parent->wheel_scroll_latching_enabled()) {
- // When scroll latching is enabled the event router sends wheel events of a
- // single scroll sequence to the target under the first wheel event. Send a
- // wheel end event to the current target view before sending a wheel event
- // to a different one.
- scroll_event.delta_y = 0.0f;
- scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
- scroll_event.dispatch_type =
- blink::WebInputEvent::DispatchType::kEventNonBlocking;
- rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- }
+ // The event router sends wheel events of a single scroll sequence to the
+ // target under the first wheel event. Send a wheel end event to the current
+ // target view before sending a wheel event to a different one.
+ scroll_event.delta_y = 0.0f;
+ scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ scroll_event.dispatch_type =
+ blink::WebInputEvent::DispatchType::kEventNonBlocking;
+ rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
// Ensure that the view position is propagated to the child properly.
filter->WaitForRect();
@@ -1370,17 +1369,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScrollBubblingFromOOPIFTest) {
update_rect = filter->last_rect();
}
- if (rwhv_parent->wheel_scroll_latching_enabled()) {
- // When scroll latching is enabled the event router sends wheel events of a
- // single scroll sequence to the target under the first wheel event. Send a
- // wheel end event to the current target view before sending a wheel event
- // to a different one.
- scroll_event.delta_y = 0.0f;
- scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
- scroll_event.dispatch_type =
- blink::WebInputEvent::DispatchType::kEventNonBlocking;
- rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- }
+ // The event router sends wheel events of a single scroll sequence to the
+ // target under the first wheel event. Send a wheel end event to the current
+ // target view before sending a wheel event to a different one.
+ scroll_event.delta_y = 0.0f;
+ scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ scroll_event.dispatch_type =
+ blink::WebInputEvent::DispatchType::kEventNonBlocking;
+ rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
filter->ResetRectRunLoop();
// Once we've sent a wheel to the nested iframe that we expect to turn into
@@ -1399,17 +1395,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScrollBubblingFromOOPIFTest) {
scroll_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- if (rwhv_parent->wheel_scroll_latching_enabled()) {
- // When scroll latching is enabled the event router sends wheel events of a
- // single scroll sequence to the target under the first wheel event. Send a
- // wheel end event to the current target view before sending a wheel event
- // to a different one.
- scroll_event.delta_y = 0.0f;
- scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
- scroll_event.dispatch_type =
- blink::WebInputEvent::DispatchType::kEventNonBlocking;
- rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- }
+ // The event router sends wheel events of a single scroll sequence to the
+ // target under the first wheel event. Send a wheel end event to the current
+ // target view before sending a wheel event to a different one.
+ scroll_event.delta_y = 0.0f;
+ scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ scroll_event.dispatch_type =
+ blink::WebInputEvent::DispatchType::kEventNonBlocking;
+ rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
// Ensure ensuing offset change is received, and then reset the filter.
filter->WaitForRect();
@@ -1561,9 +1554,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
RenderWidgetHost* child_rwh =
child_iframe_node->current_frame_host()->GetRenderWidgetHost();
+ WaitForHitTestDataOrChildSurfaceReady(
+ child_iframe_node->current_frame_host());
- WaitForChildFrameSurfaceReady(child_iframe_node->current_frame_host());
-
+ GenerateTapDownGesture(child_rwh);
// Send a GSB to start scrolling sequence.
blink::WebGestureEvent gesture_scroll_begin(
blink::WebGestureEvent::kGestureScrollBegin,
@@ -1688,6 +1682,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_nested_frames.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameSubmissionObserver frame_observer(shell()->web_contents());
// It is safe to obtain the root frame tree node here, as it doesn't change.
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
@@ -1712,22 +1707,19 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
->GetRenderWidgetHost()
->GetView());
- WaitForChildFrameSurfaceReady(nested_iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(
+ nested_iframe_node->current_frame_host());
InputEventAckWaiter ack_observer(
root->current_frame_host()->GetRenderWidgetHost(),
blink::WebInputEvent::kGestureScrollBegin);
std::unique_ptr<ScrollObserver> scroll_observer;
- if (root_view->wheel_scroll_latching_enabled()) {
- // All GSU events will be wrapped between a single GSB-GSE pair. The
- // expected delta value is equal to summation of all scroll update deltas.
- scroll_observer = std::make_unique<ScrollObserver>(0, 15);
- } else {
- // Each GSU will be wrapped betweeen its own GSB-GSE pair. The expected
- // delta value is the delta of the first GSU event.
- scroll_observer = std::make_unique<ScrollObserver>(0, 5);
- }
+
+ // All GSU events will be wrapped between a single GSB-GSE pair. The expected
+ // delta value is equal to summation of all scroll update deltas.
+ scroll_observer = std::make_unique<ScrollObserver>(0, 15);
+
root->current_frame_host()->GetRenderWidgetHost()->AddInputEventObserver(
scroll_observer.get());
@@ -1737,7 +1729,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
blink::WebInputEvent::kMouseWheel, blink::WebInputEvent::kNoModifiers,
blink::WebInputEvent::GetStaticTimeStampForTests());
gfx::Rect bounds = rwhv_nested->GetViewBounds();
- float scale_factor = GetPageScaleFactor(shell());
+ float scale_factor =
+ frame_observer.LastRenderFrameMetadata().page_scale_factor;
scroll_event.SetPositionInWidget(
gfx::ToCeiledInt((bounds.x() - root_view->GetViewBounds().x() + 10) *
scale_factor),
@@ -1750,35 +1743,22 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
ack_observer.Wait();
- // When wheel scroll latching is disabled, each wheel event will have its own
- // complete scroll seqeunce.
- if (!root_view->wheel_scroll_latching_enabled())
- scroll_observer->Wait();
-
- // Send 10 wheel events with delta_y = 1 to the nested oopif. When scroll
- // latching is disabled, each wheel event will have its own scroll sequence.
+ // Send 10 wheel events with delta_y = 1 to the nested oopif.
scroll_event.delta_y = 1.0f;
scroll_event.phase = blink::WebMouseWheelEvent::kPhaseChanged;
- for (int i = 0; i < 10; i++) {
- if (!root_view->wheel_scroll_latching_enabled())
- scroll_observer->Reset(0, 1);
+ for (int i = 0; i < 10; i++)
rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- if (!root_view->wheel_scroll_latching_enabled())
- scroll_observer->Wait();
- }
- // Send a wheel end event to complete the scrolling sequence when wheel scroll
- // latching is enabled.
- if (root_view->wheel_scroll_latching_enabled()) {
- scroll_event.delta_y = 0.0f;
- scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
- rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- scroll_observer->Wait();
- }
+ // Send a wheel end event to complete the scrolling sequence.
+ scroll_event.delta_y = 0.0f;
+ scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
+ scroll_observer->Wait();
}
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(OS_MACOSX)
// Flaky: https://crbug.com/836200.
+// Flaky timeouts on Mac: https://crbug.com/863971.
#define MAYBE_ScrollBubblingFromOOPIFWithBodyOverflowHidden \
DISABLED_ScrollBubblingFromOOPIFWithBodyOverflowHidden
#else
@@ -1792,13 +1772,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
GURL url_domain_a(embedded_test_server()->GetURL(
"a.com", "/scrollable_page_with_iframe.html"));
EXPECT_TRUE(NavigateToURL(shell(), url_domain_a));
+ RenderFrameSubmissionObserver frame_observer(shell()->web_contents());
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
FrameTreeNode* iframe_node = root->child_at(0);
GURL url_domain_b(
embedded_test_server()->GetURL("b.com", "/body_overflow_hidden.html"));
NavigateFrameToURL(iframe_node, url_domain_b);
- WaitForChildFrameSurfaceReady(iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(iframe_node->current_frame_host());
RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
root->current_frame_host()->GetRenderWidgetHost()->GetView());
@@ -1816,7 +1797,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
blink::WebInputEvent::kMouseWheel, blink::WebInputEvent::kNoModifiers,
blink::WebInputEvent::GetStaticTimeStampForTests());
gfx::Rect bounds = child_view->GetViewBounds();
- float scale_factor = GetPageScaleFactor(shell());
+ float scale_factor =
+ frame_observer.LastRenderFrameMetadata().page_scale_factor;
scroll_event.SetPositionInWidget(
gfx::ToCeiledInt((bounds.x() - root_view->GetViewBounds().x() + 10) *
scale_factor),
@@ -1828,13 +1810,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
scroll_event.has_precise_scrolling_deltas = true;
child_view->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- // Send a wheel end event to complete the scrolling sequence when wheel scroll
- // latching is enabled.
- if (root_view->wheel_scroll_latching_enabled()) {
- scroll_event.delta_y = 0.0f;
- scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
- child_view->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- }
+ // Send a wheel end event to complete the scrolling sequence.
+ scroll_event.delta_y = 0.0f;
+ scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ child_view->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
scroll_observer.Wait();
}
@@ -1878,7 +1857,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScrollLocalSubframeInOOPIF) {
->GetRenderWidgetHost()
->GetView());
- WaitForChildFrameSurfaceReady(parent_iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(
+ parent_iframe_node->current_frame_host());
// When we scroll the inner frame, we should have the GSB be consumed.
// The outer iframe not being scrollable should not cause the GSB to go
@@ -2207,19 +2187,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CompositorFrameSwapped) {
EXPECT_EQ(site_url, child_node->current_url());
EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
child_node->current_frame_host()->GetSiteInstance());
- RenderWidgetHostViewBase* rwhv_base = static_cast<RenderWidgetHostViewBase*>(
- child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
-
- // Wait for OnSwapCompositorFrame message.
- while (rwhv_base->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();
- }
+ // Wait for CompositorFrame submission.
+ RenderFrameSubmissionObserver observer(
+ child_node->current_frame_host()
+ ->GetRenderWidgetHost()
+ ->render_frame_metadata_provider());
+ observer.WaitForAnyFrameSubmission();
}
// Ensure that OOPIFs are deleted after navigating to a new main frame.
@@ -5530,8 +5503,15 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// navigation is initiated before the first page receives the SwapOut ACK.
// Ensure that this doesn't crash and that the RVH(A) is not reused in that
// case.
+#if defined(OS_MACOSX)
+#define MAYBE_RenderViewHostIsNotReusedAfterDelayedSwapOutACK \
+ DISABLED_RenderViewHostIsNotReusedAfterDelayedSwapOutACK
+#else
+#define MAYBE_RenderViewHostIsNotReusedAfterDelayedSwapOutACK \
+ RenderViewHostIsNotReusedAfterDelayedSwapOutACK
+#endif
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
- RenderViewHostIsNotReusedAfterDelayedSwapOutACK) {
+ MAYBE_RenderViewHostIsNotReusedAfterDelayedSwapOutACK) {
GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
EXPECT_TRUE(NavigateToURL(shell(), a_url));
@@ -6343,54 +6323,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CSSVisibilityChanged) {
}
}
-// A class which counts the number of times a RenderWidgetHostViewChildFrame
-// swaps compositor frames.
-class ChildFrameCompositorFrameSwapCounter {
- public:
- explicit ChildFrameCompositorFrameSwapCounter(
- RenderWidgetHostViewChildFrame* view)
- : view_(view), weak_factory_(this) {
- RegisterCallback();
- }
-
- ~ChildFrameCompositorFrameSwapCounter() {}
-
- // Wait until at least |count| new frames are swapped.
- void WaitForNewFrames(size_t count) {
- while (counter_ < count) {
- base::RunLoop loop;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, loop.QuitClosure(), TestTimeouts::tiny_timeout());
- loop.Run();
- }
- }
-
- void ResetCounter() { counter_ = 0; }
- size_t GetCount() const { return counter_; }
-
- private:
- void RegisterCallback() {
- view_->RegisterFrameSwappedCallback(
- base::BindOnce(&ChildFrameCompositorFrameSwapCounter::OnFrameSwapped,
- weak_factory_.GetWeakPtr()));
- }
-
- void OnFrameSwapped() {
- counter_++;
-
- // Register a new callback as the old one is released now.
- RegisterCallback();
- }
-
- size_t counter_ = 0;
-
- private:
- RenderWidgetHostViewChildFrame* view_;
- base::WeakPtrFactory<ChildFrameCompositorFrameSwapCounter> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ChildFrameCompositorFrameSwapCounter);
-};
-
// This test verifies that hiding an OOPIF in CSS will stop generating
// compositor frames for the OOPIF and any nested OOPIFs inside it. This holds
// even when the whole page is shown.
@@ -6439,24 +6371,28 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
static_cast<RenderWidgetHostViewChildFrame*>(
root->child_at(0)->child_at(0)->current_frame_host()->GetView());
- ChildFrameCompositorFrameSwapCounter first_counter(first_child_view);
- ChildFrameCompositorFrameSwapCounter second_counter(second_child_view);
- ChildFrameCompositorFrameSwapCounter third_counter(nested_child_view);
+ RenderFrameSubmissionObserver first_frame_counter(
+ first_child_view->host_->render_frame_metadata_provider());
+ RenderFrameSubmissionObserver second_frame_counter(
+ second_child_view->host_->render_frame_metadata_provider());
+ RenderFrameSubmissionObserver third_frame_counter(
+ nested_child_view->host_->render_frame_metadata_provider());
- const size_t kFrameCountLimit = 20u;
+ const int kFrameCountLimit = 20;
// Wait for a minimum number of compositor frames for the second frame.
- second_counter.WaitForNewFrames(kFrameCountLimit);
- ASSERT_LE(kFrameCountLimit, second_counter.GetCount());
+ while (second_frame_counter.render_frame_count() < kFrameCountLimit)
+ second_frame_counter.WaitForAnyFrameSubmission();
+ ASSERT_LE(kFrameCountLimit, second_frame_counter.render_frame_count());
// Now make sure all frames have roughly the counter value in the sense that
// no counter value is more than twice any other.
- float ratio = static_cast<float>(first_counter.GetCount()) /
- static_cast<float>(second_counter.GetCount());
+ float ratio = static_cast<float>(first_frame_counter.render_frame_count()) /
+ static_cast<float>(second_frame_counter.render_frame_count());
EXPECT_GT(2.5f, ratio + 1 / ratio) << "Ratio is: " << ratio;
- ratio = static_cast<float>(first_counter.GetCount()) /
- static_cast<float>(third_counter.GetCount());
+ ratio = static_cast<float>(first_frame_counter.render_frame_count()) /
+ static_cast<float>(third_frame_counter.render_frame_count());
EXPECT_GT(2.5f, ratio + 1 / ratio) << "Ratio is: " << ratio;
// Make sure all views can become visible.
@@ -6485,21 +6421,22 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
shell()->web_contents()->WasHidden();
shell()->web_contents()->WasShown();
- first_counter.ResetCounter();
- second_counter.ResetCounter();
- third_counter.ResetCounter();
+ first_frame_counter.ResetCounter();
+ second_frame_counter.ResetCounter();
+ third_frame_counter.ResetCounter();
// We expect the second counter to keep running.
- second_counter.WaitForNewFrames(kFrameCountLimit);
- ASSERT_LT(kFrameCountLimit, second_counter.GetCount() + 1u);
+ while (second_frame_counter.render_frame_count() < kFrameCountLimit)
+ second_frame_counter.WaitForAnyFrameSubmission();
+ ASSERT_LT(kFrameCountLimit, second_frame_counter.render_frame_count() + 1);
// Verify that the counter for other two frames did not count much.
- ratio = static_cast<float>(first_counter.GetCount()) /
- static_cast<float>(second_counter.GetCount());
+ ratio = static_cast<float>(first_frame_counter.render_frame_count()) /
+ static_cast<float>(second_frame_counter.render_frame_count());
EXPECT_GT(0.5f, ratio) << "Ratio is: " << ratio;
- ratio = static_cast<float>(third_counter.GetCount()) /
- static_cast<float>(second_counter.GetCount());
+ ratio = static_cast<float>(third_frame_counter.render_frame_count()) /
+ static_cast<float>(second_frame_counter.render_frame_count());
EXPECT_GT(0.5f, ratio) << "Ratio is: " << ratio;
}
@@ -6555,19 +6492,22 @@ IN_PROC_BROWSER_TEST_F(
EXPECT_FALSE(first_child_view->CanBecomeVisible());
- ChildFrameCompositorFrameSwapCounter first_counter(first_child_view);
- ChildFrameCompositorFrameSwapCounter second_counter(second_child_view);
+ RenderFrameSubmissionObserver first_frame_counter(
+ first_child_view->host_->render_frame_metadata_provider());
+ RenderFrameSubmissionObserver second_frame_counter(
+ second_child_view->host_->render_frame_metadata_provider());
- const size_t kFrameCountLimit = 20u;
+ const int kFrameCountLimit = 20;
// Wait for a certain number of swapped compositor frames generated for the
// second child view. During the same interval the first frame should not have
// swapped any compositor frames.
- second_counter.WaitForNewFrames(kFrameCountLimit);
- ASSERT_LT(kFrameCountLimit, second_counter.GetCount() + 1u);
+ while (second_frame_counter.render_frame_count() < kFrameCountLimit)
+ second_frame_counter.WaitForAnyFrameSubmission();
+ ASSERT_LT(kFrameCountLimit, second_frame_counter.render_frame_count() + 1);
- float ratio = static_cast<float>(first_counter.GetCount()) /
- static_cast<float>(second_counter.GetCount());
+ float ratio = static_cast<float>(first_frame_counter.render_frame_count()) /
+ static_cast<float>(second_frame_counter.render_frame_count());
EXPECT_GT(0.5f, ratio) << "Ratio is: " << ratio;
}
@@ -7397,20 +7337,25 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_FALSE(rvh->is_swapped_out_);
}
-// Helper class to wait for a ShutdownRequest message to arrive, in response to
-// which RenderProcessWillExit is called on observers by RenderProcessHost.
+// Helper class to wait for a ShutdownRequest message to arrive.
class ShutdownObserver : public RenderProcessHostObserver {
public:
ShutdownObserver() : message_loop_runner_(new MessageLoopRunner) {}
void RenderProcessShutdownRequested(RenderProcessHost* host) override {
+ has_received_shutdown_request_ = true;
message_loop_runner_->Quit();
}
void Wait() { message_loop_runner_->Run(); }
+ bool has_received_shutdown_request() {
+ return has_received_shutdown_request_;
+ }
+
private:
scoped_refptr<MessageLoopRunner> message_loop_runner_;
+ bool has_received_shutdown_request_ = false;
DISALLOW_COPY_AND_ASSIGN(ShutdownObserver);
};
@@ -7500,8 +7445,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
// Ensures that navigating to data: URLs present in session history will
-// correctly commit the navigation in the same process as the parent frame.
-// See https://crbug.com/606996.
+// correctly commit the navigation in the same process as the one used for the
+// original navigation. See https://crbug.com/606996.
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
NavigateSubframeToDataUrlInSessionHistory) {
GURL main_url(embedded_test_server()->GetURL(
@@ -7527,7 +7472,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_TRUE(observer.last_navigation_succeeded());
EXPECT_EQ(data_url, observer.last_navigation_url());
scoped_refptr<SiteInstanceImpl> orig_site_instance =
- child->current_frame_host()->GetSiteInstance();
+ child->current_frame_host()->GetSiteInstance();
EXPECT_NE(root->current_frame_host()->GetSiteInstance(), orig_site_instance);
// Navigate it to another cross-site url.
@@ -7547,6 +7492,286 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(orig_site_instance, child->current_frame_host()->GetSiteInstance());
}
+// Ensures that subframes navigated to data: URLs start in a process based on
+// their creator, but end up in unique processes after a restore (since
+// SiteInstance relationships are not preserved on restore, until
+// https://crbug.com/14987 is fixed). This is better than restoring into the
+// parent process, per https://crbug.com/863069.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ SubframeDataUrlsAfterRestore) {
+ // We must use a page that has iframes in the HTML here, unlike
+ // cross_site_iframe_factory.html which loads them dynamically. In the latter
+ // case, Chrome will not restore subframe URLs from history, which is needed
+ // for this test.
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/frame_tree/page_with_two_iframes.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ EXPECT_EQ(2U, root->child_count());
+ EXPECT_EQ(
+ " Site A ------------ proxies for B C\n"
+ " |--Site B ------- proxies for A C\n"
+ " +--Site C ------- proxies for A B\n"
+ "Where A = http://a.com/\n"
+ " B = http://bar.com/\n"
+ " C = http://baz.com/",
+ DepictFrameTree(root));
+
+ FrameTreeNode* child_0 = root->child_at(0);
+ FrameTreeNode* child_1 = root->child_at(1);
+ scoped_refptr<SiteInstanceImpl> child_site_instance_0 =
+ child_0->current_frame_host()->GetSiteInstance();
+ scoped_refptr<SiteInstanceImpl> child_site_instance_1 =
+ child_1->current_frame_host()->GetSiteInstance();
+
+ // Navigate the iframes to data URLs via renderer initiated navigations, which
+ // will commit in the existing SiteInstances.
+ TestNavigationObserver observer(shell()->web_contents());
+ GURL data_url_0("data:text/html,dataurl_0");
+ {
+ TestFrameNavigationObserver commit_observer(child_0);
+ EXPECT_TRUE(
+ ExecuteScript(child_0, "location.href = '" + data_url_0.spec() + "';"));
+ commit_observer.WaitForCommit();
+ }
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ EXPECT_EQ(data_url_0, observer.last_navigation_url());
+ EXPECT_EQ(child_site_instance_0,
+ child_0->current_frame_host()->GetSiteInstance());
+
+ GURL data_url_1("data:text/html,dataurl_1");
+ {
+ TestFrameNavigationObserver commit_observer(child_1);
+ EXPECT_TRUE(
+ ExecuteScript(child_1, "location.href = '" + data_url_1.spec() + "';"));
+ commit_observer.WaitForCommit();
+ }
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ EXPECT_EQ(data_url_1, observer.last_navigation_url());
+ EXPECT_EQ(child_site_instance_1,
+ child_1->current_frame_host()->GetSiteInstance());
+
+ // Grab the NavigationEntry and clone its PageState into a new entry for
+ // restoring into a new tab.
+ const NavigationControllerImpl& controller =
+ static_cast<const NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+ NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
+ std::unique_ptr<NavigationEntryImpl> restored_entry =
+ NavigationEntryImpl::FromNavigationEntry(
+ NavigationController::CreateNavigationEntry(
+ main_url, Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
+ std::string(), controller.GetBrowserContext(),
+ nullptr /* blob_url_loader_factory */));
+ EXPECT_EQ(0U, restored_entry->root_node()->children.size());
+ restored_entry->SetPageState(entry->GetPageState());
+ ASSERT_EQ(2U, restored_entry->root_node()->children.size());
+
+ // Restore the NavigationEntry into a new tab and check that the data URLs are
+ // not loaded into the parent's SiteInstance.
+ std::vector<std::unique_ptr<NavigationEntry>> entries;
+ entries.push_back(std::move(restored_entry));
+ Shell* new_shell = Shell::CreateNewWindow(
+ controller.GetBrowserContext(), GURL::EmptyGURL(), nullptr, gfx::Size());
+ FrameTreeNode* new_root =
+ static_cast<WebContentsImpl*>(new_shell->web_contents())
+ ->GetFrameTree()
+ ->root();
+ NavigationControllerImpl& new_controller =
+ static_cast<NavigationControllerImpl&>(
+ new_shell->web_contents()->GetController());
+ new_controller.Restore(entries.size() - 1,
+ RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
+ ASSERT_EQ(0u, entries.size());
+ {
+ TestNavigationObserver restore_observer(new_shell->web_contents());
+ new_controller.LoadIfNecessary();
+ restore_observer.Wait();
+ }
+ ASSERT_EQ(2U, new_root->child_count());
+ EXPECT_EQ(main_url, new_root->current_url());
+ EXPECT_EQ("data", new_root->child_at(0)->current_url().scheme());
+ EXPECT_EQ("data", new_root->child_at(1)->current_url().scheme());
+
+ EXPECT_NE(new_root->current_frame_host()->GetSiteInstance(),
+ new_root->child_at(0)->current_frame_host()->GetSiteInstance());
+ EXPECT_NE(new_root->current_frame_host()->GetSiteInstance(),
+ new_root->child_at(1)->current_frame_host()->GetSiteInstance());
+ EXPECT_NE(new_root->child_at(0)->current_frame_host()->GetSiteInstance(),
+ new_root->child_at(1)->current_frame_host()->GetSiteInstance());
+}
+
+// Similar to SubframeDataUrlsAfterRestore, but ensures that about:blank frames
+// do get put into their parent process after restore, even if they weren't
+// originally. This is safe because they do not contain active content (even
+// when there's a fragment in the URL), and it avoids unnecessary OOPIFs.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ SubframeBlankUrlsAfterRestore) {
+ // We must use a page that has iframes in the HTML here, unlike
+ // cross_site_iframe_factory.html which loads them dynamically. In the latter
+ // case, Chrome will not restore subframe URLs from history, which is needed
+ // for this test.
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/frame_tree/page_with_two_iframes.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ EXPECT_EQ(2U, root->child_count());
+ EXPECT_EQ(
+ " Site A ------------ proxies for B C\n"
+ " |--Site B ------- proxies for A C\n"
+ " +--Site C ------- proxies for A B\n"
+ "Where A = http://a.com/\n"
+ " B = http://bar.com/\n"
+ " C = http://baz.com/",
+ DepictFrameTree(root));
+
+ FrameTreeNode* child_0 = root->child_at(0);
+ FrameTreeNode* child_1 = root->child_at(1);
+ scoped_refptr<SiteInstanceImpl> child_site_instance_0 =
+ child_0->current_frame_host()->GetSiteInstance();
+ scoped_refptr<SiteInstanceImpl> child_site_instance_1 =
+ child_1->current_frame_host()->GetSiteInstance();
+
+ // Navigate the iframes to about:blank URLs via renderer initiated
+ // navigations, which will commit in the existing SiteInstances.
+ TestNavigationObserver observer(shell()->web_contents());
+ GURL blank_url("about:blank");
+ {
+ TestFrameNavigationObserver commit_observer(child_0);
+ EXPECT_TRUE(
+ ExecuteScript(child_0, "location.href = '" + blank_url.spec() + "';"));
+ commit_observer.WaitForCommit();
+ }
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ EXPECT_EQ(blank_url, observer.last_navigation_url());
+ EXPECT_EQ(child_site_instance_0,
+ child_0->current_frame_host()->GetSiteInstance());
+
+ GURL blank_url_ref("about:blank#1");
+ {
+ TestFrameNavigationObserver commit_observer(child_1);
+ EXPECT_TRUE(ExecuteScript(
+ child_1, "location.href = '" + blank_url_ref.spec() + "';"));
+ commit_observer.WaitForCommit();
+ }
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ EXPECT_EQ(blank_url_ref, observer.last_navigation_url());
+ EXPECT_EQ(child_site_instance_1,
+ child_1->current_frame_host()->GetSiteInstance());
+
+ // Grab the NavigationEntry and clone its PageState into a new entry for
+ // restoring into a new tab.
+ const NavigationControllerImpl& controller =
+ static_cast<const NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+ NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
+ std::unique_ptr<NavigationEntryImpl> restored_entry =
+ NavigationEntryImpl::FromNavigationEntry(
+ NavigationController::CreateNavigationEntry(
+ main_url, Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
+ std::string(), controller.GetBrowserContext(),
+ nullptr /* blob_url_loader_factory */));
+ EXPECT_EQ(0U, restored_entry->root_node()->children.size());
+ restored_entry->SetPageState(entry->GetPageState());
+ ASSERT_EQ(2U, restored_entry->root_node()->children.size());
+
+ // Restore the NavigationEntry into a new tab and check that the data URLs are
+ // not loaded into the parent's SiteInstance.
+ std::vector<std::unique_ptr<NavigationEntry>> entries;
+ entries.push_back(std::move(restored_entry));
+ Shell* new_shell = Shell::CreateNewWindow(
+ controller.GetBrowserContext(), GURL::EmptyGURL(), nullptr, gfx::Size());
+ FrameTreeNode* new_root =
+ static_cast<WebContentsImpl*>(new_shell->web_contents())
+ ->GetFrameTree()
+ ->root();
+ NavigationControllerImpl& new_controller =
+ static_cast<NavigationControllerImpl&>(
+ new_shell->web_contents()->GetController());
+ new_controller.Restore(entries.size() - 1,
+ RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
+ ASSERT_EQ(0u, entries.size());
+ {
+ TestNavigationObserver restore_observer(new_shell->web_contents());
+ new_controller.LoadIfNecessary();
+ restore_observer.Wait();
+ }
+ ASSERT_EQ(2U, new_root->child_count());
+ EXPECT_EQ(main_url, new_root->current_url());
+ EXPECT_TRUE(new_root->child_at(0)->current_url().IsAboutBlank());
+ EXPECT_TRUE(new_root->child_at(1)->current_url().IsAboutBlank());
+
+ EXPECT_EQ(new_root->current_frame_host()->GetSiteInstance(),
+ new_root->child_at(0)->current_frame_host()->GetSiteInstance());
+ EXPECT_EQ(new_root->current_frame_host()->GetSiteInstance(),
+ new_root->child_at(1)->current_frame_host()->GetSiteInstance());
+}
+
+// Similar to SubframeBlankUrlsAfterRestore, but ensures that about:srcdoc ends
+// up in its parent's process after restore, since that's where its content
+// comes from.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ SubframeSrcdocUrlAfterRestore) {
+ // Load a page that uses iframe srcdoc.
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/frame_tree/page_with_srcdoc_frame.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ EXPECT_EQ(1U, root->child_count());
+ FrameTreeNode* child = root->child_at(0);
+ scoped_refptr<SiteInstanceImpl> child_site_instance =
+ child->current_frame_host()->GetSiteInstance();
+ EXPECT_EQ(child_site_instance, root->current_frame_host()->GetSiteInstance());
+
+ // Grab the NavigationEntry and clone its PageState into a new entry for
+ // restoring into a new tab.
+ const NavigationControllerImpl& controller =
+ static_cast<const NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+ NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
+ std::unique_ptr<NavigationEntryImpl> restored_entry =
+ NavigationEntryImpl::FromNavigationEntry(
+ NavigationController::CreateNavigationEntry(
+ main_url, Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
+ std::string(), controller.GetBrowserContext(),
+ nullptr /* blob_url_loader_factory */));
+ EXPECT_EQ(0U, restored_entry->root_node()->children.size());
+ restored_entry->SetPageState(entry->GetPageState());
+ ASSERT_EQ(1U, restored_entry->root_node()->children.size());
+
+ // Restore the NavigationEntry into a new tab and check that the srcdoc URLs
+ // are still loaded into the parent's SiteInstance.
+ std::vector<std::unique_ptr<NavigationEntry>> entries;
+ entries.push_back(std::move(restored_entry));
+ Shell* new_shell = Shell::CreateNewWindow(
+ controller.GetBrowserContext(), GURL::EmptyGURL(), nullptr, gfx::Size());
+ FrameTreeNode* new_root =
+ static_cast<WebContentsImpl*>(new_shell->web_contents())
+ ->GetFrameTree()
+ ->root();
+ NavigationControllerImpl& new_controller =
+ static_cast<NavigationControllerImpl&>(
+ new_shell->web_contents()->GetController());
+ new_controller.Restore(entries.size() - 1,
+ RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
+ ASSERT_EQ(0u, entries.size());
+ {
+ TestNavigationObserver restore_observer(new_shell->web_contents());
+ new_controller.LoadIfNecessary();
+ restore_observer.Wait();
+ }
+ ASSERT_EQ(1U, new_root->child_count());
+ EXPECT_EQ(main_url, new_root->current_url());
+ EXPECT_EQ(GURL(content::kAboutSrcDocURL),
+ new_root->child_at(0)->current_url());
+
+ EXPECT_EQ(new_root->current_frame_host()->GetSiteInstance(),
+ new_root->child_at(0)->current_frame_host()->GetSiteInstance());
+}
+
// Ensures that navigating to about:blank URLs present in session history will
// correctly commit the navigation in the same process as the one used for
// the original navigation.
@@ -8082,8 +8307,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
child->current_frame_host()->GetView(),
proxy_to_parent->cross_process_frame_connector()->get_view_for_testing());
- // Make sure that the child frame has submitted a compositor frame.
- WaitForChildFrameSurfaceReady(child->current_frame_host());
+ // Make sure that the child frame has submitted a compositor frame
+ RenderFrameSubmissionObserver frame_observer(child);
+ frame_observer.WaitForMetadataChange();
// Send a postMessage from the child to its parent. This verifies that the
// parent's proxy in the child's SiteInstance was also restored.
@@ -9587,8 +9813,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Verify that a remote-to-local main frame navigation doesn't overwrite
// the previous history entry. See https://crbug.com/725716.
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
- CrossProcessMainFrameNavigationDoesNotOverwriteHistory) {
+IN_PROC_BROWSER_TEST_F(
+ SitePerProcessBrowserTest,
+ DISABLED_CrossProcessMainFrameNavigationDoesNotOverwriteHistory) {
GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title2.html"));
@@ -9917,7 +10144,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
manager1.WaitForNavigationFinished();
// Make sure the process is live and at the new URL.
- EXPECT_TRUE(b_site_instance->GetProcess()->HasConnection());
+ EXPECT_TRUE(b_site_instance->GetProcess()->IsInitializedAndNotDead());
EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
EXPECT_EQ(root_speculative_rfh, root->current_frame_host());
EXPECT_EQ(new_url_1, root->current_frame_host()->GetLastCommittedURL());
@@ -10009,7 +10236,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
manager2.WaitForNavigationFinished();
// Make sure the process is live and at the new URL.
- EXPECT_TRUE(b_site_instance->GetProcess()->HasConnection());
+ EXPECT_TRUE(b_site_instance->GetProcess()->IsInitializedAndNotDead());
ASSERT_EQ(2U, root->child_count());
EXPECT_TRUE(child->current_frame_host()->IsRenderFrameLive());
EXPECT_EQ(child_speculative_rfh, child->current_frame_host());
@@ -10402,7 +10629,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAndroidSiteIsolationTest,
// The child will change with the cross-site navigation. It shouldn't change
// after this.
child = root->child_at(0);
- WaitForChildFrameSurfaceReady(child->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
RenderWidgetHostViewChildFrame* child_view =
static_cast<RenderWidgetHostViewChildFrame*>(
@@ -11061,7 +11288,7 @@ class CommitMessageOrderReverser : public DidCommitProvisionalLoadInterceptor {
void WaitForBothCommits() { outer_run_loop.Run(); }
protected:
- void WillDispatchDidCommitProvisionalLoad(
+ bool WillDispatchDidCommitProvisionalLoad(
RenderFrameHost* render_frame_host,
::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
service_manager::mojom::InterfaceProviderRequest*
@@ -11080,6 +11307,7 @@ class CommitMessageOrderReverser : public DidCommitProvisionalLoadInterceptor {
} else if (nested_loop_quit_) {
std::move(nested_loop_quit_).Run();
}
+ return true;
}
private:
@@ -11210,7 +11438,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
DepictFrameTree(root));
FrameTreeNode* nested_child = root->child_at(0)->child_at(0);
- WaitForChildFrameSurfaceReady(nested_child->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(nested_child->current_frame_host());
EXPECT_TRUE(
ExecuteScript(nested_child->current_frame_host(), "startTest();"));
@@ -11442,8 +11670,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
popup_child->current_frame_host()->GetView());
// Make sure the child frame keeps generating compositor frames.
- ChildFrameCompositorFrameSwapCounter counter(child_view);
- counter.WaitForNewFrames(10u);
+ RenderFrameSubmissionObserver frame_counter(
+ child_view->host_->render_frame_metadata_provider());
+ while (frame_counter.render_frame_count() < 10)
+ frame_counter.WaitForAnyFrameSubmission();
}
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, FrameDepthSimple) {
@@ -11702,6 +11932,72 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(start_url, rfh->GetLastCommittedURL());
}
+namespace {
+
+// A helper class that watches for SwapOut ACK messages, allowing them
+// to go through but remembering that the message was received. It also
+// watches for any ShutdownRequests coming from the renderer and ensures that
+// the SwapOut ACK is received prior to those.
+class SwapoutACKReceivedFilter : public BrowserMessageFilter {
+ public:
+ explicit SwapoutACKReceivedFilter(RenderProcessHost* process)
+ : BrowserMessageFilter(FrameMsgStart) {
+ process->AddObserver(&shutdown_observer_);
+ process->AddFilter(this);
+ }
+
+ bool has_received_swapout_ack() { return received_; }
+
+ protected:
+ ~SwapoutACKReceivedFilter() override {}
+
+ private:
+ // BrowserMessageFilter:
+ bool OnMessageReceived(const IPC::Message& message) override {
+ if (message.type() == FrameHostMsg_SwapOut_ACK::ID) {
+ // This ensures that the SwapOut ACK arrived before any
+ // renderer-initiated process shutdown requests.
+ EXPECT_FALSE(shutdown_observer_.has_received_shutdown_request())
+ << " Shutdown request should be received after the swapout ACK";
+ received_ = true;
+ }
+ return false;
+ }
+
+ bool received_ = false;
+ ShutdownObserver shutdown_observer_;
+ DISALLOW_COPY_AND_ASSIGN(SwapoutACKReceivedFilter);
+};
+
+} // namespace
+
+// Verify that when the last active frame in a process is going away as part of
+// OnSwapOut, the SwapOut ACK is received prior to the process starting to shut
+// down, ensuring that any related unload work also happens before shutdown.
+// See https://crbug.com/867274 and https://crbug.com/794625.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ SwapOutACKArrivesPriorToProcessShutdownRequest) {
+ GURL start_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+ RenderFrameHostImpl* rfh = web_contents()->GetMainFrame();
+ rfh->DisableSwapOutTimerForTesting();
+
+ // Navigate cross-site. Since the current frame is the last active frame in
+ // the current process, the process will eventually shut down. Once the
+ // process goes away, ensure that the SwapOut ACK was received (i.e., that we
+ // didn't just simulate OnSwappedOut() due to the process erroneously going
+ // away before the SwapOut ACK was received, as in https://crbug.com/867274).
+ RenderProcessHostWatcher watcher(
+ rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ scoped_refptr<SwapoutACKReceivedFilter> swapout_ack_filter =
+ new SwapoutACKReceivedFilter(rfh->GetProcess());
+ GURL cross_site_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURLFromRenderer(shell(), cross_site_url));
+ watcher.Wait();
+ EXPECT_TRUE(swapout_ack_filter->has_received_swapout_ack());
+ EXPECT_TRUE(watcher.did_exit_normally());
+}
+
// Class to monitor incoming FrameHostMsg_UpdateViewportIntersection messages.
class UpdateViewportIntersectionMessageFilter
: public content::BrowserMessageFilter {
@@ -11903,7 +12199,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Verify that OOPIF select element popup menu coordinates account for scroll
// offset in containers embedding frame.
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, PopupMenuInTallIframeTest) {
+// TODO(crbug.com/859552): Reenable this.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ DISABLED_PopupMenuInTallIframeTest) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_tall_positioned_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -11972,7 +12270,7 @@ class ClosePageBeforeCommitHelper : public DidCommitProvisionalLoadInterceptor {
private:
// DidCommitProvisionalLoadInterceptor:
- void WillDispatchDidCommitProvisionalLoad(
+ bool WillDispatchDidCommitProvisionalLoad(
RenderFrameHost* render_frame_host,
::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
service_manager::mojom::InterfaceProviderRequest*
@@ -11983,6 +12281,7 @@ class ClosePageBeforeCommitHelper : public DidCommitProvisionalLoadInterceptor {
rvh->ClosePage();
if (run_loop_)
run_loop_->Quit();
+ return true;
}
std::unique_ptr<base::RunLoop> run_loop_;
@@ -12063,7 +12362,7 @@ class SitePerProcessBrowserTouchActionTest : public SitePerProcessBrowserTest {
router->RouteTouchEvent(rwhv_root, &touch_event,
ui::LatencyInfo(ui::SourceEventType::TOUCH));
ack_observer.Wait();
- cc::TouchAction touch_action =
+ base::Optional<cc::TouchAction> touch_action =
static_cast<RenderWidgetHostImpl*>(rwhv_child->GetRenderWidgetHost())
->input_router()
->AllowedTouchAction();
@@ -12081,24 +12380,28 @@ class SitePerProcessBrowserTouchActionTest : public SitePerProcessBrowserTest {
router->RouteTouchEvent(rwhv_root, &touch_event,
ui::LatencyInfo(ui::SourceEventType::TOUCH));
ack_observer.Wait();
- return touch_action;
+ return touch_action.has_value() ? touch_action.value()
+ : cc::kTouchActionAuto;
}
// Waits until the parent frame has had enough time to propagate the effective
// touch action to the child frame and the child frame has had enough time to
// process it.
- void WaitForTouchActionUpdated(MainThreadFrameObserver* observer,
- content::RenderFrameHost* child_frame) {
- // Ensures that main frame has calculated the new effective touch action for
- // child frames.
- observer->Wait();
- // Ensures that if a child frame is in progress we will wait until the next
- // one.
- WaitForChildFrameSurfaceReady(child_frame);
- // This child frame should receive the effective touch action from parent
- // (if the previous one didn't) and propagates it.
- WaitForChildFrameSurfaceReady(child_frame);
- observer->Wait();
+ void WaitForTouchActionUpdated(
+ MainThreadFrameObserver* root_thread_observer,
+ MainThreadFrameObserver* child_thread_observer) {
+ // Sends an event to the root frame's renderer main thread, upon return the
+ // root frame should have calculated the new effective touch action for the
+ // child frame.
+ root_thread_observer->Wait();
+ // Sends an event to the child frame's renderer main thread, upon return the
+ // child frame should have received the effective touch action from parent
+ // and propagated it.
+ child_thread_observer->Wait();
+ // The child's handling of the touch action may lead to further propagation
+ // back to the parent. This sends an event to the root frame's renderer main
+ // thread, upon return it should have handled any touch action update.
+ root_thread_observer->Wait();
}
};
@@ -12113,9 +12416,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
root->current_frame_host()->GetRenderWidgetHost()->GetView());
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child->current_frame_host()->GetRenderWidgetHost()->GetView());
- std::unique_ptr<MainThreadFrameObserver> observer(new MainThreadFrameObserver(
- root->current_frame_host()->GetRenderWidgetHost()));
- observer->Wait();
+ std::unique_ptr<MainThreadFrameObserver> root_thread_observer(
+ new MainThreadFrameObserver(
+ root->current_frame_host()->GetRenderWidgetHost()));
+ root_thread_observer->Wait();
GURL b_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
NavigateFrameToURL(child, b_url);
@@ -12124,7 +12428,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
EXPECT_TRUE(
ExecuteScript(shell(), "document.body.style.touchAction = 'none'"));
// Waits for the next frame.
- WaitForChildFrameSurfaceReady(child->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
+ std::unique_ptr<MainThreadFrameObserver> child_thread_observer(
+ new MainThreadFrameObserver(
+ child->current_frame_host()->GetRenderWidgetHost()));
RenderWidgetHostViewChildFrame* child_view =
static_cast<RenderWidgetHostViewChildFrame*>(
@@ -12135,7 +12442,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
RenderWidgetHostInputEventRouter* router =
static_cast<WebContentsImpl*>(web_contents())->GetInputEventRouter();
- WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ WaitForTouchActionUpdated(root_thread_observer.get(),
+ child_thread_observer.get());
// Gestures are filtered by the intersection of touch-action values of the
// touched element and all its ancestors up to the one that implements the
// gesture. Since iframe allows scrolling, touch action pan restrictions will
@@ -12147,7 +12455,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
EXPECT_TRUE(
ExecuteScript(shell(), "document.body.style.touchAction = 'auto'"));
- WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ WaitForTouchActionUpdated(root_thread_observer.get(),
+ child_thread_observer.get());
EXPECT_EQ(cc::TouchAction::kTouchActionAuto,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
point_inside_child));
@@ -12180,15 +12489,19 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
root->current_frame_host()->GetRenderWidgetHost()->GetView());
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child->current_frame_host()->GetRenderWidgetHost()->GetView());
- std::unique_ptr<MainThreadFrameObserver> observer(new MainThreadFrameObserver(
- root->current_frame_host()->GetRenderWidgetHost()));
- observer->Wait();
+ std::unique_ptr<MainThreadFrameObserver> root_thread_observer(
+ new MainThreadFrameObserver(
+ root->current_frame_host()->GetRenderWidgetHost()));
+ root_thread_observer->Wait();
EXPECT_TRUE(
ExecuteScript(shell(), "document.body.style.touchAction = 'none'"));
// Wait for child frame ready in order to get the correct point inside child.
- WaitForChildFrameSurfaceReady(child->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
+ std::unique_ptr<MainThreadFrameObserver> child_thread_observer(
+ new MainThreadFrameObserver(
+ child->current_frame_host()->GetRenderWidgetHost()));
RenderWidgetHostViewChildFrame* child_view =
static_cast<RenderWidgetHostViewChildFrame*>(
child->current_frame_host()->GetRenderWidgetHost()->GetView());
@@ -12199,7 +12512,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
static_cast<WebContentsImpl*>(web_contents())->GetInputEventRouter();
// Child should inherit effective touch action none from root.
- WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ WaitForTouchActionUpdated(root_thread_observer.get(),
+ child_thread_observer.get());
EXPECT_EQ(cc::TouchAction::kTouchActionPan,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
point_inside_child));
@@ -12210,7 +12524,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
EXPECT_TRUE(ExecuteScript(
parent,
"document.getElementById('parent-div').style.touchAction = 'none';"));
- WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ WaitForTouchActionUpdated(root_thread_observer.get(),
+ child_thread_observer.get());
EXPECT_EQ(cc::TouchAction::kTouchActionPan,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
point_inside_child));
@@ -12219,7 +12534,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
EXPECT_TRUE(ExecuteScript(
parent,
"document.getElementById('parent-div').style.touchAction = 'auto'"));
- WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ WaitForTouchActionUpdated(root_thread_observer.get(),
+ child_thread_observer.get());
EXPECT_EQ(cc::TouchAction::kTouchActionAuto,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
point_inside_child));
@@ -12247,15 +12563,19 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
root->current_frame_host()->GetRenderWidgetHost()->GetView());
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child->current_frame_host()->GetRenderWidgetHost()->GetView());
- std::unique_ptr<MainThreadFrameObserver> observer(new MainThreadFrameObserver(
- root->current_frame_host()->GetRenderWidgetHost()));
- observer->Wait();
+ std::unique_ptr<MainThreadFrameObserver> root_thread_observer(
+ new MainThreadFrameObserver(
+ root->current_frame_host()->GetRenderWidgetHost()));
+ root_thread_observer->Wait();
EXPECT_TRUE(
ExecuteScript(shell(), "document.body.style.touchAction = 'none'"));
// Wait for child frame ready in order to get the correct point inside child.
- WaitForChildFrameSurfaceReady(child->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
+ std::unique_ptr<MainThreadFrameObserver> child_thread_observer(
+ new MainThreadFrameObserver(
+ child->current_frame_host()->GetRenderWidgetHost()));
RenderWidgetHostViewChildFrame* child_view =
static_cast<RenderWidgetHostViewChildFrame*>(
child->current_frame_host()->GetRenderWidgetHost()->GetView());
@@ -12265,7 +12585,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
RenderWidgetHostInputEventRouter* router =
static_cast<WebContentsImpl*>(web_contents())->GetInputEventRouter();
// Child should inherit effective touch action none from root.
- WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ WaitForTouchActionUpdated(root_thread_observer.get(),
+ child_thread_observer.get());
EXPECT_EQ(cc::TouchAction::kTouchActionPan,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
point_inside_child));
@@ -12273,12 +12594,21 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
// After navigation, child should still inherit effective touch action none
// from parent.
GURL new_url(embedded_test_server()->GetURL("c.com", "/title2.html"));
+ // Reset before navigation, as navigation destroys the underlying
+ // RenderWidgetHost being observed.
+ child_thread_observer.reset();
NavigateFrameToURL(child, new_url);
- WaitForChildFrameSurfaceReady(child->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host());
+ // Navigation destroys the previous RenderWidgetHost, so we need to begin
+ // observing the new renderer main thread associated with the child frame.
+ child_thread_observer.reset(new MainThreadFrameObserver(
+ child->current_frame_host()->GetRenderWidgetHost()));
+
rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ WaitForTouchActionUpdated(root_thread_observer.get(),
+ child_thread_observer.get());
EXPECT_EQ(cc::TouchAction::kTouchActionPan,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
point_inside_child));
@@ -12691,4 +13021,131 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
subframe->effective_frame_policy().sandbox_flags);
}
+// Ensure that when two cross-site frames have subframes with unique origins,
+// and those subframes create blob URLs and navigate to them, the blob URLs end
+// up in different processes. See https://crbug.com/863623.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ TwoBlobURLsWithNullOriginDontShareProcess) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/navigation_controller/page_with_data_iframe.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ FrameTreeNode* subframe = root->child_at(0);
+
+ // Create a blob URL in the subframe, and navigate to it.
+ TestNavigationObserver observer(shell()->web_contents());
+ std::string blob_script =
+ "var blob = new Blob(['foo'], {type : 'text/html'});"
+ "var url = URL.createObjectURL(blob);"
+ "location = url;";
+ EXPECT_TRUE(ExecuteScript(subframe, blob_script));
+ observer.Wait();
+ RenderFrameHostImpl* subframe_rfh = subframe->current_frame_host();
+ EXPECT_TRUE(subframe_rfh->GetLastCommittedURL().SchemeIsBlob());
+
+ // Open a cross-site popup and repeat these steps.
+ GURL popup_url(embedded_test_server()->GetURL(
+ "b.com", "/navigation_controller/page_with_data_iframe.html"));
+ Shell* new_shell = OpenPopup(root, popup_url, "");
+ FrameTreeNode* popup_root =
+ static_cast<WebContentsImpl*>(new_shell->web_contents())
+ ->GetFrameTree()
+ ->root();
+ FrameTreeNode* popup_subframe = popup_root->child_at(0);
+
+ TestNavigationObserver popup_observer(new_shell->web_contents());
+ EXPECT_TRUE(ExecuteScript(popup_subframe, blob_script));
+ popup_observer.Wait();
+ RenderFrameHostImpl* popup_subframe_rfh =
+ popup_subframe->current_frame_host();
+ EXPECT_TRUE(popup_subframe_rfh->GetLastCommittedURL().SchemeIsBlob());
+
+ // Ensure that the two blob subframes don't share a process or SiteInstance.
+ EXPECT_NE(subframe->current_frame_host()->GetSiteInstance(),
+ popup_subframe->current_frame_host()->GetSiteInstance());
+ EXPECT_NE(
+ subframe->current_frame_host()->GetSiteInstance()->GetProcess(),
+ popup_subframe->current_frame_host()->GetSiteInstance()->GetProcess());
+ EXPECT_NE(
+ subframe->current_frame_host()->GetSiteInstance()->GetSiteURL(),
+ popup_subframe->current_frame_host()->GetSiteInstance()->GetSiteURL());
+}
+
+// Ensure that when a process is about to be destroyed after the last active
+// frame in it goes away, an attempt to reuse a proxy in that process doesn't
+// result in a crash. See https://crbug.com/794625.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ RenderFrameProxyNotRecreatedDuringProcessShutdown) {
+ GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ GURL popup_url(embedded_test_server()->GetURL(
+ "b.com", "/title1.html"));
+ Shell* new_shell = OpenPopup(root, popup_url, "foo");
+ FrameTreeNode* popup_root =
+ static_cast<WebContentsImpl*>(new_shell->web_contents())
+ ->GetFrameTree()
+ ->root();
+ auto* rfh = popup_root->current_frame_host();
+
+ // Disable the swapout timer to prevent flakiness.
+ rfh->DisableSwapOutTimerForTesting();
+
+ // This will be used to monitor that b.com process exits cleanly.
+ RenderProcessHostWatcher b_process_observer(
+ popup_root->current_frame_host()->GetProcess(),
+ RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
+
+ // In the first tab, install a postMessage handler to navigate the popup to a
+ // hung b.com URL once the first message is received.
+ GURL hung_b_url(embedded_test_server()->GetURL("b.com", "/hung"));
+ TestNavigationManager manager(new_shell->web_contents(), hung_b_url);
+ EXPECT_TRUE(ExecuteScript(shell(), base::StringPrintf(R"(
+ window.done = false;
+ window.onmessage = () => {
+ if (!window.done) {
+ window.open('%s', 'foo');
+ window.done = true;
+ }
+ };)", hung_b_url.spec().c_str())));
+
+ // In the popup, install an unload handler to send a lot of postMessages to
+ // the opener. This keeps the MessageLoop in the b.com process busy after
+ // navigating away from the current document. In https://crbug.com/794625,
+ // this was needed so that a subsequent IPC to recreate a proxy arrives
+ // before the process fully shuts down.
+ EXPECT_TRUE(ExecuteScript(new_shell, R"(
+ window.onunload = () => {
+ for (var i=0; i<10000; i++)
+ opener.postMessage('hi','*');
+ })"));
+
+ // Navigate popup to a.com. This swaps out the last active frame in the
+ // b.com process, and hence initiates process shutdown.
+ TestFrameNavigationObserver commit_observer(popup_root);
+ GURL another_a_url(embedded_test_server()->GetURL("a.com", "/title3.html"));
+ EXPECT_TRUE(ExecuteScript(
+ new_shell,
+ base::StringPrintf("location = '%s';", another_a_url.spec().c_str())));
+ commit_observer.WaitForCommit();
+
+ // At this point, popup's original RFH is pending deletion.
+ EXPECT_FALSE(rfh->is_active());
+
+ // When the opener receives a postMessage from the popup's unload handler, it
+ // should start a navigation back to b.com. Wait for it. This navigation
+ // creates a speculative RFH which reuses the proxy that was created as part
+ // of swapping out from |popup_url| to |another_a_url|.
+ EXPECT_TRUE(manager.WaitForRequestStart());
+
+ // Cancel the started navigation (to /hung) in the popup and make sure the
+ // b.com renderer process exits cleanly without a crash. In
+ // https://crbug.com/794625, the crash was caused by trying to recreate the
+ // reused proxy, which had been incorrectly set as non-live.
+ popup_root->ResetNavigationRequest(false, false);
+ b_process_observer.Wait();
+ EXPECT_TRUE(b_process_observer.did_exit_normally());
+}
+
} // namespace content
diff --git a/chromium/content/browser/site_per_process_hit_test_browsertest.cc b/chromium/content/browser/site_per_process_hit_test_browsertest.cc
index 9884d624e54..8f00efa866d 100644
--- a/chromium/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/chromium/content/browser/site_per_process_hit_test_browsertest.cc
@@ -28,6 +28,7 @@
#include "content/public/common/use_zoom_for_dsf_policy.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/common/shell_switches.h"
@@ -41,6 +42,7 @@
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "content/public/browser/overscroll_configuration.h"
#include "content/test/mock_overscroll_controller_delegate_aura.h"
+#include "ui/aura/window_tree_host.h"
#endif
#if defined(OS_MACOSX)
@@ -240,7 +242,7 @@ void SurfaceHitTestTestHelper(
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
DispatchMouseEventAndWaitUntilDispatch(web_contents, rwhv_child,
gfx::PointF(5, 5), rwhv_child,
@@ -273,7 +275,7 @@ void OverlapSurfaceHitTestHelper(
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
gfx::PointF parent_location = gfx::PointF(5, 5);
parent_location =
@@ -320,7 +322,8 @@ void NestedSurfaceHitTestTestHelper(
->GetRenderWidgetHost()
->GetView());
- WaitForChildFrameSurfaceReady(nested_iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(
+ nested_iframe_node->current_frame_host());
DispatchMouseEventAndWaitUntilDispatch(web_contents, rwhv_nested,
gfx::PointF(10, 10), rwhv_nested,
@@ -350,7 +353,7 @@ void HitTestLayerSquashing(
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
gfx::Vector2dF child_offset = rwhv_child->GetViewBounds().origin() -
rwhv_root->GetViewBounds().origin();
@@ -399,7 +402,7 @@ void HitTestWatermark(
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
gfx::Vector2dF child_offset = rwhv_child->GetViewBounds().origin() -
rwhv_root->GetViewBounds().origin();
@@ -419,15 +422,48 @@ void HitTestWatermark(
web_contents, rwhv_child, child_location, rwhv_child, child_location);
}
-// This helper accounts for Android devices which use page scale factor
-// different from 1.0. Coordinate targeting needs to be adjusted before
-// hit testing.
-double GetPageScaleFactor(Shell* shell) {
- return RenderWidgetHostImpl::From(
- shell->web_contents()->GetRenderViewHost()->GetWidget())
- ->last_frame_metadata()
- .page_scale_factor;
+#if defined(USE_AURA)
+void HitTestRootWindowTransform(
+ Shell* shell,
+ net::test_server::EmbeddedTestServer* embedded_test_server) {
+ // Apply transform to root window to test that we respect root window
+ // transform when transforming event location.
+ gfx::Transform transform;
+ transform.RotateAboutXAxis(180.f);
+ transform.Translate(0.f,
+ -shell->window()->GetHost()->window()->bounds().height());
+ shell->window()->GetHost()->SetRootTransform(transform);
+
+ GURL main_url(embedded_test_server->GetURL(
+ "/frame_tree/page_with_positioned_frame.html"));
+ EXPECT_TRUE(NavigateToURL(shell, main_url));
+ auto* web_contents = static_cast<WebContentsImpl*>(shell->web_contents());
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = 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());
+
+ RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
+
+ DispatchMouseEventAndWaitUntilDispatch(web_contents, rwhv_child,
+ gfx::PointF(5, 5), rwhv_child,
+ gfx::PointF(5, 5));
+
+ DispatchMouseEventAndWaitUntilDispatch(
+ web_contents, rwhv_root, gfx::PointF(2, 2), rwhv_root, gfx::PointF(2, 2));
}
+#endif // defined(USE_AURA)
#if defined(USE_AURA)
bool ConvertJSONToPoint(const std::string& str, gfx::PointF* point) {
@@ -550,7 +586,8 @@ class SitePerProcessHitTestBrowserTest
feature_list_.InitAndEnableFeature(
features::kEnableVizHitTestSurfaceLayer);
} else {
- feature_list_.InitAndDisableFeature(features::kEnableVizHitTestDrawQuad);
+ feature_list_.InitWithFeatures({}, {features::kEnableVizHitTestDrawQuad,
+ features::kVizDisplayCompositor});
}
}
@@ -637,7 +674,8 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessInternalsHitTestBrowserTest,
NavigateFrameToURL(parent_iframe_node, site_url);
FrameTreeNode* nested_iframe_node = parent_iframe_node->child_at(0);
- WaitForChildFrameSurfaceReady(nested_iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(
+ nested_iframe_node->current_frame_host());
EXPECT_EQ(
" Site A ------------ proxies for B\n"
@@ -763,7 +801,8 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessInternalsHitTestBrowserTest,
NavigateFrameToURL(parent_iframe_node, site_url);
FrameTreeNode* nested_iframe_node = parent_iframe_node->child_at(0);
- WaitForChildFrameSurfaceReady(nested_iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(
+ nested_iframe_node->current_frame_host());
EXPECT_EQ(
" Site A ------------ proxies for B\n"
@@ -916,17 +955,29 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessInternalsHitTestBrowserTest,
}
#endif // defined(USE_AURA)
+#if defined(OS_CHROMEOS)
+// Times out flakily on Chrome OS. crbug.com/833380
+#define MAYBE_CancelWheelScrollBubblingOnWheelTargetDeletion \
+ DISABLED_CancelWheelScrollBubblingOnWheelTargetDeletion
+#else
+#define MAYBE_CancelWheelScrollBubblingOnWheelTargetDeletion \
+ CancelWheelScrollBubblingOnWheelTargetDeletion
+#endif
+
// Tests that wheel scroll bubbling gets cancelled when the wheel target view
// gets destroyed in the middle of a wheel scroll seqeunce. This happens in
// cases like overscroll navigation from inside an oopif.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- CancelWheelScrollBubblingOnWheelTargetDeletion) {
+ MAYBE_CancelWheelScrollBubblingOnWheelTargetDeletion) {
ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
0);
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameSubmissionObserver render_frame_submission_observer(
+ shell()->web_contents());
+
// It is safe to obtain the root frame tree node here, as it doesn't change.
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
ASSERT_EQ(1U, root->child_count());
@@ -945,7 +996,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
static_cast<WebContentsImpl*>(shell()->web_contents())
->GetInputEventRouter();
- WaitForChildFrameSurfaceReady(iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(iframe_node->current_frame_host());
InputEventAckWaiter scroll_begin_observer(
root->current_frame_host()->GetRenderWidgetHost(),
@@ -959,7 +1010,9 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
blink::WebInputEvent::kMouseWheel, blink::WebInputEvent::kNoModifiers,
blink::WebInputEvent::GetStaticTimeStampForTests());
gfx::Rect bounds = child_rwhv->GetViewBounds();
- float scale_factor = GetPageScaleFactor(shell());
+ float scale_factor =
+ render_frame_submission_observer.LastRenderFrameMetadata()
+ .page_scale_factor;
gfx::Point position_in_widget(
gfx::ToCeiledInt((bounds.x() - root_view->GetViewBounds().x() + 5) *
scale_factor),
@@ -989,6 +1042,14 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
scroll_end_observer.Wait();
}
+#if defined(OS_LINUX)
+// The test is flaky on Linux: https://crbug.com/833380.
+#define MAYBE_BubbledScrollEventsTransformedCorrectly \
+ DISABLED_BubbledScrollEventsTransformedCorrectly
+#else
+#define MAYBE_BubbledScrollEventsTransformedCorrectly \
+ BubbledScrollEventsTransformedCorrectly
+#endif
// When a scroll event is bubbled, ensure that the bubbled event's coordinates
// are correctly updated to the ancestor's coordinate space. In particular,
// ensure that the transformation considers CSS scaling of the child where
@@ -996,11 +1057,14 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// coordinates in the ancestor's coordinate space.
// See https://crbug.com/817392
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- BubbledScrollEventsTransformedCorrectly) {
+ MAYBE_BubbledScrollEventsTransformedCorrectly) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_scaled_frame.html"));
ASSERT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameSubmissionObserver render_frame_submission_observer(
+ shell()->web_contents());
+
// It is safe to obtain the root frame tree node here, as it doesn't change.
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
ASSERT_EQ(1U, root->child_count());
@@ -1016,9 +1080,11 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
static_cast<WebContentsImpl*>(shell()->web_contents())
->GetInputEventRouter();
- WaitForChildFrameSurfaceReady(iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(iframe_node->current_frame_host());
- const float scale_factor = GetPageScaleFactor(shell());
+ const float scale_factor =
+ render_frame_submission_observer.LastRenderFrameMetadata()
+ .page_scale_factor;
// Due to the CSS scaling of the iframe, the position in the child view's
// coordinates is (96, 96) and not (48, 48) (or approximately these values
// if there's rounding due to the scale factor).
@@ -1062,13 +1128,17 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
class SitePerProcessEmulatedTouchBrowserTest
: public SitePerProcessHitTestBrowserTest {
public:
- enum TestType { ScrollBubbling, PinchGoesToMainFrame };
+ enum TestType { ScrollBubbling, PinchGoesToMainFrame, TouchActionBubbling };
~SitePerProcessEmulatedTouchBrowserTest() override {}
void RunTest(TestType test_type) {
- GURL main_url(embedded_test_server()->GetURL(
- "/frame_tree/page_with_positioned_frame.html"));
+ std::string url;
+ if (test_type == TouchActionBubbling)
+ url = "/frame_tree/page_with_pany_frame.html";
+ else
+ url = "/frame_tree/page_with_positioned_frame.html";
+ GURL main_url(embedded_test_server()->GetURL(url));
ASSERT_TRUE(NavigateToURL(shell(), main_url));
// It is safe to obtain the root frame tree node here, as it doesn't change.
@@ -1091,7 +1161,7 @@ class SitePerProcessEmulatedTouchBrowserTest
static_cast<WebContentsImpl*>(shell()->web_contents())
->GetInputEventRouter();
- WaitForChildFrameSurfaceReady(iframe_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(iframe_node->current_frame_host());
auto expect_gesture_with_position = base::BindRepeating(
[](blink::WebInputEvent::Type expected_type,
@@ -1114,6 +1184,7 @@ class SitePerProcessEmulatedTouchBrowserTest
blink::WebInputEvent::Type expected_gesture_type;
switch (test_type) {
case ScrollBubbling:
+ case TouchActionBubbling:
expected_gesture_type = blink::WebInputEvent::kGestureScrollBegin;
break;
case PinchGoesToMainFrame:
@@ -1186,7 +1257,7 @@ class SitePerProcessEmulatedTouchBrowserTest
router->RouteMouseEvent(root_rwhv, &mouse_drag_event, ui::LatencyInfo());
router->RouteMouseEvent(root_rwhv, &mouse_up_event, ui::LatencyInfo());
- if (test_type == ScrollBubbling) {
+ if (test_type == ScrollBubbling || test_type == TouchActionBubbling) {
// Verify child receives GestureScrollBegin.
child_gesture_event_observer.Wait();
}
@@ -1200,16 +1271,43 @@ class SitePerProcessEmulatedTouchBrowserTest
}
};
+#if defined(OS_CHROMEOS)
+// Flaky: https://crbug.com/833380
+#define MAYBE_EmulatedTouchScrollBubbles DISABLED_EmulatedTouchScrollBubbles
+#else
+#define MAYBE_EmulatedTouchScrollBubbles EmulatedTouchScrollBubbles
+#endif
+
IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest,
- EmulatedTouchScrollBubbles) {
+ MAYBE_EmulatedTouchScrollBubbles) {
RunTest(ScrollBubbling);
}
+#if defined(OS_LINUX)
+// Flaky: https://crbug.com/833380
+#define MAYBE_EmulatedTouchPinchGoesToMainFrame \
+ DISABLED_EmulatedTouchPinchGoesToMainFrame
+#else
+#define MAYBE_EmulatedTouchPinchGoesToMainFrame \
+ EmulatedTouchPinchGoesToMainFrame
+#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest,
- EmulatedTouchPinchGoesToMainFrame) {
+ MAYBE_EmulatedTouchPinchGoesToMainFrame) {
RunTest(PinchGoesToMainFrame);
}
+#if defined(OS_CHROMEOS)
+// Flaky timeouts: https://crbug.com/833380
+#define MAYBE_EmulatedGestureScrollBubbles DISABLED_EmulatedGestureScrollBubbles
+#else
+#define MAYBE_EmulatedGestureScrollBubbles EmulatedGestureScrollBubbles
+#endif
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest,
+ MAYBE_EmulatedGestureScrollBubbles) {
+ RunTest(TouchActionBubbling);
+}
+
#if defined(USE_AURA) || defined(OS_ANDROID)
// When unconsumed scrolls in a child bubble to the root and start an
@@ -1230,6 +1328,9 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
"a.com", "/cross_site_iframe_factory.html?a(b)"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameSubmissionObserver render_frame_submission_observer(
+ shell()->web_contents());
+
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root();
@@ -1259,7 +1360,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
static_cast<RenderWidgetHostViewChildFrame*>(
child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
ASSERT_TRUE(rwhv_root->IsScrollOffsetAtTop());
ASSERT_TRUE(rwhv_child->IsScrollOffsetAtTop());
@@ -1273,7 +1374,9 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// to the child.
const gfx::Rect root_bounds = rwhv_root->GetViewBounds();
const gfx::Rect child_bounds = rwhv_child->GetViewBounds();
- const float page_scale_factor = GetPageScaleFactor(shell());
+ const float page_scale_factor =
+ render_frame_submission_observer.LastRenderFrameMetadata()
+ .page_scale_factor;
const gfx::PointF point_in_child(
(child_bounds.x() - root_bounds.x() + 10) * page_scale_factor,
(child_bounds.y() - root_bounds.y() + 10) * page_scale_factor);
@@ -1433,7 +1536,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// and is needed for trackpad scrolling on Chromebooks.
#if defined(USE_AURA)
-#if defined(THREAD_SANITIZER)
+#if defined(THREAD_SANITIZER) || defined(OS_CHROMEOS)
// Flaky: https://crbug.com/833380
#define MAYBE_ScrollEventToOOPIF DISABLED_ScrollEventToOOPIF
#else
@@ -1461,7 +1564,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
static_cast<RenderWidgetHostViewAura*>(
root->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
// Create listener for input events.
TestInputEventObserver child_frame_monitor(
@@ -1482,7 +1585,10 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// Verify that this a mouse wheel event was sent to the child frame renderer.
EXPECT_TRUE(child_frame_monitor.EventWasReceived());
- EXPECT_EQ(child_frame_monitor.EventType(), blink::WebInputEvent::kMouseWheel);
+ const auto& child_events = child_frame_monitor.events_received();
+ EXPECT_NE(child_events.end(),
+ std::find(child_events.begin(), child_events.end(),
+ blink::WebInputEvent::kMouseWheel));
}
#if defined(THREAD_SANITIZER)
@@ -1516,7 +1622,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
static_cast<RenderWidgetHostViewAura*>(
root->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
RenderWidgetHostInputEventRouter* router =
web_contents()->GetInputEventRouter();
@@ -1580,9 +1686,10 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// Test that mouse events are being routed to the correct RenderWidgetHostView
// based on coordinates.
-#if defined(THREAD_SANITIZER)
+#if defined(THREAD_SANITIZER) || defined(OS_CHROMEOS)
// The test times out often on TSAN bot.
// https://crbug.com/591170.
+// Also times out flakily on Chrome OS. crbug.com/833380
#define MAYBE_SurfaceHitTestTest DISABLED_SurfaceHitTestTest
#else
#define MAYBE_SurfaceHitTestTest SurfaceHitTestTest
@@ -1624,11 +1731,6 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
NestedSurfaceHitTestTestHelper(shell(), embedded_test_server());
}
-IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- OverlapSurfaceHitTestTest) {
- OverlapSurfaceHitTestHelper(shell(), embedded_test_server());
-}
-
#if defined(OS_LINUX)
// Flaky timeouts and failures: https://crbug.com/833380
#define MAYBE_OverlapSurfaceHitTestTest DISABLED_OverlapSurfaceHitTestTest
@@ -1640,6 +1742,11 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
OverlapSurfaceHitTestHelper(shell(), embedded_test_server());
}
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
+ MAYBE_OverlapSurfaceHitTestTest) {
+ OverlapSurfaceHitTestHelper(shell(), embedded_test_server());
+}
+
#if defined(OS_LINUX)
// Flaky timeouts and failures: https://crbug.com/833380
#define MAYBE_HitTestLayerSquashing DISABLED_HitTestLayerSquashing
@@ -1672,8 +1779,26 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
HitTestWatermark(shell(), embedded_test_server());
}
+#if defined(USE_AURA)
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, RootWindowTransform) {
+ HitTestRootWindowTransform(shell(), embedded_test_server());
+}
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
+ RootWindowTransform) {
+ HitTestRootWindowTransform(shell(), embedded_test_server());
+}
+#endif // defined(USE_AURA)
+
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
HitTestStaleDataDeletedView) {
+ // TODO(sunxd): Hit test regions are not submitted for overlapping surfaces,
+ // causing /2 to fail outside of Viz. https::/crbug.com/846798
+ if (base::FeatureList::IsEnabled(features::kEnableVizHitTestSurfaceLayer) &&
+ !base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) {
+ return;
+ }
+
// Have two iframes to avoid going to short circuit path during the second
// targeting.
GURL main_url(
@@ -1705,8 +1830,8 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
static_cast<RenderWidgetHostViewBase*>(
child_node2->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForChildFrameSurfaceReady(child_node1->current_frame_host());
- WaitForChildFrameSurfaceReady(child_node2->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node1->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node2->current_frame_host());
const gfx::PointF child_location(50, 50);
gfx::PointF parent_location =
@@ -1745,7 +1870,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
EXPECT_EQ(result.target_location.value(), parent_location);
}
-#if defined(THREAD_SANITIZER)
+#if defined(THREAD_SANITIZER) || defined(OS_LINUX)
// Flaky: https://crbug.com/833380
#define MAYBE_SurfaceHitTestPointerEventsNone \
DISABLED_SurfaceHitTestPointerEventsNone
@@ -1783,7 +1908,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
root->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
// Target input event to child frame.
blink::WebMouseEvent child_event(
@@ -1805,10 +1930,18 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
EXPECT_FALSE(child_frame_monitor.EventWasReceived());
}
+#if defined(OS_CHROMEOS)
+// Flaky on Chrome OS. crbug.com/833380
+#define MAYBE_AsynchronousHitTestChildTimeout \
+ DISABLED_AsynchronousHitTestChildTimeout
+#else
+#define MAYBE_AsynchronousHitTestChildTimeout AsynchronousHitTestChildTimeout
+#endif
+
// Verify that an event is properly retargeted to the main frame when an
// asynchronous hit test to the child frame times out.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- AsynchronousHitTestChildTimeout) {
+ MAYBE_AsynchronousHitTestChildTimeout) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_busy_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1836,7 +1969,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
root->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
// Target input event to child frame. It should get delivered to the main
// frame instead because the child frame main thread is non-responsive.
@@ -1925,7 +2058,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
TooltipMonitor tooltip_monitor(rwhv_a->GetCursorManager());
- WaitForChildFrameSurfaceReady(b_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(b_node->current_frame_host());
// Make sure the point_in_a_frame value is outside the default 8px margin
// for the body element.
@@ -2026,7 +2159,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// than nullptr. If it did, this test would be unnecessary.
DCHECK(!rwhv_a->GetCursorManager());
- WaitForChildFrameSurfaceReady(b_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(b_node->current_frame_host());
// Make sure the point_in_a_frame value is outside the default 8px margin
// for the body element.
@@ -2104,6 +2237,9 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
"a.com", "/cross_site_iframe_factory.html?a(b,c(d))"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameSubmissionObserver render_frame_submission_observer(
+ shell()->web_contents());
+
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root();
@@ -2132,8 +2268,8 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// Verifying surfaces are ready in B and D are sufficient, since other
// surfaces contain at least one of them.
- WaitForChildFrameSurfaceReady(b_node->current_frame_host());
- WaitForChildFrameSurfaceReady(d_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(b_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(d_node->current_frame_host());
// Create listeners for mouse events. These are used to verify that the
// RenderWidgetHostInputEventRouter is generating MouseLeave, etc for
@@ -2149,7 +2285,9 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
RenderWidgetHostMouseEventMonitor d_frame_monitor(
d_node->current_frame_host()->GetRenderWidgetHost());
- float scale_factor = GetPageScaleFactor(shell());
+ float scale_factor =
+ render_frame_submission_observer.LastRenderFrameMetadata()
+ .page_scale_factor;
// Get the view bounds of the child iframe, which should account for the
// relative offset of its direct parent within the root frame, for use in
@@ -2211,12 +2349,6 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
EXPECT_TRUE(d_frame_monitor.EventWasReceived());
}
-#if defined(OS_LINUX)
-// Flaky timeouts and failures: https://crbug.com/833380
-#define MAYBE_CrossProcessMouseCapture DISABLED_CrossProcessMouseCapture
-#else
-#define MAYBE_CrossProcessMouseCapture CrossProcessMouseCapture
-#endif
// Verify that mouse capture works on a RenderWidgetHostView level, so that
// dragging scroll bars and selecting text continues even when the mouse
// cursor crosses over cross-process frame boundaries.
@@ -2224,11 +2356,14 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// Other reasons for a node to capture mouse input need to be addressed. See
// https://crbug.com/647378.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- MAYBE_CrossProcessMouseCapture) {
+ CrossProcessMouseCapture) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_large_scrollable_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameSubmissionObserver render_frame_submission_observer(
+ shell()->web_contents());
+
// It is safe to obtain the root frame tree node here, as it doesn't change.
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
ASSERT_EQ(1U, root->child_count());
@@ -2255,9 +2390,11 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
- float scale_factor = GetPageScaleFactor(shell());
+ float scale_factor =
+ render_frame_submission_observer.LastRenderFrameMetadata()
+ .page_scale_factor;
// Get the view bounds of the child iframe, which should account for the
// relative offset of its direct parent within the root frame, for use in
@@ -2418,7 +2555,7 @@ void CursorUpdateReceivedFromCrossSiteIframeHelper(
EXPECT_NE(shell->web_contents()->GetSiteInstance(),
child_node->current_frame_host()->GetSiteInstance());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
scoped_refptr<CursorMessageFilter> filter = new CursorMessageFilter();
child_node->current_frame_host()->GetProcess()->AddFilter(filter.get());
@@ -2578,12 +2715,10 @@ class SitePerProcessMouseWheelHitTestBrowserTest
web_contents()->GetRenderWidgetHostView());
set_rwhv_root(rwhv_root);
- if (rwhv_root->wheel_scroll_latching_enabled()) {
- // Set the wheel scroll latching timeout to a large value to make sure
- // that the timer doesn't expire for the duration of the test.
- rwhv_root->event_handler()->set_mouse_wheel_wheel_phase_handler_timeout(
- TestTimeouts::action_max_timeout());
- }
+ // Set the wheel scroll latching timeout to a large value to make sure
+ // that the timer doesn't expire for the duration of the test.
+ rwhv_root->event_handler()->set_mouse_wheel_wheel_phase_handler_timeout(
+ TestTimeouts::action_max_timeout());
InputEventAckWaiter waiter(expected_target->GetRenderWidgetHost(),
blink::WebInputEvent::kMouseWheel);
@@ -2598,19 +2733,13 @@ class SitePerProcessMouseWheelHitTestBrowserTest
SendMouseWheel(pos);
- // If async_wheel_events is disabled, this time only the wheel handler
- // fires, since even numbered scrolls are prevent-defaulted. If it is
- // enabled, then this wheel event will be sent non-blockingly and won't be
- // cancellable.
+ // Even though even number events are prevented by default since the first
+ // wheel event is not prevented by default, the rest of the wheel events
+ // will be handled nonblocking and the scroll will happen.
EXPECT_TRUE(msg_queue.WaitForMessage(&reply));
EXPECT_EQ("\"wheel: 2\"", reply);
- if (base::FeatureList::IsEnabled(features::kAsyncWheelEvents) &&
- base::FeatureList::IsEnabled(
- features::kTouchpadAndWheelScrollLatching)) {
- DCHECK(rwhv_root->wheel_scroll_latching_enabled());
- EXPECT_TRUE(msg_queue.WaitForMessage(&reply));
- EXPECT_EQ("\"scroll: 2\"", reply);
- }
+ EXPECT_TRUE(msg_queue.WaitForMessage(&reply));
+ EXPECT_EQ("\"scroll: 2\"", reply);
SendMouseWheel(pos);
@@ -2626,26 +2755,16 @@ class SitePerProcessMouseWheelHitTestBrowserTest
RenderWidgetHostViewAura* rwhv_root_;
};
-// Subclass to disable wheel scroll latching in failing tests.
-// https://crbug.com/800822
-class SitePerProcessMouseWheelHitTestBrowserTestWheelScrollLatchingDisabled
- : public SitePerProcessMouseWheelHitTestBrowserTest {
- public:
- SitePerProcessMouseWheelHitTestBrowserTestWheelScrollLatchingDisabled() {}
- void SetUp() override {
- feature_list_.InitWithFeatures({},
- {features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents});
- SitePerProcessMouseWheelHitTestBrowserTest::SetUp();
- }
-
- private:
- base::test::ScopedFeatureList feature_list_;
-};
-
-IN_PROC_BROWSER_TEST_P(
- SitePerProcessMouseWheelHitTestBrowserTestWheelScrollLatchingDisabled,
- MultipleSubframeWheelEventsOnMainThread) {
+// Fails on Windows official build, see // https://crbug.com/800822
+#if defined(OS_WIN)
+#define MAYBE_MultipleSubframeWheelEventsOnMainThread \
+ DISABLED_MultipleSubframeWheelEventsOnMainThread
+#else
+#define MAYBE_MultipleSubframeWheelEventsOnMainThread \
+ MultipleSubframeWheelEventsOnMainThread
+#endif
+IN_PROC_BROWSER_TEST_P(SitePerProcessMouseWheelHitTestBrowserTest,
+ MAYBE_MultipleSubframeWheelEventsOnMainThread) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_two_positioned_frames.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -2668,8 +2787,7 @@ IN_PROC_BROWSER_TEST_P(
static_cast<RenderWidgetHostViewBase*>(
root->child_at(frame_index)->current_frame_host()->GetView());
- EXPECT_FALSE(child_rwhv->wheel_scroll_latching_enabled());
- WaitForChildFrameSurfaceReady(
+ WaitForHitTestDataOrChildSurfaceReady(
root->child_at(frame_index)->current_frame_host());
content::RenderFrameHostImpl* child =
@@ -2685,9 +2803,15 @@ IN_PROC_BROWSER_TEST_P(
// Verifies that test in SubframeWheelEventsOnMainThread also makes sense for
// the same page loaded in the mainframe.
-IN_PROC_BROWSER_TEST_P(
- SitePerProcessMouseWheelHitTestBrowserTestWheelScrollLatchingDisabled,
- MainframeWheelEventsOnMainThread) {
+// Fails on Windows official build, see // https://crbug.com/800822
+#if defined(OS_WIN)
+#define MAYBE_MainframeWheelEventsOnMainThread \
+ DISABLED_MainframeWheelEventsOnMainThread
+#else
+#define MAYBE_MainframeWheelEventsOnMainThread MainframeWheelEventsOnMainThread
+#endif
+IN_PROC_BROWSER_TEST_P(SitePerProcessMouseWheelHitTestBrowserTest,
+ MAYBE_MainframeWheelEventsOnMainThread) {
GURL main_url(
embedded_test_server()->GetURL("/page_with_scrollable_div.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -2696,9 +2820,6 @@ IN_PROC_BROWSER_TEST_P(
content::RenderFrameHostImpl* rfhi = root->current_frame_host();
SetupWheelAndScrollHandlers(rfhi);
- EXPECT_FALSE(
- rfhi->GetRenderWidgetHost()->GetView()->wheel_scroll_latching_enabled());
-
gfx::Point pos(10, 10);
RunTest(pos, rfhi->GetRenderWidgetHost()->GetView());
@@ -2724,7 +2845,8 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessMouseWheelHitTestBrowserTest,
// surface information required for event hit testing is ready.
RenderWidgetHostViewBase* child_rwhv = static_cast<RenderWidgetHostViewBase*>(
root->child_at(0)->current_frame_host()->GetView());
- WaitForChildFrameSurfaceReady(root->child_at(0)->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(
+ root->child_at(0)->current_frame_host());
RenderWidgetHostInputEventRouter* router =
web_contents()->GetInputEventRouter();
@@ -2737,24 +2859,22 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessMouseWheelHitTestBrowserTest,
SendMouseWheel(pos);
waiter.Wait();
- if (child_rwhv->wheel_scroll_latching_enabled())
- EXPECT_EQ(child_rwhv, router->wheel_target_.target);
- else
- EXPECT_EQ(nullptr, router->wheel_target_.target);
+ EXPECT_EQ(child_rwhv, router->wheel_target_.target);
- // Send a mouse wheel event to the main frame. If wheel scroll latching is
- // enabled it will be still routed to child till the end of current scrolling
- // sequence. Since wheel scroll latching is enabled by default, we always do
- // sync targeting so InputEventAckWaiter is not needed here.
+ // Send a mouse wheel event to the main frame. It will be still routed to
+ // child till the end of current scrolling sequence. Since wheel scroll
+ // latching is enabled by default, we always do sync targeting so
+ // InputEventAckWaiter is not needed here.
TestInputEventObserver child_frame_monitor(child_rwhv->GetRenderWidgetHost());
SendMouseWheel(pos);
- if (child_rwhv->wheel_scroll_latching_enabled())
- EXPECT_EQ(child_rwhv, router->wheel_target_.target);
- else
- EXPECT_EQ(nullptr, router->wheel_target_.target);
+ EXPECT_EQ(child_rwhv, router->wheel_target_.target);
+
// Verify that this a mouse wheel event was sent to the child frame renderer.
EXPECT_TRUE(child_frame_monitor.EventWasReceived());
- EXPECT_EQ(child_frame_monitor.EventType(), blink::WebInputEvent::kMouseWheel);
+ const auto& child_events = child_frame_monitor.events_received();
+ EXPECT_NE(child_events.end(),
+ std::find(child_events.begin(), child_events.end(),
+ blink::WebInputEvent::kMouseWheel));
// Kill the wheel target view process. This must reset the wheel_target_.
RenderProcessHost* child_process =
@@ -2784,20 +2904,21 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// Synchronize with the child and parent renderers to guarantee that the
// surface information required for event hit testing is ready.
- WaitForChildFrameSurfaceReady(root->child_at(0)->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(
+ root->child_at(0)->current_frame_host());
// There's no intrinsic reason the following values can't be equal, but they
// aren't at present, and if they become the same this test will need to be
// updated to accommodate.
EXPECT_NE(cc::kTouchActionAuto, cc::kTouchActionNone);
- // Verify the child's input router is initially set for kTouchActionAuto. The
- // TouchStart event will trigger kTouchActionNone being sent back to the
- // browser.
+ // Verify the child's input router is initially not set. The TouchStart event
+ // will trigger kTouchActionNone being sent back to the browser.
RenderWidgetHostImpl* child_render_widget_host =
root->child_at(0)->current_frame_host()->GetRenderWidgetHost();
- EXPECT_EQ(cc::kTouchActionAuto,
- child_render_widget_host->input_router()->AllowedTouchAction());
+ EXPECT_EQ(true, child_render_widget_host->input_router()
+ ->AllowedTouchAction()
+ .has_value());
InputEventAckWaiter waiter(child_render_widget_host,
blink::WebInputEvent::kTouchStart);
@@ -2866,14 +2987,14 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// updated to accommodate.
EXPECT_NE(cc::kTouchActionAuto, cc::kTouchActionNone);
- // Verify the main frame's input router is initially set for
- // kTouchActionAuto. The
+ // Verify the main frame's input router is initially not set. The
// TouchStart event will trigger kTouchActionNone being sent back to the
// browser.
RenderWidgetHostImpl* render_widget_host =
root->current_frame_host()->GetRenderWidgetHost();
- EXPECT_EQ(cc::kTouchActionAuto,
- render_widget_host->input_router()->AllowedTouchAction());
+ EXPECT_EQ(
+ true,
+ render_widget_host->input_router()->AllowedTouchAction().has_value());
// Simulate touch event to sub-frame.
gfx::Point frame_center(150, 150);
@@ -2941,7 +3062,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// Synchronize with the child and parent renderers to guarantee that the
// surface information required for event hit testing is ready.
- WaitForChildFrameSurfaceReady(child_frame_host);
+ WaitForHitTestDataOrChildSurfaceReady(child_frame_host);
// There have been no GestureTaps sent yet.
{
@@ -3130,6 +3251,7 @@ void SendTouchpadPinchSequenceWithExpectedTarget(
ui::GestureEventDetails pinch_update_details(ui::ET_GESTURE_PINCH_UPDATE);
pinch_update_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+ pinch_update_details.set_scale(1.23);
ui::GestureEvent pinch_update(gesture_point.x(), gesture_point.y(), 0,
ui::EventTimeForNow(), pinch_update_details);
UpdateEventRootLocation(&pinch_update, root_view_aura);
@@ -3146,9 +3268,9 @@ void SendTouchpadPinchSequenceWithExpectedTarget(
ui::EventTimeForNow(), pinch_end_details);
UpdateEventRootLocation(&pinch_end, root_view_aura);
root_view_aura->OnGestureEvent(&pinch_end);
- EXPECT_EQ(expected_target, router_touchpad_gesture_target);
EXPECT_TRUE(target_monitor.EventWasReceived());
EXPECT_EQ(target_monitor.EventType(), blink::WebInputEvent::kGesturePinchEnd);
+ EXPECT_EQ(nullptr, router_touchpad_gesture_target);
}
#if !defined(OS_WIN)
@@ -3156,22 +3278,14 @@ void SendTouchpadPinchSequenceWithExpectedTarget(
void SendTouchpadFlingSequenceWithExpectedTarget(
RenderWidgetHostViewBase* root_view,
const gfx::Point& gesture_point,
- RenderWidgetHostViewBase*& router_touchpad_gesture_target,
+ RenderWidgetHostViewBase*& router_wheel_target,
RenderWidgetHostViewBase* expected_target) {
auto* root_view_aura = static_cast<RenderWidgetHostViewAura*>(root_view);
- if (root_view_aura->wheel_scroll_latching_enabled()) {
- // Touchpad Fling must be sent inside a gesture scroll seqeunce.
- blink::WebGestureEvent gesture_event(
- blink::WebGestureEvent::kGestureScrollBegin,
- blink::WebInputEvent::kNoModifiers,
- blink::WebInputEvent::GetStaticTimeStampForTests(),
- blink::kWebGestureDeviceTouchpad);
- gesture_event.SetPositionInWidget(gfx::PointF(gesture_point));
- gesture_event.data.scroll_begin.delta_x_hint = 0.0f;
- gesture_event.data.scroll_begin.delta_y_hint = 1.0f;
- expected_target->GetRenderWidgetHost()->ForwardGestureEvent(gesture_event);
- }
+ ui::ScrollEvent scroll_begin(ui::ET_SCROLL, gesture_point,
+ ui::EventTimeForNow(), 0, 1, 0, 1, 0, 2);
+ UpdateEventRootLocation(&scroll_begin, root_view_aura);
+ root_view_aura->OnScrollEvent(&scroll_begin);
ui::ScrollEvent fling_start(ui::ET_SCROLL_FLING_START, gesture_point,
ui::EventTimeForNow(), 0, 1, 0, 1, 0, 1);
@@ -3189,7 +3303,7 @@ void SendTouchpadFlingSequenceWithExpectedTarget(
EXPECT_FALSE(target_monitor.EventWasReceived());
fling_start_waiter.Wait();
EXPECT_TRUE(target_monitor.EventWasReceived());
- EXPECT_EQ(expected_target, router_touchpad_gesture_target);
+ EXPECT_EQ(expected_target, router_wheel_target);
target_monitor.ResetEventsReceived();
// Send a GFC event, the fling_controller will process the GFC and stop the
@@ -3198,15 +3312,15 @@ void SendTouchpadFlingSequenceWithExpectedTarget(
InputEventAckWaiter gestrue_scroll_end_waiter(
expected_target->GetRenderWidgetHost(),
blink::WebInputEvent::kGestureScrollEnd);
+ InputEventAckWaiter fling_cancel_waiter(
+ expected_target->GetRenderWidgetHost(),
+ blink::WebInputEvent::kGestureFlingCancel);
ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL, gesture_point,
ui::EventTimeForNow(), 0, 1, 0, 1, 0, 1);
UpdateEventRootLocation(&fling_cancel, root_view_aura);
root_view_aura->OnScrollEvent(&fling_cancel);
- EXPECT_EQ(expected_target, router_touchpad_gesture_target);
- EXPECT_TRUE(target_monitor.EventWasReceived());
- EXPECT_EQ(target_monitor.EventType(),
- blink::WebInputEvent::kGestureFlingCancel);
gestrue_scroll_end_waiter.Wait();
+ fling_cancel_waiter.Wait();
}
#endif // !defined(OS_WIN)
@@ -3239,7 +3353,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// Synchronize with the child and parent renderers to guarantee that the
// surface information required for event hit testing is ready.
- WaitForChildFrameSurfaceReady(child_frame_host);
+ WaitForHitTestDataOrChildSurfaceReady(child_frame_host);
// All touches & gestures are sent to the main frame's view, and should be
// routed appropriately from there.
@@ -3335,7 +3449,7 @@ IN_PROC_BROWSER_TEST_P(
// Synchronize with the child and parent renderers to guarantee that the
// surface information required for event hit testing is ready.
- WaitForChildFrameSurfaceReady(child_frame_host);
+ WaitForHitTestDataOrChildSurfaceReady(child_frame_host);
// All touches & gestures are sent to the main frame's view, and should be
// routed appropriately from there.
@@ -3419,7 +3533,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// surface information required for event hit testing is ready.
auto* rwhv_child =
static_cast<RenderWidgetHostViewBase*>(child_frame_host->GetView());
- WaitForChildFrameSurfaceReady(child_frame_host);
+ WaitForHitTestDataOrChildSurfaceReady(child_frame_host);
// All touches & gestures are sent to the main frame's view, and should be
// routed appropriately from there.
@@ -3429,6 +3543,29 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
RenderWidgetHostInputEventRouter* router = contents->GetInputEventRouter();
EXPECT_EQ(nullptr, router->touchpad_gesture_target_.target);
+ // TODO(848050): If we send multiple touchpad pinch sequences to separate
+ // views and the timing of the acks are such that the begin ack of the second
+ // sequence arrives in the root before the end ack of the first sequence, we
+ // would produce an invalid gesture event sequence. For now, we wait for the
+ // root to receive the end ack before sending a pinch sequence to a different
+ // view. The root view should preserve validity of input event sequences
+ // when processing acks from multiple views, so that waiting here is not
+ // necessary.
+ auto wait_for_pinch_sequence_end = base::BindRepeating(
+ [](RenderWidgetHost* rwh) {
+ InputEventAckWaiter pinch_end_observer(
+ rwh, base::BindRepeating([](content::InputEventAckSource,
+ content::InputEventAckState,
+ const blink::WebInputEvent& event) {
+ return event.GetType() ==
+ blink::WebGestureEvent::kGesturePinchEnd &&
+ !static_cast<const blink::WebGestureEvent&>(event)
+ .NeedsWheelEvent();
+ }));
+ pinch_end_observer.Wait();
+ },
+ rwhv_parent->GetRenderWidgetHost());
+
gfx::Point main_frame_point(25, 25);
gfx::Point child_center(150, 150);
@@ -3437,11 +3574,15 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
rwhv_parent, main_frame_point, router->touchpad_gesture_target_.target,
rwhv_parent);
+ wait_for_pinch_sequence_end.Run();
+
// Send touchpad pinch sequence to child.
SendTouchpadPinchSequenceWithExpectedTarget(
rwhv_parent, child_center, router->touchpad_gesture_target_.target,
rwhv_child);
+ wait_for_pinch_sequence_end.Run();
+
// Send another touchpad pinch sequence to main frame.
SendTouchpadPinchSequenceWithExpectedTarget(
rwhv_parent, main_frame_point, router->touchpad_gesture_target_.target,
@@ -3452,20 +3593,79 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// Send touchpad fling sequence to main-frame.
SendTouchpadFlingSequenceWithExpectedTarget(
- rwhv_parent, main_frame_point, router->touchpad_gesture_target_.target,
- rwhv_parent);
+ rwhv_parent, main_frame_point, router->wheel_target_.target, rwhv_parent);
// Send touchpad fling sequence to child.
SendTouchpadFlingSequenceWithExpectedTarget(
- rwhv_parent, child_center, router->touchpad_gesture_target_.target,
- rwhv_child);
+ rwhv_parent, child_center, router->wheel_target_.target, rwhv_child);
// Send another touchpad fling sequence to main frame.
SendTouchpadFlingSequenceWithExpectedTarget(
- rwhv_parent, main_frame_point, router->touchpad_gesture_target_.target,
- rwhv_parent);
+ rwhv_parent, main_frame_point, router->wheel_target_.target, rwhv_parent);
#endif
}
+
+// Test that performing a touchpad pinch over an OOPIF offers the synthetic
+// wheel events to the child and causes the page scale factor to change for
+// the main frame (given that the child did not consume the wheel).
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
+ TouchpadPinchOverOOPIF) {
+ // TODO(crbug.com/853761): Flaky with viz hit testing
+ if (features::IsVizHitTestingEnabled()) {
+ LOG(INFO) << "Skipping test due to https://crbug.com/853761";
+ return;
+ }
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_frame.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ RenderFrameSubmissionObserver render_frame_submission_observer(
+ shell()->web_contents());
+
+ WebContentsImpl* contents = web_contents();
+ FrameTreeNode* root = contents->GetFrameTree()->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ GURL frame_url(
+ embedded_test_server()->GetURL("b.com", "/page_with_wheel_handler.html"));
+ NavigateFrameToURL(root->child_at(0), frame_url);
+ auto* child_frame_host = root->child_at(0)->current_frame_host();
+
+ auto* rwhv_child =
+ static_cast<RenderWidgetHostViewBase*>(child_frame_host->GetView());
+ WaitForHitTestDataOrChildSurfaceReady(child_frame_host);
+
+ auto* rwhv_parent = static_cast<RenderWidgetHostViewBase*>(
+ contents->GetRenderWidgetHostView());
+
+ RenderWidgetHostInputEventRouter* router = contents->GetInputEventRouter();
+ EXPECT_EQ(nullptr, router->touchpad_gesture_target_.target);
+
+ const float scale_factor =
+ render_frame_submission_observer.LastRenderFrameMetadata()
+ .page_scale_factor;
+ const gfx::Point point_in_child(gfx::ToCeiledInt(100 * scale_factor),
+ gfx::ToCeiledInt(100 * scale_factor));
+
+ content::TestPageScaleObserver scale_observer(shell()->web_contents());
+ SendTouchpadPinchSequenceWithExpectedTarget(
+ rwhv_parent, point_in_child, router->touchpad_gesture_target_.target,
+ rwhv_child);
+
+ // Ensure the child frame saw the wheel event.
+ bool default_prevented = false;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ child_frame_host,
+ "handlerPromise.then(function(e) {"
+ " window.domAutomationController.send(e.defaultPrevented);"
+ "});",
+ &default_prevented));
+ EXPECT_FALSE(default_prevented);
+
+ scale_observer.WaitForPageScaleUpdate();
+}
+
#endif // defined(USE_AURA)
// A WebContentsDelegate to capture ContextMenu creation events.
@@ -3511,6 +3711,9 @@ void CreateContextMenuTestHelper(
"/frame_tree/page_with_positioned_frame.html"));
EXPECT_TRUE(NavigateToURL(shell, main_url));
+ RenderFrameSubmissionObserver render_frame_submission_observer(
+ shell->web_contents());
+
// 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()
@@ -3531,7 +3734,7 @@ void CreateContextMenuTestHelper(
// 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.
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
// A WebContentsDelegate to listen for the ShowContextMenu message.
ContextMenuObserverDelegate context_menu_delegate;
@@ -3541,7 +3744,9 @@ void CreateContextMenuTestHelper(
static_cast<WebContentsImpl*>(shell->web_contents())
->GetInputEventRouter();
- float scale_factor = GetPageScaleFactor(shell);
+ float scale_factor =
+ render_frame_submission_observer.LastRenderFrameMetadata()
+ .page_scale_factor;
gfx::Rect root_bounds = root_view->GetViewBounds();
gfx::Rect bounds = rwhv_child->GetViewBounds();
@@ -3572,9 +3777,10 @@ void CreateContextMenuTestHelper(
EXPECT_NEAR(point.y(), params.y, 2);
}
-#if defined(OS_ANDROID) || defined(OS_WIN)
+#if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_LINUX)
// High DPI tests don't work properly on Android, which has fixed scale factor.
// Windows is disabled because of https://crbug.com/545547.
+// The test is flaky on Linux: https://crbug.com/833380.
#define MAYBE_CreateContextMenuTest DISABLED_CreateContextMenuTest
#elif defined(THREAD_SANITIZER)
// TSAN is flaky on both standard and High DPI: https://crbug.com/833380
@@ -3617,7 +3823,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, PopupMenuTest) {
web_contents()->SendScreenRects();
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
@@ -3948,7 +4154,7 @@ class SitePerProcessGestureHitTestBrowserTest
rwhva_root_ = static_cast<RenderWidgetHostViewAura*>(
shell()->web_contents()->GetRenderWidgetHostView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
rwhi_child_ = child_node->current_frame_host()->GetRenderWidgetHost();
rwhi_root_ = root_node->current_frame_host()->GetRenderWidgetHost();
@@ -4069,7 +4275,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessGestureHitTestBrowserTest,
rwhva_root_ = static_cast<RenderWidgetHostViewAura*>(
shell()->web_contents()->GetRenderWidgetHostView());
- WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
MainThreadFrameObserver observer(rwhv_child_->GetRenderWidgetHost());
observer.Wait();
@@ -4204,7 +4410,8 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, HitTestNestedFrames) {
->GetRenderWidgetHost()
->GetView());
- WaitForChildFrameSurfaceReady(grandchild_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(grandchild_node->current_frame_host());
// Create two points to hit test: One in the child of the main frame, and
// one in the frame nested within that. The hit test request is sent to the
@@ -4285,11 +4492,6 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */,
SitePerProcessMouseWheelHitTestBrowserTest,
testing::Combine(testing::ValuesIn(kHitTestOption),
testing::ValuesIn(kOneScale)));
-INSTANTIATE_TEST_CASE_P(
- /* no prefix */,
- SitePerProcessMouseWheelHitTestBrowserTestWheelScrollLatchingDisabled,
- testing::Combine(testing::ValuesIn(kHitTestOption),
- testing::ValuesIn(kOneScale)));
INSTANTIATE_TEST_CASE_P(/* no prefix */,
SitePerProcessGestureHitTestBrowserTest,
testing::Combine(testing::ValuesIn(kHitTestOption),
diff --git a/chromium/content/browser/site_per_process_mac_browsertest.mm b/chromium/content/browser/site_per_process_mac_browsertest.mm
index dc16103b3aa..ca814f4d223 100644
--- a/chromium/content/browser/site_per_process_mac_browsertest.mm
+++ b/chromium/content/browser/site_per_process_mac_browsertest.mm
@@ -12,6 +12,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#import "third_party/ocmock/OCMock/OCMock.h"
@@ -190,28 +191,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessMacBrowserTest,
scroll_event.momentum_phase = blink::WebMouseWheelEvent::kPhaseNone;
child_rwhv->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- // If wheel scroll latching is enabled, no wheel event with phase ended will
- // be sent before a wheel event with momentum phase began. So, no
- // GestureScrollEnd and no GestureScrollBegin will be generated between
- // normal scroll and momentum scroll phases.
- if (!child_rwhv->wheel_scroll_latching_enabled()) {
- // End of non-momentum scrolling.
- scroll_event.delta_y = 0.0f;
- scroll_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
- scroll_event.momentum_phase = blink::WebMouseWheelEvent::kPhaseNone;
- child_rwhv->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- gesture_scroll_end_ack_observer.Wait();
- gesture_scroll_begin_ack_observer.Reset();
- gesture_scroll_end_ack_observer.Reset();
- }
-
// We now go into a fling.
scroll_event.delta_y = -2.0f;
scroll_event.phase = blink::WebMouseWheelEvent::kPhaseNone;
scroll_event.momentum_phase = blink::WebMouseWheelEvent::kPhaseBegan;
child_rwhv->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- if (!child_rwhv->wheel_scroll_latching_enabled())
- gesture_scroll_begin_ack_observer.Wait();
scroll_event.delta_y = -2.0f;
scroll_event.phase = blink::WebMouseWheelEvent::kPhaseNone;
@@ -294,7 +278,7 @@ void SendMacTouchpadPinchSequenceWithExpectedTarget(
[cocoa_view magnifyWithEvent:pinchEndEvent];
if (ShouldSendGestureEvents())
[cocoa_view endGestureWithEvent:pinchEndEvent];
- EXPECT_EQ(expected_target, router_touchpad_gesture_target);
+ EXPECT_EQ(nullptr, router_touchpad_gesture_target);
}
} // namespace
@@ -318,7 +302,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessMacBrowserTest,
// surface information required for event hit testing is ready.
auto* rwhv_child =
static_cast<RenderWidgetHostViewBase*>(child_frame_host->GetView());
- WaitForChildFrameSurfaceReady(child_frame_host);
+ WaitForHitTestDataOrChildSurfaceReady(child_frame_host);
// All touches & gestures are sent to the main frame's view, and should be
// routed appropriately from there.
diff --git a/chromium/content/browser/snapshot_browsertest.cc b/chromium/content/browser/snapshot_browsertest.cc
index 2145e19369f..8577567de1c 100644
--- a/chromium/content/browser/snapshot_browsertest.cc
+++ b/chromium/content/browser/snapshot_browsertest.cc
@@ -76,12 +76,8 @@ class SnapshotBrowserTest : public ContentBrowserTest {
return static_cast<content::WebContentsImpl*>(browser->web_contents());
}
- content::RenderViewHostImpl* GetRenderViewHostImpl(Shell* browser) {
- return GetWebContents(browser)->GetRenderViewHost();
- }
-
content::RenderWidgetHostImpl* GetRenderWidgetHostImpl(Shell* browser) {
- return GetRenderViewHostImpl(browser)->GetWidget();
+ return GetWebContents(browser)->GetRenderViewHost()->GetWidget();
}
void SetupTestServer() {
@@ -230,8 +226,8 @@ IN_PROC_BROWSER_TEST_F(SnapshotBrowserTest, SingleWindowTest) {
"#%02x%02x%02x", expected.color.r, expected.color.g, expected.color.b);
std::string script = std::string("fillWithColor(\"") + colorString + "\");";
std::string result;
- EXPECT_TRUE(content::ExecuteScriptAndExtractString(
- GetRenderViewHostImpl(shell()), script, &result));
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(GetWebContents(shell()),
+ script, &result));
EXPECT_EQ(result, colorString);
expected_snapshots_.push_back(expected);
@@ -256,8 +252,7 @@ IN_PROC_BROWSER_TEST_F(SnapshotBrowserTest, SingleWindowTest) {
// Linux Chromium OS ASAN LSAN Tests (1)
// Linux TSAN Tests
// See crbug.com/771119
-#if (defined(OS_WIN) && !defined(NDEBUG)) || \
- (defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER)) || \
+#if (defined(OS_WIN) && !defined(NDEBUG)) || (defined(OS_CHROMEOS)) || \
(defined(OS_LINUX) && defined(THREAD_SANITIZER))
#define MAYBE_SyncMultiWindowTest DISABLED_SyncMultiWindowTest
#define MAYBE_AsyncMultiWindowTest DISABLED_AsyncMultiWindowTest
@@ -272,7 +267,7 @@ IN_PROC_BROWSER_TEST_F(SnapshotBrowserTest, MAYBE_SyncMultiWindowTest) {
for (int i = 0; i < 3; ++i) {
bool result = false;
EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
- GetRenderViewHostImpl(shell()), "openNewWindow()", &result));
+ GetWebContents(shell()), "openNewWindow()", &result));
EXPECT_TRUE(result);
}
@@ -283,7 +278,7 @@ IN_PROC_BROWSER_TEST_F(SnapshotBrowserTest, MAYBE_SyncMultiWindowTest) {
auto browser_list = Shell::windows();
EXPECT_EQ(4u, browser_list.size());
- for (int i = 0; i < 40; ++i) {
+ for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 4; j++) {
// Start each iteration by taking a snapshot with a different
// browser instance.
@@ -302,7 +297,7 @@ IN_PROC_BROWSER_TEST_F(SnapshotBrowserTest, MAYBE_SyncMultiWindowTest) {
std::string("fillWithColor(\"") + colorString + "\");";
std::string result;
EXPECT_TRUE(content::ExecuteScriptAndExtractString(
- GetRenderViewHostImpl(browser), script, &result));
+ GetWebContents(browser), script, &result));
EXPECT_EQ(result, colorString);
expected_snapshots_.push_back(expected);
// Get the snapshot from the surface rather than the window. The
@@ -327,7 +322,7 @@ IN_PROC_BROWSER_TEST_F(SnapshotBrowserTest, MAYBE_AsyncMultiWindowTest) {
for (int i = 0; i < 3; ++i) {
bool result = false;
EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
- GetRenderViewHostImpl(shell()), "openNewWindow()", &result));
+ GetWebContents(shell()), "openNewWindow()", &result));
EXPECT_TRUE(result);
}
@@ -345,7 +340,7 @@ IN_PROC_BROWSER_TEST_F(SnapshotBrowserTest, MAYBE_AsyncMultiWindowTest) {
// component type.
int divisor = 3;
- for (int i = 0; i < 20 * divisor; ++i) {
+ for (int i = 0; i < 10 * divisor; ++i) {
for (int j = 0; j < 4; j++) {
// Start each iteration by taking a snapshot with a different
// browser instance.
@@ -370,7 +365,7 @@ IN_PROC_BROWSER_TEST_F(SnapshotBrowserTest, MAYBE_AsyncMultiWindowTest) {
std::string("fillWithColor(\"") + colorString + "\");";
std::string result;
EXPECT_TRUE(content::ExecuteScriptAndExtractString(
- GetRenderViewHostImpl(browser), script, &result));
+ GetWebContents(browser), script, &result));
EXPECT_EQ(result, colorString);
// Get the snapshot from the surface rather than the window. The
// on-screen display path is verified by the GPU tests, and it
diff --git a/chromium/content/browser/speech/chunked_byte_buffer.cc b/chromium/content/browser/speech/chunked_byte_buffer.cc
index ae219c75800..5e3f70c45c6 100644
--- a/chromium/content/browser/speech/chunked_byte_buffer.cc
+++ b/chromium/content/browser/speech/chunked_byte_buffer.cc
@@ -89,7 +89,7 @@ void ChunkedByteBuffer::Append(const uint8_t* start, size_t length) {
total_bytes_stored_ += length;
}
-void ChunkedByteBuffer::Append(const std::string& string) {
+void ChunkedByteBuffer::Append(base::StringPiece string) {
Append(reinterpret_cast<const uint8_t*>(string.data()), string.size());
}
diff --git a/chromium/content/browser/speech/chunked_byte_buffer.h b/chromium/content/browser/speech/chunked_byte_buffer.h
index e6afe40e8cd..98bdd925f3f 100644
--- a/chromium/content/browser/speech/chunked_byte_buffer.h
+++ b/chromium/content/browser/speech/chunked_byte_buffer.h
@@ -13,6 +13,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
namespace content {
@@ -36,7 +37,7 @@ class CONTENT_EXPORT ChunkedByteBuffer {
void Append(const uint8_t* start, size_t length);
// Appends bytes contained in the |string| to the buffer.
- void Append(const std::string& string);
+ void Append(base::StringPiece string);
// Checks whether one or more complete chunks are available in the buffer.
bool HasChunks() const;
diff --git a/chromium/content/browser/speech/speech_recognition_browsertest.cc b/chromium/content/browser/speech/speech_recognition_browsertest.cc
index 90bf96296dc..3288ddad032 100644
--- a/chromium/content/browser/speech/speech_recognition_browsertest.cc
+++ b/chromium/content/browser/speech/speech_recognition_browsertest.cc
@@ -128,16 +128,18 @@ std::string MakeGoodResponse() {
proto::SpeechRecognitionEvent proto_event;
proto_event.set_status(proto::SpeechRecognitionEvent::STATUS_SUCCESS);
proto::SpeechRecognitionResult* proto_result = proto_event.add_result();
- SpeechRecognitionResult result;
- result.hypotheses.push_back(SpeechRecognitionHypothesis(
+ blink::mojom::SpeechRecognitionResultPtr result =
+ blink::mojom::SpeechRecognitionResult::New();
+ result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
base::UTF8ToUTF16("Pictures of the moon"), 1.0F));
- proto_result->set_final(!result.is_provisional);
- for (size_t i = 0; i < result.hypotheses.size(); ++i) {
+ proto_result->set_final(!result->is_provisional);
+ for (size_t i = 0; i < result->hypotheses.size(); ++i) {
proto::SpeechRecognitionAlternative* proto_alternative =
proto_result->add_alternative();
- const SpeechRecognitionHypothesis& hypothesis = result.hypotheses[i];
- proto_alternative->set_confidence(hypothesis.confidence);
- proto_alternative->set_transcript(base::UTF16ToUTF8(hypothesis.utterance));
+ const blink::mojom::SpeechRecognitionHypothesisPtr& hypothesis =
+ result->hypotheses[i];
+ proto_alternative->set_confidence(hypothesis->confidence);
+ proto_alternative->set_transcript(base::UTF16ToUTF8(hypothesis->utterance));
}
std::string msg_string;
diff --git a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
index 410717dee0f..4e8664ea9da 100644
--- a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
+++ b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
@@ -20,18 +20,18 @@
#include "content/public/browser/speech_recognition_manager_delegate.h"
#include "content/public/browser/speech_recognition_session_config.h"
#include "content/public/browser/speech_recognition_session_context.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_switches.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace content {
SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost(
int render_process_id,
- int render_frame_id,
- scoped_refptr<net::URLRequestContextGetter> context_getter)
+ int render_frame_id)
: render_process_id_(render_process_id),
render_frame_id_(render_frame_id),
- context_getter_(std::move(context_getter)),
weak_factory_(this) {
// Do not add any non-trivial initialization here, instead do it lazily when
// required (e.g. see the method |SpeechRecognitionManager::GetInstance()|) or
@@ -42,12 +42,10 @@ SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost(
void SpeechRecognitionDispatcherHost::Create(
int render_process_id,
int render_frame_id,
- scoped_refptr<net::URLRequestContextGetter> context_getter,
- mojom::SpeechRecognizerRequest request) {
- mojo::MakeStrongBinding(
- std::make_unique<SpeechRecognitionDispatcherHost>(
- render_process_id, render_frame_id, std::move(context_getter)),
- std::move(request));
+ blink::mojom::SpeechRecognizerRequest request) {
+ mojo::MakeStrongBinding(std::make_unique<SpeechRecognitionDispatcherHost>(
+ render_process_id, render_frame_id),
+ std::move(request));
}
SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() {}
@@ -57,10 +55,10 @@ SpeechRecognitionDispatcherHost::AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}
-// -------- mojom::SpeechRecognizer interface implementation ------------------
+// -------- blink::mojom::SpeechRecognizer interface implementation ------------
void SpeechRecognitionDispatcherHost::Start(
- mojom::StartSpeechRecognitionRequestParamsPtr params) {
+ blink::mojom::StartSpeechRecognitionRequestParamsPtr params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Check that the origin specified by the renderer process is one
@@ -86,7 +84,7 @@ void SpeechRecognitionDispatcherHost::StartRequestOnUI(
speech_recognition_dispatcher_host,
int render_process_id,
int render_frame_id,
- mojom::StartSpeechRecognitionRequestParamsPtr params) {
+ blink::mojom::StartSpeechRecognitionRequestParamsPtr params) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
int embedder_render_process_id = 0;
int embedder_render_frame_id = MSG_ROUTING_NONE;
@@ -133,19 +131,28 @@ void SpeechRecognitionDispatcherHost::StartRequestOnUI(
->delegate()
->FilterProfanities(embedder_render_process_id);
+ StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
+ web_contents->GetBrowserContext(), web_contents->GetSiteInstance());
+
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SpeechRecognitionDispatcherHost::StartSessionOnIO,
- speech_recognition_dispatcher_host, std::move(params),
- embedder_render_process_id, embedder_render_frame_id,
- filter_profanities));
+ base::BindOnce(
+ &SpeechRecognitionDispatcherHost::StartSessionOnIO,
+ speech_recognition_dispatcher_host, std::move(params),
+ embedder_render_process_id, embedder_render_frame_id,
+ filter_profanities,
+ storage_partition->GetURLLoaderFactoryForBrowserProcessIOThread(),
+ base::WrapRefCounted(storage_partition->GetURLRequestContext())));
}
void SpeechRecognitionDispatcherHost::StartSessionOnIO(
- mojom::StartSpeechRecognitionRequestParamsPtr params,
+ blink::mojom::StartSpeechRecognitionRequestParamsPtr params,
int embedder_render_process_id,
int embedder_render_frame_id,
- bool filter_profanities) {
+ bool filter_profanities,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ shared_url_loader_factory_info,
+ scoped_refptr<net::URLRequestContextGetter> deprecated_context_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
SpeechRecognitionSessionContext context;
@@ -163,13 +170,17 @@ void SpeechRecognitionDispatcherHost::StartSessionOnIO(
config.max_hypotheses = params->max_hypotheses;
config.origin = params->origin;
config.initial_context = context;
- config.url_request_context_getter = context_getter_.get();
+ config.shared_url_loader_factory = network::SharedURLLoaderFactory::Create(
+ std::move(shared_url_loader_factory_info));
+ config.deprecated_url_request_context_getter =
+ std::move(deprecated_context_getter);
config.filter_profanities = filter_profanities;
config.continuous = params->continuous;
config.interim_results = params->interim_results;
config.event_listener = session->AsWeakPtr();
- for (mojom::SpeechRecognitionGrammarPtr& grammar_ptr : params->grammars) {
+ for (blink::mojom::SpeechRecognitionGrammarPtr& grammar_ptr :
+ params->grammars) {
config.grammars.push_back(*grammar_ptr);
}
@@ -186,12 +197,18 @@ void SpeechRecognitionDispatcherHost::StartSessionOnIO(
// ---------------------- SpeechRecognizerSession -----------------------------
SpeechRecognitionSession::SpeechRecognitionSession(
- mojom::SpeechRecognitionSessionClientPtrInfo client_ptr_info)
+ blink::mojom::SpeechRecognitionSessionClientPtrInfo client_ptr_info)
: session_id_(SpeechRecognitionManager::kSessionIDInvalid),
client_(std::move(client_ptr_info)),
+ stopped_(false),
weak_factory_(this) {}
-SpeechRecognitionSession::~SpeechRecognitionSession() = default;
+SpeechRecognitionSession::~SpeechRecognitionSession() {
+ // If a connection error happens and the session hasn't been stopped yet,
+ // abort it.
+ if (!stopped_)
+ Abort();
+}
base::WeakPtr<SpeechRecognitionSession> SpeechRecognitionSession::AsWeakPtr() {
return weak_factory_.GetWeakPtr();
@@ -199,11 +216,13 @@ base::WeakPtr<SpeechRecognitionSession> SpeechRecognitionSession::AsWeakPtr() {
void SpeechRecognitionSession::Abort() {
SpeechRecognitionManager::GetInstance()->AbortSession(session_id_);
+ stopped_ = true;
}
void SpeechRecognitionSession::StopCapture() {
SpeechRecognitionManager::GetInstance()->StopAudioCaptureForSession(
session_id_);
+ stopped_ = true;
}
// -------- SpeechRecognitionEventListener interface implementation -----------
@@ -230,18 +249,20 @@ void SpeechRecognitionSession::OnAudioEnd(int session_id) {
void SpeechRecognitionSession::OnRecognitionEnd(int session_id) {
client_->Ended();
+ stopped_ = true;
+ client_.reset();
}
void SpeechRecognitionSession::OnRecognitionResults(
int session_id,
- const SpeechRecognitionResults& results) {
- client_->ResultRetrieved(results);
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& results) {
+ client_->ResultRetrieved(mojo::Clone(results));
}
void SpeechRecognitionSession::OnRecognitionError(
int session_id,
- const SpeechRecognitionError& error) {
- client_->ErrorOccurred(error);
+ const blink::mojom::SpeechRecognitionError& error) {
+ client_->ErrorOccurred(blink::mojom::SpeechRecognitionError::New(error));
}
// The events below are currently not used by speech JS APIs implementation.
diff --git a/chromium/content/browser/speech/speech_recognition_dispatcher_host.h b/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
index bce40c3ad6d..ffa9bd51448 100644
--- a/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
+++ b/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
@@ -10,12 +10,16 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
-#include "content/common/speech_recognizer.mojom.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/speech_recognition_event_listener.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/url_request/url_request_context_getter.h"
+#include "third_party/blink/public/mojom/speech/speech_recognizer.mojom.h"
+
+namespace network {
+class SharedURLLoaderFactoryInfo;
+}
namespace content {
@@ -26,21 +30,18 @@ class SpeechRecognitionManager;
// interface that allows a RenderFrame to start a speech recognition session
// in the browser process, by communicating with SpeechRecognitionManager.
class CONTENT_EXPORT SpeechRecognitionDispatcherHost
- : public mojom::SpeechRecognizer {
+ : public blink::mojom::SpeechRecognizer {
public:
- SpeechRecognitionDispatcherHost(
- int render_process_id,
- int render_frame_id,
- scoped_refptr<net::URLRequestContextGetter> context_getter);
+ SpeechRecognitionDispatcherHost(int render_process_id, int render_frame_id);
~SpeechRecognitionDispatcherHost() override;
static void Create(int render_process_id,
int render_frame_id,
- scoped_refptr<net::URLRequestContextGetter> context_getter,
- mojom::SpeechRecognizerRequest request);
+ blink::mojom::SpeechRecognizerRequest request);
base::WeakPtr<SpeechRecognitionDispatcherHost> AsWeakPtr();
- // mojom::SpeechRecognizer implementation
- void Start(mojom::StartSpeechRecognitionRequestParamsPtr params) override;
+ // blink::mojom::SpeechRecognizer implementation
+ void Start(
+ blink::mojom::StartSpeechRecognitionRequestParamsPtr params) override;
private:
static void StartRequestOnUI(
@@ -48,15 +49,18 @@ class CONTENT_EXPORT SpeechRecognitionDispatcherHost
speech_recognition_dispatcher_host,
int render_process_id,
int render_frame_id,
- mojom::StartSpeechRecognitionRequestParamsPtr params);
- void StartSessionOnIO(mojom::StartSpeechRecognitionRequestParamsPtr params,
- int embedder_render_process_id,
- int embedder_render_frame_id,
- bool filter_profanities);
+ blink::mojom::StartSpeechRecognitionRequestParamsPtr params);
+ void StartSessionOnIO(
+ blink::mojom::StartSpeechRecognitionRequestParamsPtr params,
+ int embedder_render_process_id,
+ int embedder_render_frame_id,
+ bool filter_profanities,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ shared_url_loader_factory_info,
+ scoped_refptr<net::URLRequestContextGetter> deprecated_context_getter);
const int render_process_id_;
const int render_frame_id_;
- scoped_refptr<net::URLRequestContextGetter> context_getter_;
// Used for posting asynchronous tasks (on the IO thread) without worrying
// about this class being destroyed in the meanwhile (due to browser shutdown)
@@ -66,21 +70,22 @@ class CONTENT_EXPORT SpeechRecognitionDispatcherHost
DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionDispatcherHost);
};
-// SpeechRecognitionSession implements the mojom::SpeechRecognitionSession
-// interface for a particular session. It also acts as a proxy for events sent
-// from SpeechRecognitionManager, and forwards the events to the renderer using
-// a SpeechRecognitionSessionClientPtr (that is passed from the render process).
-class SpeechRecognitionSession : public mojom::SpeechRecognitionSession,
+// SpeechRecognitionSession implements the
+// blink::mojom::SpeechRecognitionSession interface for a particular session. It
+// also acts as a proxy for events sent from SpeechRecognitionManager, and
+// forwards the events to the renderer using a SpeechRecognitionSessionClientPtr
+// (that is passed from the render process).
+class SpeechRecognitionSession : public blink::mojom::SpeechRecognitionSession,
public SpeechRecognitionEventListener {
public:
explicit SpeechRecognitionSession(
- mojom::SpeechRecognitionSessionClientPtrInfo client_ptr_info);
+ blink::mojom::SpeechRecognitionSessionClientPtrInfo client_ptr_info);
~SpeechRecognitionSession() override;
base::WeakPtr<SpeechRecognitionSession> AsWeakPtr();
void SetSessionId(int session_id) { session_id_ = session_id; }
- // mojom::SpeechRecognitionSession implementation.
+ // blink::mojom::SpeechRecognitionSession implementation.
void Abort() override;
void StopCapture() override;
@@ -92,17 +97,21 @@ class SpeechRecognitionSession : public mojom::SpeechRecognitionSession,
void OnSoundEnd(int session_id) override;
void OnAudioEnd(int session_id) override;
void OnRecognitionEnd(int session_id) override;
- void OnRecognitionResults(int session_id,
- const SpeechRecognitionResults& results) override;
- void OnRecognitionError(int session_id,
- const SpeechRecognitionError& error) override;
+ void OnRecognitionResults(
+ int session_id,
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& results)
+ override;
+ void OnRecognitionError(
+ int session_id,
+ const blink::mojom::SpeechRecognitionError& error) override;
void OnAudioLevelsChange(int session_id,
float volume,
float noise_volume) override;
private:
int session_id_;
- mojom::SpeechRecognitionSessionClientPtr client_;
+ blink::mojom::SpeechRecognitionSessionClientPtr client_;
+ bool stopped_;
base::WeakPtrFactory<SpeechRecognitionSession> weak_factory_;
};
diff --git a/chromium/content/browser/speech/speech_recognition_engine.cc b/chromium/content/browser/speech/speech_recognition_engine.cc
index e05de0f8484..275129d367e 100644
--- a/chromium/content/browser/speech/speech_recognition_engine.cc
+++ b/chromium/content/browser/speech/speech_recognition_engine.cc
@@ -16,9 +16,9 @@
#include "base/time/time.h"
#include "content/browser/speech/audio_buffer.h"
#include "content/browser/speech/proto/google_streaming_api.pb.h"
-#include "content/public/common/speech_recognition_error.h"
-#include "content/public/common/speech_recognition_result.h"
#include "google_apis/google_api_keys.h"
+#include "mojo/public/c/system/types.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
@@ -27,8 +27,11 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_status.h"
-
-using net::URLFetcher;
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h"
namespace content {
namespace {
@@ -44,6 +47,9 @@ const char* web_service_base_url_for_tests = nullptr;
// This matches the maximum maxAlternatives value supported by the server.
const uint32_t kMaxMaxAlternatives = 30;
+// Maximum amount of data written per Mojo write.
+const uint32_t kMaxUploadWrite = 128 * 1024;
+
// TODO(hans): Remove this and other logging when we don't need it anymore.
void DumpResponse(const std::string& response) {
DVLOG(1) << "------------";
@@ -80,6 +86,197 @@ const uint32_t kDefaultMaxHypotheses = 1;
} // namespace
+// Streams sound data up to the server.
+class SpeechRecognitionEngine::UpstreamLoader
+ : public network::mojom::ChunkedDataPipeGetter {
+ public:
+ UpstreamLoader(std::unique_ptr<network::ResourceRequest> resource_request,
+ net::NetworkTrafficAnnotationTag upstream_traffic_annotation,
+ network::mojom::URLLoaderFactory* url_loader_factory,
+ SpeechRecognitionEngine* speech_recognition_engine)
+ : speech_recognition_engine_(speech_recognition_engine) {
+ // Attach a chunked upload body.
+ network::mojom::ChunkedDataPipeGetterPtr data_pipe;
+ binding_set_.AddBinding(this, mojo::MakeRequest(&data_pipe));
+ resource_request->request_body = new network::ResourceRequestBody();
+ resource_request->request_body->SetToChunkedDataPipe(std::move(data_pipe));
+ simple_url_loader_ = network::SimpleURLLoader::Create(
+ std::move(resource_request), upstream_traffic_annotation);
+ simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+ url_loader_factory,
+ base::BindOnce(&UpstreamLoader::OnComplete, base::Unretained(this)));
+ }
+
+ ~UpstreamLoader() override = default;
+
+ void OnComplete(std::unique_ptr<std::string> response_body) {
+ int response_code = -1;
+ if (simple_url_loader_->ResponseInfo() &&
+ simple_url_loader_->ResponseInfo()->headers) {
+ response_code =
+ simple_url_loader_->ResponseInfo()->headers->response_code();
+ }
+ speech_recognition_engine_->OnUpstreamDataComplete(response_body != nullptr,
+ response_code);
+ }
+
+ void AppendChunkToUpload(const std::string& data, bool is_last_chunk) {
+ DCHECK(!has_last_chunk_);
+
+ upload_body_ += data;
+ if (is_last_chunk) {
+ // Send size before the rest of the body. While it doesn't matter much, if
+ // the other side receives the size before the last chunk, which Mojo does
+ // not gaurantee, some protocols can merge the data and the last chunk
+ // itself into a single frame.
+ has_last_chunk_ = is_last_chunk;
+ if (get_size_callback_)
+ std::move(get_size_callback_).Run(net::OK, upload_body_.size());
+ }
+
+ SendData();
+ }
+
+ private:
+ void OnUploadPipeWriteable(MojoResult unused) { SendData(); }
+
+ // Attempts to send more of the upload body, if more data is available, and
+ // |upload_pipe_| is valid.
+ void SendData() {
+ DCHECK_LE(upload_position_, upload_body_.size());
+
+ if (!upload_pipe_.is_valid())
+ return;
+
+ // Nothing more to write yet, or done writing everything.
+ if (upload_position_ == upload_body_.size())
+ return;
+
+ // Since kMaxUploadWrite is a uint32_t, no overflow occurs in this downcast.
+ uint32_t write_bytes = std::min(upload_body_.length() - upload_position_,
+ static_cast<size_t>(kMaxUploadWrite));
+ MojoResult result =
+ upload_pipe_->WriteData(upload_body_.data() + upload_position_,
+ &write_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+
+ // Wait for the pipe to have more capacity available, if needed.
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ upload_pipe_watcher_->ArmOrNotify();
+ return;
+ }
+
+ // Do nothing on pipe closure - depend on the SimpleURLLoader to notice the
+ // other pipes being closed on error. Can reach this point if there's a
+ // retry, for instance, so cannot draw any conclusions here.
+ if (result != MOJO_RESULT_OK)
+ return;
+
+ upload_position_ += write_bytes;
+ // If more data is available, arm the watcher again. Don't write again in a
+ // loop, even if WriteData would allow it, to avoid blocking the current
+ // thread.
+ if (upload_position_ < upload_body_.size())
+ upload_pipe_watcher_->ArmOrNotify();
+ }
+
+ // mojom::ChunkedDataPipeGetter implementation:
+
+ void GetSize(GetSizeCallback get_size_callback) override {
+ if (has_last_chunk_) {
+ std::move(get_size_callback).Run(net::OK, upload_body_.size());
+ } else {
+ get_size_callback_ = std::move(get_size_callback);
+ }
+ }
+
+ void StartReading(mojo::ScopedDataPipeProducerHandle pipe) override {
+ // Delete any existing pipe, if any.
+ upload_pipe_watcher_.reset();
+ upload_pipe_ = std::move(pipe);
+ upload_pipe_watcher_ = std::make_unique<mojo::SimpleWatcher>(
+ FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL);
+ upload_pipe_watcher_->Watch(
+ upload_pipe_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
+ base::BindRepeating(&UpstreamLoader::OnUploadPipeWriteable,
+ base::Unretained(this)));
+ upload_position_ = 0;
+
+ // Will attempt to start sending the request body, if any data is available.
+ SendData();
+ }
+
+ // Partial upload body. Have to cache the entire thing in memory, in case have
+ // to replay it.
+ std::string upload_body_;
+ // Current position in |upload_body_|. All bytes before this point have been
+ // written to |upload_pipe_|.
+ size_t upload_position_ = 0;
+ // Whether |upload_body_| is complete.
+ bool has_last_chunk_ = false;
+
+ // Current pipe being used to send the |upload_body_| to the URLLoader.
+ mojo::ScopedDataPipeProducerHandle upload_pipe_;
+ // Watches |upload_pipe_| for writeability.
+ std::unique_ptr<mojo::SimpleWatcher> upload_pipe_watcher_;
+
+ // If non-null, invoked once the size of the upload is known.
+ network::mojom::ChunkedDataPipeGetter::GetSizeCallback get_size_callback_;
+
+ SpeechRecognitionEngine* const speech_recognition_engine_;
+ std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
+ mojo::BindingSet<network::mojom::ChunkedDataPipeGetter> binding_set_;
+
+ DISALLOW_COPY_AND_ASSIGN(UpstreamLoader);
+};
+
+// Streams response data from the server to the SpeechRecognitionEngine.
+class SpeechRecognitionEngine::DownstreamLoader
+ : public network::SimpleURLLoaderStreamConsumer {
+ public:
+ DownstreamLoader(std::unique_ptr<network::ResourceRequest> resource_request,
+ net::NetworkTrafficAnnotationTag upstream_traffic_annotation,
+ network::mojom::URLLoaderFactory* url_loader_factory,
+ SpeechRecognitionEngine* speech_recognition_engine)
+ : speech_recognition_engine_(speech_recognition_engine) {
+ simple_url_loader_ = network::SimpleURLLoader::Create(
+ std::move(resource_request), upstream_traffic_annotation);
+ simple_url_loader_->DownloadAsStream(url_loader_factory, this);
+ }
+
+ ~DownstreamLoader() override = default;
+
+ // SimpleURLLoaderStreamConsumer implementation:
+
+ void OnDataReceived(base::StringPiece string_piece,
+ base::OnceClosure resume) override {
+ speech_recognition_engine_->OnDownstreamDataReceived(string_piece);
+ std::move(resume).Run();
+ }
+
+ void OnComplete(bool success) override {
+ int response_code = -1;
+ if (simple_url_loader_->ResponseInfo() &&
+ simple_url_loader_->ResponseInfo()->headers) {
+ response_code =
+ simple_url_loader_->ResponseInfo()->headers->response_code();
+ }
+
+ speech_recognition_engine_->OnDownstreamDataComplete(success,
+ response_code);
+ }
+
+ void OnRetry(base::OnceClosure start_retry) override {
+ // Retries are not enabled for these requests.
+ NOTREACHED();
+ }
+
+ private:
+ SpeechRecognitionEngine* const speech_recognition_engine_;
+ std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
+
+ DISALLOW_COPY_AND_ASSIGN(DownstreamLoader);
+};
+
SpeechRecognitionEngine::Config::Config()
: filter_profanities(false),
continuous(true),
@@ -91,15 +288,16 @@ SpeechRecognitionEngine::Config::Config()
SpeechRecognitionEngine::Config::~Config() {}
const int SpeechRecognitionEngine::kAudioPacketIntervalMs = 100;
-const int SpeechRecognitionEngine::kUpstreamUrlFetcherIdForTesting = 0;
-const int SpeechRecognitionEngine::kDownstreamUrlFetcherIdForTesting = 1;
const int SpeechRecognitionEngine::kWebserviceStatusNoError = 0;
const int SpeechRecognitionEngine::kWebserviceStatusErrorNoMatch = 5;
SpeechRecognitionEngine::SpeechRecognitionEngine(
- net::URLRequestContextGetter* context)
- : url_context_(context),
- previous_response_length_(0),
+ scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<net::URLRequestContextGetter>
+ deprecated_url_request_context_getter)
+ : shared_url_loader_factory_(std::move(shared_url_loader_factory)),
+ deprecated_url_request_context_getter_(
+ std::move(deprecated_url_request_context_getter)),
got_last_definitive_result_(false),
is_dispatching_event_(false),
use_framed_post_data_(false),
@@ -139,64 +337,27 @@ void SpeechRecognitionEngine::AudioChunksEnded() {
DispatchEvent(event_args);
}
-void SpeechRecognitionEngine::OnURLFetchComplete(const URLFetcher* source) {
- const bool kResponseComplete = true;
- DispatchHTTPResponse(source, kResponseComplete);
-}
-
-void SpeechRecognitionEngine::OnURLFetchDownloadProgress(
- const URLFetcher* source,
- int64_t current,
- int64_t total,
- int64_t current_network_bytes) {
- const bool kPartialResponse = false;
- DispatchHTTPResponse(source, kPartialResponse);
-}
-
-void SpeechRecognitionEngine::DispatchHTTPResponse(const URLFetcher* source,
- bool end_of_response) {
+void SpeechRecognitionEngine::OnUpstreamDataComplete(bool success,
+ int response_code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(source);
- const bool response_is_good = source->GetStatus().is_success() &&
- source->GetResponseCode() == 200;
- std::string response;
- if (response_is_good)
- source->GetResponseAsString(&response);
- const size_t current_response_length = response.size();
-
- DVLOG(1) << (source == downstream_fetcher_.get() ? "Downstream" : "Upstream")
- << "HTTP, code: " << source->GetResponseCode()
- << " length: " << current_response_length
- << " eor: " << end_of_response;
-
- // URLFetcher provides always the entire response buffer, but we are only
- // interested in the fresh data introduced by the last chunk. Therefore, we
- // drop the previous content we have already processed.
- if (current_response_length != 0) {
- DCHECK_GE(current_response_length, previous_response_length_);
- response.erase(0, previous_response_length_);
- previous_response_length_ = current_response_length;
- }
- if (!response_is_good && source == downstream_fetcher_.get()) {
- DVLOG(1) << "Downstream error " << source->GetResponseCode();
- FSMEventArgs event_args(EVENT_DOWNSTREAM_ERROR);
- DispatchEvent(event_args);
- return;
- }
- if (!response_is_good && source == upstream_fetcher_.get()) {
- DVLOG(1) << "Upstream error " << source->GetResponseCode()
- << " EOR " << end_of_response;
+ DVLOG(1) << "Upstream complete success: " << success
+ << " response_code: " << response_code;
+
+ if (!success) {
FSMEventArgs event_args(EVENT_UPSTREAM_ERROR);
DispatchEvent(event_args);
return;
}
- // Ignore incoming data on the upstream connection.
- if (source == upstream_fetcher_.get())
- return;
+ // Do nothing on clean completion of upstream request.
+}
- DCHECK(response_is_good && source == downstream_fetcher_.get());
+void SpeechRecognitionEngine::OnDownstreamDataReceived(
+ base::StringPiece new_response_data) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ DVLOG(1) << "Downstream length: " << new_response_data.size();
// The downstream response is organized in chunks, whose size is determined
// by a 4 bytes prefix, transparently handled by the ChunkedByteBuffer class.
@@ -206,7 +367,7 @@ void SpeechRecognitionEngine::DispatchHTTPResponse(const URLFetcher* source,
// url fetcher. However there isn't any particular matching beween our
// protocol chunks and HTTP chunks, in the sense that a single HTTP chunk can
// contain a portion of one chunk or even more chunks together.
- chunked_byte_buffer_.Append(response);
+ chunked_byte_buffer_.Append(new_response_data);
// A single HTTP chunk can contain more than one data chunk, thus the while.
while (chunked_byte_buffer_.HasChunks()) {
@@ -217,10 +378,23 @@ void SpeechRecognitionEngine::DispatchHTTPResponse(const URLFetcher* source,
event_args.response->end()));
DispatchEvent(event_args);
}
- if (end_of_response) {
- FSMEventArgs event_args(EVENT_DOWNSTREAM_CLOSED);
+}
+
+void SpeechRecognitionEngine::OnDownstreamDataComplete(bool success,
+ int response_code) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ DVLOG(1) << "Downstream complete success: " << success
+ << " response_code: " << response_code;
+
+ if (!success) {
+ FSMEventArgs event_args(EVENT_DOWNSTREAM_ERROR);
DispatchEvent(event_args);
+ return;
}
+
+ FSMEventArgs event_args(EVENT_DOWNSTREAM_CLOSED);
+ DispatchEvent(event_args);
}
bool SpeechRecognitionEngine::IsRecognitionPending() const {
@@ -319,8 +493,8 @@ SpeechRecognitionEngine::ExecuteTransitionAndGetNextState(
SpeechRecognitionEngine::FSMState
SpeechRecognitionEngine::ConnectBothStreams(const FSMEventArgs&) {
- DCHECK(!upstream_fetcher_.get());
- DCHECK(!downstream_fetcher_.get());
+ DCHECK(!upstream_loader_.get());
+ DCHECK(!downstream_loader_.get());
encoder_.reset(new AudioEncoder(config_.audio_sample_rate,
config_.audio_num_bits_per_sample));
@@ -391,14 +565,14 @@ SpeechRecognitionEngine::ConnectBothStreams(const FSMEventArgs&) {
}
}
})");
- downstream_fetcher_ =
- URLFetcher::Create(kDownstreamUrlFetcherIdForTesting, downstream_url,
- URLFetcher::GET, this, downstream_traffic_annotation);
- downstream_fetcher_->SetRequestContext(url_context_.get());
- downstream_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DO_NOT_SEND_AUTH_DATA);
- downstream_fetcher_->Start();
+ auto downstream_request = std::make_unique<network::ResourceRequest>();
+ downstream_request->load_flags = net::LOAD_DO_NOT_SAVE_COOKIES |
+ net::LOAD_DO_NOT_SEND_COOKIES |
+ net::LOAD_DO_NOT_SEND_AUTH_DATA;
+ downstream_request->url = downstream_url;
+ downstream_loader_ = std::make_unique<DownstreamLoader>(
+ std::move(downstream_request), downstream_traffic_annotation,
+ shared_url_loader_factory_.get(), this);
// Setup upstream fetcher.
// TODO(hans): Support for user-selected grammars.
@@ -418,7 +592,8 @@ SpeechRecognitionEngine::ConnectBothStreams(const FSMEventArgs&) {
base::UintToString(max_alternatives));
}
upstream_args.push_back("app=chromium");
- for (const mojom::SpeechRecognitionGrammar& grammar : config_.grammars) {
+ for (const blink::mojom::SpeechRecognitionGrammar& grammar :
+ config_.grammars) {
std::string grammar_value(base::NumberToString(grammar.weight) + ":" +
grammar.url.spec());
upstream_args.push_back(
@@ -486,20 +661,25 @@ SpeechRecognitionEngine::ConnectBothStreams(const FSMEventArgs&) {
}
}
})");
- upstream_fetcher_ =
- URLFetcher::Create(kUpstreamUrlFetcherIdForTesting, upstream_url,
- URLFetcher::POST, this, upstream_traffic_annotation);
- if (use_framed_post_data_)
- upstream_fetcher_->SetChunkedUpload("application/octet-stream");
- else
- upstream_fetcher_->SetChunkedUpload(encoder_->GetMimeType());
- upstream_fetcher_->SetRequestContext(url_context_.get());
- upstream_fetcher_->SetReferrer(config_.origin_url);
- upstream_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DO_NOT_SEND_AUTH_DATA);
- upstream_fetcher_->Start();
- previous_response_length_ = 0;
+
+ auto upstream_request = std::make_unique<network::ResourceRequest>();
+ upstream_request->url = upstream_url;
+ upstream_request->method = "POST";
+ upstream_request->referrer = GURL(config_.origin_url);
+ upstream_request->load_flags = net::LOAD_DO_NOT_SAVE_COOKIES |
+ net::LOAD_DO_NOT_SEND_COOKIES |
+ net::LOAD_DO_NOT_SEND_AUTH_DATA;
+ if (use_framed_post_data_) {
+ upstream_request->headers.SetHeader(net::HttpRequestHeaders::kContentType,
+ "application/octet-stream");
+ } else {
+ upstream_request->headers.SetHeader(net::HttpRequestHeaders::kContentType,
+ encoder_->GetMimeType());
+ }
+
+ upstream_loader_ = std::make_unique<UpstreamLoader>(
+ std::move(upstream_request), upstream_traffic_annotation,
+ shared_url_loader_factory_.get(), this);
if (preamble_encoder_) {
// Encode and send preamble right away.
@@ -518,7 +698,7 @@ SpeechRecognitionEngine::ConnectBothStreams(const FSMEventArgs&) {
SpeechRecognitionEngine::FSMState
SpeechRecognitionEngine::TransmitAudioUpstream(
const FSMEventArgs& event_args) {
- DCHECK(upstream_fetcher_.get());
+ DCHECK(upstream_loader_.get());
DCHECK(event_args.audio_data.get());
const AudioChunk& audio = *(event_args.audio_data.get());
@@ -544,21 +724,23 @@ SpeechRecognitionEngine::ProcessDownstreamResponse(
case proto::SpeechRecognitionEvent::STATUS_SUCCESS:
break;
case proto::SpeechRecognitionEvent::STATUS_NO_SPEECH:
- return Abort(SPEECH_RECOGNITION_ERROR_NO_SPEECH);
+ return Abort(blink::mojom::SpeechRecognitionErrorCode::kNoSpeech);
case proto::SpeechRecognitionEvent::STATUS_ABORTED:
- return Abort(SPEECH_RECOGNITION_ERROR_ABORTED);
+ return Abort(blink::mojom::SpeechRecognitionErrorCode::kAborted);
case proto::SpeechRecognitionEvent::STATUS_AUDIO_CAPTURE:
- return Abort(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE);
+ return Abort(blink::mojom::SpeechRecognitionErrorCode::kAudioCapture);
case proto::SpeechRecognitionEvent::STATUS_NETWORK:
- return Abort(SPEECH_RECOGNITION_ERROR_NETWORK);
+ return Abort(blink::mojom::SpeechRecognitionErrorCode::kNetwork);
case proto::SpeechRecognitionEvent::STATUS_NOT_ALLOWED:
- return Abort(SPEECH_RECOGNITION_ERROR_NOT_ALLOWED);
+ return Abort(blink::mojom::SpeechRecognitionErrorCode::kNotAllowed);
case proto::SpeechRecognitionEvent::STATUS_SERVICE_NOT_ALLOWED:
- return Abort(SPEECH_RECOGNITION_ERROR_SERVICE_NOT_ALLOWED);
+ return Abort(
+ blink::mojom::SpeechRecognitionErrorCode::kServiceNotAllowed);
case proto::SpeechRecognitionEvent::STATUS_BAD_GRAMMAR:
- return Abort(SPEECH_RECOGNITION_ERROR_BAD_GRAMMAR);
+ return Abort(blink::mojom::SpeechRecognitionErrorCode::kBadGrammar);
case proto::SpeechRecognitionEvent::STATUS_LANGUAGE_NOT_SUPPORTED:
- return Abort(SPEECH_RECOGNITION_ERROR_LANGUAGE_NOT_SUPPORTED);
+ return Abort(
+ blink::mojom::SpeechRecognitionErrorCode::kLanguageNotSupported);
}
}
@@ -567,30 +749,31 @@ SpeechRecognitionEngine::ProcessDownstreamResponse(
delegate_->OnSpeechRecognitionEngineEndOfUtterance();
}
- SpeechRecognitionResults results;
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results;
for (int i = 0; i < ws_event.result_size(); ++i) {
const proto::SpeechRecognitionResult& ws_result = ws_event.result(i);
- results.push_back(SpeechRecognitionResult());
- SpeechRecognitionResult& result = results.back();
- result.is_provisional = !(ws_result.has_final() && ws_result.final());
+ results.push_back(blink::mojom::SpeechRecognitionResult::New());
+ blink::mojom::SpeechRecognitionResultPtr& result = results.back();
+ result->is_provisional = !(ws_result.has_final() && ws_result.final());
- if (!result.is_provisional)
+ if (!result->is_provisional)
got_last_definitive_result_ = true;
for (int j = 0; j < ws_result.alternative_size(); ++j) {
const proto::SpeechRecognitionAlternative& ws_alternative =
ws_result.alternative(j);
- SpeechRecognitionHypothesis hypothesis;
+ blink::mojom::SpeechRecognitionHypothesisPtr hypothesis =
+ blink::mojom::SpeechRecognitionHypothesis::New();
if (ws_alternative.has_confidence())
- hypothesis.confidence = ws_alternative.confidence();
+ hypothesis->confidence = ws_alternative.confidence();
else if (ws_result.has_stability())
- hypothesis.confidence = ws_result.stability();
+ hypothesis->confidence = ws_result.stability();
DCHECK(ws_alternative.has_transcript());
// TODO(hans): Perhaps the transcript should be required in the proto?
if (ws_alternative.has_transcript())
- hypothesis.utterance = base::UTF8ToUTF16(ws_alternative.transcript());
+ hypothesis->utterance = base::UTF8ToUTF16(ws_alternative.transcript());
- result.hypotheses.push_back(hypothesis);
+ result->hypotheses.push_back(std::move(hypothesis));
}
}
if (results.size()) {
@@ -606,7 +789,8 @@ SpeechRecognitionEngine::RaiseNoMatchErrorIfGotNoResults(
if (!got_last_definitive_result_) {
// Provide an empty result to notify that recognition is ended with no
// errors, yet neither any further results.
- delegate_->OnSpeechRecognitionEngineResults(SpeechRecognitionResults());
+ delegate_->OnSpeechRecognitionEngineResults(
+ std::vector<blink::mojom::SpeechRecognitionResultPtr>());
}
return AbortSilently(event_args);
}
@@ -614,7 +798,7 @@ SpeechRecognitionEngine::RaiseNoMatchErrorIfGotNoResults(
SpeechRecognitionEngine::FSMState
SpeechRecognitionEngine::CloseUpstreamAndWaitForResults(
const FSMEventArgs&) {
- DCHECK(upstream_fetcher_.get());
+ DCHECK(upstream_loader_.get());
DCHECK(encoder_.get());
DVLOG(1) << "Closing upstream.";
@@ -641,34 +825,35 @@ SpeechRecognitionEngine::CloseUpstreamAndWaitForResults(
SpeechRecognitionEngine::FSMState
SpeechRecognitionEngine::CloseDownstream(const FSMEventArgs&) {
- DCHECK(!upstream_fetcher_.get());
- DCHECK(downstream_fetcher_.get());
+ DCHECK(!upstream_loader_.get());
+ DCHECK(downstream_loader_.get());
DVLOG(1) << "Closing downstream.";
- downstream_fetcher_.reset();
+ downstream_loader_.reset();
return STATE_IDLE;
}
SpeechRecognitionEngine::FSMState
SpeechRecognitionEngine::AbortSilently(const FSMEventArgs&) {
- return Abort(SPEECH_RECOGNITION_ERROR_NONE);
+ return Abort(blink::mojom::SpeechRecognitionErrorCode::kNone);
}
SpeechRecognitionEngine::FSMState
SpeechRecognitionEngine::AbortWithError(const FSMEventArgs&) {
- return Abort(SPEECH_RECOGNITION_ERROR_NETWORK);
+ return Abort(blink::mojom::SpeechRecognitionErrorCode::kNetwork);
}
SpeechRecognitionEngine::FSMState SpeechRecognitionEngine::Abort(
- SpeechRecognitionErrorCode error_code) {
+ blink::mojom::SpeechRecognitionErrorCode error_code) {
DVLOG(1) << "Aborting with error " << error_code;
- if (error_code != SPEECH_RECOGNITION_ERROR_NONE) {
+ if (error_code != blink::mojom::SpeechRecognitionErrorCode::kNone) {
delegate_->OnSpeechRecognitionEngineError(
- SpeechRecognitionError(error_code));
+ blink::mojom::SpeechRecognitionError(
+ error_code, blink::mojom::SpeechAudioErrorDetails::kNone));
}
- downstream_fetcher_.reset();
- upstream_fetcher_.reset();
+ downstream_loader_.reset();
+ upstream_loader_.reset();
encoder_.reset();
return STATE_IDLE;
}
@@ -687,12 +872,12 @@ SpeechRecognitionEngine::NotFeasible(const FSMEventArgs& event_args) {
std::string SpeechRecognitionEngine::GetAcceptedLanguages() const {
std::string langs = config_.language;
- if (langs.empty() && url_context_.get()) {
+ if (langs.empty() && deprecated_url_request_context_getter_.get()) {
// If no language is provided then we use the first from the accepted
// language list. If this list is empty then it defaults to "en-US".
// Example of the contents of this list: "es,en-GB;q=0.8", ""
net::URLRequestContext* request_context =
- url_context_->GetURLRequestContext();
+ deprecated_url_request_context_getter_->GetURLRequestContext();
DCHECK(request_context);
// TODO(pauljensen): SpeechRecognitionEngine should be constructed with
// a reference to the HttpUserAgentSettings rather than accessing the
@@ -730,9 +915,9 @@ void SpeechRecognitionEngine::UploadAudioChunk(const std::string& data,
base::WriteBigEndian(&frame[0], static_cast<uint32_t>(data.size()));
base::WriteBigEndian(&frame[4], static_cast<uint32_t>(type));
frame.replace(8, data.size(), data);
- upstream_fetcher_->AppendChunkToUpload(frame, is_final);
+ upstream_loader_->AppendChunkToUpload(frame, is_final);
} else {
- upstream_fetcher_->AppendChunkToUpload(data, is_final);
+ upstream_loader_->AppendChunkToUpload(data, is_final);
}
}
diff --git a/chromium/content/browser/speech/speech_recognition_engine.h b/chromium/content/browser/speech/speech_recognition_engine.h
index 8a28cb6f86a..5119585cdd2 100644
--- a/chromium/content/browser/speech/speech_recognition_engine.h
+++ b/chromium/content/browser/speech/speech_recognition_engine.h
@@ -13,19 +13,25 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
+#include "base/strings/string_piece.h"
#include "content/browser/speech/audio_encoder.h"
#include "content/browser/speech/chunked_byte_buffer.h"
#include "content/common/content_export.h"
#include "content/public/browser/speech_recognition_session_preamble.h"
-#include "content/public/common/speech_recognition_error.h"
-#include "content/public/common/speech_recognition_grammar.mojom.h"
-#include "content/public/common/speech_recognition_result.h"
-#include "net/url_request/url_fetcher_delegate.h"
+#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_grammar.mojom.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h"
namespace net {
class URLRequestContextGetter;
}
+namespace network {
+class SharedURLLoaderFactory;
+}
+
namespace content {
class AudioChunk;
@@ -57,16 +63,17 @@ struct SpeechRecognitionError;
// EndRecognition. If a recognition was started, the caller can free the
// SpeechRecognitionEngine only after calling EndRecognition.
-class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
+class CONTENT_EXPORT SpeechRecognitionEngine {
public:
class Delegate {
public:
// Called whenever a result is retrieved.
virtual void OnSpeechRecognitionEngineResults(
- const SpeechRecognitionResults& results) = 0;
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>&
+ results) = 0;
virtual void OnSpeechRecognitionEngineEndOfUtterance() = 0;
virtual void OnSpeechRecognitionEngineError(
- const SpeechRecognitionError& error) = 0;
+ const blink::mojom::SpeechRecognitionError& error) = 0;
protected:
virtual ~Delegate() {}
@@ -78,7 +85,7 @@ class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
~Config();
std::string language;
- std::vector<mojom::SpeechRecognitionGrammar> grammars;
+ std::vector<blink::mojom::SpeechRecognitionGrammar> grammars;
bool filter_profanities;
bool continuous;
bool interim_results;
@@ -97,12 +104,15 @@ class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
// Duration of each audio packet.
static const int kAudioPacketIntervalMs;
- // IDs passed to URLFetcher::Create(). Used for testing.
- static const int kUpstreamUrlFetcherIdForTesting;
- static const int kDownstreamUrlFetcherIdForTesting;
-
- explicit SpeechRecognitionEngine(net::URLRequestContextGetter* context);
- ~SpeechRecognitionEngine() override;
+ // |deprecated_url_request_context_getter| is only for poking at the
+ // Accept-Language header.
+ // TODO(mmenke): Remove |deprecated_url_request_context_getter| as an
+ // argument.
+ SpeechRecognitionEngine(
+ scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<net::URLRequestContextGetter>
+ deprecated_url_request_context_getter);
+ ~SpeechRecognitionEngine();
// Sets the URL requests are sent to for tests.
static void set_web_service_base_url_for_tests(
@@ -116,14 +126,10 @@ class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
bool IsRecognitionPending() const;
int GetDesiredAudioChunkDurationMs() const;
- // net::URLFetcherDelegate methods.
- void OnURLFetchComplete(const net::URLFetcher* source) override;
- void OnURLFetchDownloadProgress(const net::URLFetcher* source,
- int64_t current,
- int64_t total,
- int64_t current_network_bytes) override;
-
private:
+ class UpstreamLoader;
+ class DownstreamLoader;
+
Delegate* delegate_;
// Response status codes from the speech recognition webservice.
@@ -173,10 +179,10 @@ class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
DISALLOW_COPY_AND_ASSIGN(FSMEventArgs);
};
- // Invoked by both upstream and downstream URLFetcher callbacks to handle
- // new chunk data, connection closed or errors notifications.
- void DispatchHTTPResponse(const net::URLFetcher* source,
- bool end_of_response);
+ void OnUpstreamDataComplete(bool success, int response_code);
+
+ void OnDownstreamDataReceived(base::StringPiece new_response_data);
+ void OnDownstreamDataComplete(bool success, int response_code);
// Entry point for pushing any new external event into the recognizer FSM.
void DispatchEvent(const FSMEventArgs& event_args);
@@ -194,7 +200,7 @@ class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
FSMState CloseDownstream(const FSMEventArgs& event_args);
FSMState AbortSilently(const FSMEventArgs& event_args);
FSMState AbortWithError(const FSMEventArgs& event_args);
- FSMState Abort(SpeechRecognitionErrorCode error);
+ FSMState Abort(blink::mojom::SpeechRecognitionErrorCode error);
FSMState DoNothing(const FSMEventArgs& event_args);
FSMState NotFeasible(const FSMEventArgs& event_args);
@@ -206,13 +212,14 @@ class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
void UploadAudioChunk(const std::string& data, FrameType type, bool is_final);
Config config_;
- std::unique_ptr<net::URLFetcher> upstream_fetcher_;
- std::unique_ptr<net::URLFetcher> downstream_fetcher_;
- scoped_refptr<net::URLRequestContextGetter> url_context_;
+ std::unique_ptr<UpstreamLoader> upstream_loader_;
+ std::unique_ptr<DownstreamLoader> downstream_loader_;
+ scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
+ scoped_refptr<net::URLRequestContextGetter>
+ deprecated_url_request_context_getter_;
std::unique_ptr<AudioEncoder> encoder_;
std::unique_ptr<AudioEncoder> preamble_encoder_;
ChunkedByteBuffer chunked_byte_buffer_;
- size_t previous_response_length_;
bool got_last_definitive_result_;
bool is_dispatching_event_;
bool use_framed_post_data_;
diff --git a/chromium/content/browser/speech/speech_recognition_engine_unittest.cc b/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
index fd880ae2d36..e5cc0943b11 100644
--- a/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
@@ -17,19 +17,20 @@
#include "base/sys_byteorder.h"
#include "content/browser/speech/audio_buffer.h"
#include "content/browser/speech/proto/google_streaming_api.pb.h"
-#include "content/public/common/speech_recognition_error.h"
-#include "content/public/common/speech_recognition_result.h"
#include "net/base/net_errors.h"
-#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_status.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h"
using base::HostToNet32;
using base::checked_cast;
-using net::URLRequestStatus;
-using net::TestURLFetcher;
-using net::TestURLFetcherFactory;
namespace content {
@@ -46,23 +47,20 @@ class SpeechRecognitionEngineTest
public:
SpeechRecognitionEngineTest()
: last_number_of_upstream_chunks_seen_(0U),
- error_(SPEECH_RECOGNITION_ERROR_NONE),
- end_of_utterance_counter_(0) { }
-
- // Creates a speech recognition request and invokes its URL fetcher delegate
- // with the given test data.
- void CreateAndTestRequest(bool success, const std::string& http_response);
+ error_(blink::mojom::SpeechRecognitionErrorCode::kNone),
+ end_of_utterance_counter_(0) {}
// SpeechRecognitionRequestDelegate methods.
void OnSpeechRecognitionEngineResults(
- const SpeechRecognitionResults& results) override {
- results_.push(results);
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& results)
+ override {
+ results_.push(mojo::Clone(results));
}
void OnSpeechRecognitionEngineEndOfUtterance() override {
++end_of_utterance_counter_;
}
void OnSpeechRecognitionEngineError(
- const SpeechRecognitionError& error) override {
+ const blink::mojom::SpeechRecognitionError& error) override {
error_ = error.code;
}
@@ -77,62 +75,72 @@ class SpeechRecognitionEngineTest
DOWNSTREAM_ERROR_NETWORK,
DOWNSTREAM_ERROR_WEBSERVICE_NO_MATCH
};
- static bool ResultsAreEqual(const SpeechRecognitionResults& a,
- const SpeechRecognitionResults& b);
+ static bool ResultsAreEqual(
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& a,
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& b);
static std::string SerializeProtobufResponse(
const proto::SpeechRecognitionEvent& msg);
- TestURLFetcher* GetUpstreamFetcher();
- TestURLFetcher* GetDownstreamFetcher();
+ const network::TestURLLoaderFactory::PendingRequest* GetUpstreamRequest();
+ const network::TestURLLoaderFactory::PendingRequest* GetDownstreamRequest();
void StartMockRecognition();
void EndMockRecognition();
void InjectDummyAudioChunk();
- size_t UpstreamChunksUploadedFromLastCall();
- std::string LastUpstreamChunkUploaded();
+ void ProvideMockResponseStartDownstreamIfNeeded();
void ProvideMockProtoResultDownstream(
const proto::SpeechRecognitionEvent& result);
- void ProvideMockResultDownstream(const SpeechRecognitionResult& result);
- void ExpectResultsReceived(const SpeechRecognitionResults& result);
+ void ProvideMockResultDownstream(
+ const blink::mojom::SpeechRecognitionResultPtr& result);
+ void ExpectResultsReceived(
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& result);
void ExpectFramedChunk(const std::string& chunk, uint32_t type);
+ // Reads and returns all pending upload data from |upstream_data_pipe_|,
+ // initializing the pipe from |GetUpstreamRequest()|, if needed.
+ std::string ConsumeChunkedUploadData();
void CloseMockDownstream(DownstreamError error);
+ base::MessageLoop message_loop_;
+
+ network::TestURLLoaderFactory url_loader_factory_;
+ mojo::ScopedDataPipeProducerHandle downstream_data_pipe_;
+ network::mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter_;
+ mojo::ScopedDataPipeConsumerHandle upstream_data_pipe_;
+
std::unique_ptr<SpeechRecognitionEngine> engine_under_test_;
- TestURLFetcherFactory url_fetcher_factory_;
size_t last_number_of_upstream_chunks_seen_;
- base::MessageLoop message_loop_;
std::string response_buffer_;
- SpeechRecognitionErrorCode error_;
+ blink::mojom::SpeechRecognitionErrorCode error_;
int end_of_utterance_counter_;
- base::queue<SpeechRecognitionResults> results_;
+ base::queue<std::vector<blink::mojom::SpeechRecognitionResultPtr>> results_;
};
TEST_F(SpeechRecognitionEngineTest, SingleDefinitiveResult) {
StartMockRecognition();
- ASSERT_TRUE(GetUpstreamFetcher());
- ASSERT_EQ(0U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_TRUE(GetUpstreamRequest());
+ ASSERT_EQ("", ConsumeChunkedUploadData());
// Inject some dummy audio chunks and check a corresponding chunked upload
// is performed every time on the server.
for (int i = 0; i < 3; ++i) {
InjectDummyAudioChunk();
- ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_FALSE(ConsumeChunkedUploadData().empty());
}
// Ensure that a final (empty) audio chunk is uploaded on chunks end.
engine_under_test_->AudioChunksEnded();
- ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_FALSE(ConsumeChunkedUploadData().empty());
ASSERT_TRUE(engine_under_test_->IsRecognitionPending());
// Simulate a protobuf message streamed from the server containing a single
// result with two hypotheses.
- SpeechRecognitionResults results;
- results.push_back(SpeechRecognitionResult());
- SpeechRecognitionResult& result = results.back();
- result.is_provisional = false;
- result.hypotheses.push_back(
- SpeechRecognitionHypothesis(base::UTF8ToUTF16("hypothesis 1"), 0.1F));
- result.hypotheses.push_back(
- SpeechRecognitionHypothesis(base::UTF8ToUTF16("hypothesis 2"), 0.2F));
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results;
+ results.push_back(blink::mojom::SpeechRecognitionResult::New());
+ blink::mojom::SpeechRecognitionResultPtr& result = results.back();
+ result->is_provisional = false;
+ result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
+ base::UTF8ToUTF16("hypothesis 1"), 0.1F));
+ result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
+ base::UTF8ToUTF16("hypothesis 2"), 0.2F));
ProvideMockResultDownstream(result);
ExpectResultsReceived(results);
@@ -142,25 +150,25 @@ TEST_F(SpeechRecognitionEngineTest, SingleDefinitiveResult) {
CloseMockDownstream(DOWNSTREAM_ERROR_NONE);
ASSERT_FALSE(engine_under_test_->IsRecognitionPending());
EndMockRecognition();
- ASSERT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ ASSERT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
ASSERT_EQ(0U, results_.size());
}
TEST_F(SpeechRecognitionEngineTest, SeveralStreamingResults) {
StartMockRecognition();
- ASSERT_TRUE(GetUpstreamFetcher());
- ASSERT_EQ(0U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_TRUE(GetUpstreamRequest());
+ ASSERT_EQ("", ConsumeChunkedUploadData());
for (int i = 0; i < 4; ++i) {
InjectDummyAudioChunk();
- ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall());
-
- SpeechRecognitionResults results;
- results.push_back(SpeechRecognitionResult());
- SpeechRecognitionResult& result = results.back();
- result.is_provisional = (i % 2 == 0); // Alternate result types.
- float confidence = result.is_provisional ? 0.0F : (i * 0.1F);
- result.hypotheses.push_back(SpeechRecognitionHypothesis(
+ ASSERT_NE("", ConsumeChunkedUploadData());
+
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results;
+ results.push_back(blink::mojom::SpeechRecognitionResult::New());
+ blink::mojom::SpeechRecognitionResultPtr& result = results.back();
+ result->is_provisional = (i % 2 == 0); // Alternate result types.
+ float confidence = result->is_provisional ? 0.0F : (i * 0.1F);
+ result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
base::UTF8ToUTF16("hypothesis"), confidence));
ProvideMockResultDownstream(result);
@@ -170,16 +178,16 @@ TEST_F(SpeechRecognitionEngineTest, SeveralStreamingResults) {
// Ensure that a final (empty) audio chunk is uploaded on chunks end.
engine_under_test_->AudioChunksEnded();
- ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_NE("", ConsumeChunkedUploadData());
ASSERT_TRUE(engine_under_test_->IsRecognitionPending());
// Simulate a final definitive result.
- SpeechRecognitionResults results;
- results.push_back(SpeechRecognitionResult());
- SpeechRecognitionResult& result = results.back();
- result.is_provisional = false;
- result.hypotheses.push_back(
- SpeechRecognitionHypothesis(base::UTF8ToUTF16("The final result"), 1.0F));
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results;
+ results.push_back(blink::mojom::SpeechRecognitionResult::New());
+ blink::mojom::SpeechRecognitionResultPtr& result = results.back();
+ result->is_provisional = false;
+ result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
+ base::UTF8ToUTF16("The final result"), 1.0F));
ProvideMockResultDownstream(result);
ExpectResultsReceived(results);
ASSERT_TRUE(engine_under_test_->IsRecognitionPending());
@@ -188,65 +196,122 @@ TEST_F(SpeechRecognitionEngineTest, SeveralStreamingResults) {
CloseMockDownstream(DOWNSTREAM_ERROR_NONE);
ASSERT_FALSE(engine_under_test_->IsRecognitionPending());
EndMockRecognition();
- ASSERT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ ASSERT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
ASSERT_EQ(0U, results_.size());
}
TEST_F(SpeechRecognitionEngineTest, NoFinalResultAfterAudioChunksEnded) {
StartMockRecognition();
- ASSERT_TRUE(GetUpstreamFetcher());
- ASSERT_EQ(0U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_TRUE(GetUpstreamRequest());
+ ASSERT_EQ("", ConsumeChunkedUploadData());
// Simulate one pushed audio chunk.
InjectDummyAudioChunk();
- ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_NE("", ConsumeChunkedUploadData());
// Simulate the corresponding definitive result.
- SpeechRecognitionResults results;
- results.push_back(SpeechRecognitionResult());
- SpeechRecognitionResult& result = results.back();
- result.hypotheses.push_back(
- SpeechRecognitionHypothesis(base::UTF8ToUTF16("hypothesis"), 1.0F));
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results;
+ results.push_back(blink::mojom::SpeechRecognitionResult::New());
+ blink::mojom::SpeechRecognitionResultPtr& result = results.back();
+ result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
+ base::UTF8ToUTF16("hypothesis"), 1.0F));
ProvideMockResultDownstream(result);
ExpectResultsReceived(results);
ASSERT_TRUE(engine_under_test_->IsRecognitionPending());
// Simulate a silent downstream closure after |AudioChunksEnded|.
engine_under_test_->AudioChunksEnded();
- ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_NE("", ConsumeChunkedUploadData());
ASSERT_TRUE(engine_under_test_->IsRecognitionPending());
CloseMockDownstream(DOWNSTREAM_ERROR_NONE);
// Expect an empty result, aimed at notifying recognition ended with no
// actual results nor errors.
- SpeechRecognitionResults empty_results;
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> empty_results;
ExpectResultsReceived(empty_results);
// Ensure everything is closed cleanly after the downstream is closed.
ASSERT_FALSE(engine_under_test_->IsRecognitionPending());
EndMockRecognition();
- ASSERT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ ASSERT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
+ ASSERT_EQ(0U, results_.size());
+}
+
+// Simulate the network service repeatedly re-requesting data (Possibly due to
+// using a stale socket, for instance).
+TEST_F(SpeechRecognitionEngineTest, ReRequestData) {
+ StartMockRecognition();
+ ASSERT_TRUE(GetUpstreamRequest());
+ ASSERT_EQ("", ConsumeChunkedUploadData());
+
+ // Simulate one pushed audio chunk.
+ InjectDummyAudioChunk();
+ std::string uploaded_data = ConsumeChunkedUploadData();
+ ASSERT_NE(uploaded_data, ConsumeChunkedUploadData());
+
+ // The network service closes the data pipe.
+ upstream_data_pipe_.reset();
+
+ // Re-opening the data pipe should result in the data being re-uploaded.
+ ASSERT_EQ(uploaded_data, ConsumeChunkedUploadData());
+
+ // Simulate the corresponding definitive result.
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results;
+ results.push_back(blink::mojom::SpeechRecognitionResult::New());
+ blink::mojom::SpeechRecognitionResultPtr& result = results.back();
+ result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
+ base::UTF8ToUTF16("hypothesis"), 1.0F));
+ ProvideMockResultDownstream(result);
+ ExpectResultsReceived(results);
+ ASSERT_TRUE(engine_under_test_->IsRecognitionPending());
+
+ // Simulate a silent downstream closure after |AudioChunksEnded|.
+ engine_under_test_->AudioChunksEnded();
+ std::string new_uploaded_data = ConsumeChunkedUploadData();
+ ASSERT_NE(new_uploaded_data, ConsumeChunkedUploadData());
+ uploaded_data += new_uploaded_data;
+
+ // The network service closes the data pipe.
+ upstream_data_pipe_.reset();
+
+ // Re-opening the data pipe should result in the data being re-uploaded.
+ ASSERT_EQ(uploaded_data, ConsumeChunkedUploadData());
+
+ ASSERT_TRUE(engine_under_test_->IsRecognitionPending());
+ CloseMockDownstream(DOWNSTREAM_ERROR_NONE);
+
+ // Expect an empty result, aimed at notifying recognition ended with no
+ // actual results nor errors.
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> empty_results;
+ ExpectResultsReceived(empty_results);
+
+ // Ensure everything is closed cleanly after the downstream is closed.
+ ASSERT_FALSE(engine_under_test_->IsRecognitionPending());
+ EndMockRecognition();
+ ASSERT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
ASSERT_EQ(0U, results_.size());
}
TEST_F(SpeechRecognitionEngineTest, NoMatchError) {
StartMockRecognition();
- ASSERT_TRUE(GetUpstreamFetcher());
- ASSERT_EQ(0U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_TRUE(GetUpstreamRequest());
+ ASSERT_EQ("", ConsumeChunkedUploadData());
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 3; ++i) {
InjectDummyAudioChunk();
+ ASSERT_NE("", ConsumeChunkedUploadData());
+ }
engine_under_test_->AudioChunksEnded();
- ASSERT_EQ(4U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_NE("", ConsumeChunkedUploadData());
ASSERT_TRUE(engine_under_test_->IsRecognitionPending());
// Simulate only a provisional result.
- SpeechRecognitionResults results;
- results.push_back(SpeechRecognitionResult());
- SpeechRecognitionResult& result = results.back();
- result.is_provisional = true;
- result.hypotheses.push_back(
- SpeechRecognitionHypothesis(base::UTF8ToUTF16("The final result"), 0.0F));
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results;
+ results.push_back(blink::mojom::SpeechRecognitionResult::New());
+ blink::mojom::SpeechRecognitionResultPtr& result = results.back();
+ result->is_provisional = true;
+ result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
+ base::UTF8ToUTF16("The final result"), 0.0F));
ProvideMockResultDownstream(result);
ExpectResultsReceived(results);
ASSERT_TRUE(engine_under_test_->IsRecognitionPending());
@@ -256,54 +321,56 @@ TEST_F(SpeechRecognitionEngineTest, NoMatchError) {
// Expect an empty result.
ASSERT_FALSE(engine_under_test_->IsRecognitionPending());
EndMockRecognition();
- SpeechRecognitionResults empty_result;
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> empty_result;
ExpectResultsReceived(empty_result);
}
TEST_F(SpeechRecognitionEngineTest, HTTPError) {
StartMockRecognition();
- ASSERT_TRUE(GetUpstreamFetcher());
- ASSERT_EQ(0U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_TRUE(GetUpstreamRequest());
+ ASSERT_EQ("", ConsumeChunkedUploadData());
InjectDummyAudioChunk();
- ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_NE("", ConsumeChunkedUploadData());
// Close the downstream with a HTTP 500 error.
CloseMockDownstream(DOWNSTREAM_ERROR_HTTP500);
- // Expect a SPEECH_RECOGNITION_ERROR_NETWORK error to be raised.
+ // Expect a blink::mojom::SpeechRecognitionErrorCode::kNetwork error to be
+ // raised.
ASSERT_FALSE(engine_under_test_->IsRecognitionPending());
EndMockRecognition();
- ASSERT_EQ(SPEECH_RECOGNITION_ERROR_NETWORK, error_);
+ ASSERT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNetwork, error_);
ASSERT_EQ(0U, results_.size());
}
TEST_F(SpeechRecognitionEngineTest, NetworkError) {
StartMockRecognition();
- ASSERT_TRUE(GetUpstreamFetcher());
- ASSERT_EQ(0U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_TRUE(GetUpstreamRequest());
+ ASSERT_EQ("", ConsumeChunkedUploadData());
InjectDummyAudioChunk();
- ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_NE("", ConsumeChunkedUploadData());
// Close the downstream fetcher simulating a network failure.
CloseMockDownstream(DOWNSTREAM_ERROR_NETWORK);
- // Expect a SPEECH_RECOGNITION_ERROR_NETWORK error to be raised.
+ // Expect a blink::mojom::SpeechRecognitionErrorCode::kNetwork error to be
+ // raised.
ASSERT_FALSE(engine_under_test_->IsRecognitionPending());
EndMockRecognition();
- ASSERT_EQ(SPEECH_RECOGNITION_ERROR_NETWORK, error_);
+ ASSERT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNetwork, error_);
ASSERT_EQ(0U, results_.size());
}
TEST_F(SpeechRecognitionEngineTest, Stability) {
StartMockRecognition();
- ASSERT_TRUE(GetUpstreamFetcher());
- ASSERT_EQ(0U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_TRUE(GetUpstreamRequest());
+ ASSERT_EQ("", ConsumeChunkedUploadData());
// Upload a dummy audio chunk.
InjectDummyAudioChunk();
- ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall());
+ ASSERT_NE("", ConsumeChunkedUploadData());
engine_under_test_->AudioChunksEnded();
// Simulate a protobuf message with an intermediate result without confidence,
@@ -318,12 +385,12 @@ TEST_F(SpeechRecognitionEngineTest, Stability) {
ProvideMockProtoResultDownstream(proto_event);
// Set up expectations.
- SpeechRecognitionResults results;
- results.push_back(SpeechRecognitionResult());
- SpeechRecognitionResult& result = results.back();
- result.is_provisional = true;
- result.hypotheses.push_back(
- SpeechRecognitionHypothesis(base::UTF8ToUTF16("foo"), 0.5));
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results;
+ results.push_back(blink::mojom::SpeechRecognitionResult::New());
+ blink::mojom::SpeechRecognitionResultPtr& result = results.back();
+ result->is_provisional = true;
+ result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
+ base::UTF8ToUTF16("foo"), 0.5));
// Check that the protobuf generated the expected result.
ExpectResultsReceived(results);
@@ -337,15 +404,15 @@ TEST_F(SpeechRecognitionEngineTest, Stability) {
EndMockRecognition();
// Since there was no final result, we get an empty "no match" result.
- SpeechRecognitionResults empty_result;
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> empty_result;
ExpectResultsReceived(empty_result);
- ASSERT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ ASSERT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
ASSERT_EQ(0U, results_.size());
}
TEST_F(SpeechRecognitionEngineTest, EndOfUtterance) {
StartMockRecognition();
- ASSERT_TRUE(GetUpstreamFetcher());
+ ASSERT_TRUE(GetUpstreamRequest());
// Simulate a END_OF_UTTERANCE proto event with continuous true.
SpeechRecognitionEngine::Config config;
@@ -382,16 +449,16 @@ TEST_F(SpeechRecognitionEngineTest, SendPreamble) {
engine_under_test_->SetConfig(config);
StartMockRecognition();
- ASSERT_TRUE(GetUpstreamFetcher());
+ ASSERT_TRUE(GetUpstreamRequest());
// First chunk uploaded should be the preamble.
- ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall());
- std::string chunk = LastUpstreamChunkUploaded();
+ std::string chunk = ConsumeChunkedUploadData();
+ ASSERT_NE("", chunk);
ExpectFramedChunk(chunk, kFrameTypePreamble);
for (int i = 0; i < 3; ++i) {
InjectDummyAudioChunk();
- ASSERT_EQ(1U, UpstreamChunksUploadedFromLastCall());
- chunk = LastUpstreamChunkUploaded();
+ chunk = ConsumeChunkedUploadData();
+ ASSERT_NE("", chunk);
ExpectFramedChunk(chunk, kFrameTypeRecognitionAudio);
}
engine_under_test_->AudioChunksEnded();
@@ -399,12 +466,12 @@ TEST_F(SpeechRecognitionEngineTest, SendPreamble) {
// Simulate a protobuf message streamed from the server containing a single
// result with one hypotheses.
- SpeechRecognitionResults results;
- results.push_back(SpeechRecognitionResult());
- SpeechRecognitionResult& result = results.back();
- result.is_provisional = false;
- result.hypotheses.push_back(
- SpeechRecognitionHypothesis(base::UTF8ToUTF16("hypothesis 1"), 0.1F));
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results;
+ results.push_back(blink::mojom::SpeechRecognitionResult::New());
+ blink::mojom::SpeechRecognitionResultPtr& result = results.back();
+ result->is_provisional = false;
+ result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
+ base::UTF8ToUTF16("hypothesis 1"), 0.1F));
ProvideMockResultDownstream(result);
ExpectResultsReceived(results);
@@ -414,13 +481,15 @@ TEST_F(SpeechRecognitionEngineTest, SendPreamble) {
CloseMockDownstream(DOWNSTREAM_ERROR_NONE);
ASSERT_FALSE(engine_under_test_->IsRecognitionPending());
EndMockRecognition();
- ASSERT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ ASSERT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
ASSERT_EQ(0U, results_.size());
}
void SpeechRecognitionEngineTest::SetUp() {
- engine_under_test_.reset(
- new SpeechRecognitionEngine(nullptr /*URLRequestContextGetter*/));
+ engine_under_test_.reset(new SpeechRecognitionEngine(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ &url_loader_factory_),
+ nullptr /*URLRequestContextGetter*/));
engine_under_test_->set_delegate(this);
}
@@ -428,14 +497,22 @@ void SpeechRecognitionEngineTest::TearDown() {
engine_under_test_.reset();
}
-TestURLFetcher* SpeechRecognitionEngineTest::GetUpstreamFetcher() {
- return url_fetcher_factory_.GetFetcherByID(
- SpeechRecognitionEngine::kUpstreamUrlFetcherIdForTesting);
+const network::TestURLLoaderFactory::PendingRequest*
+SpeechRecognitionEngineTest::GetUpstreamRequest() {
+ for (const auto& pending_request : *url_loader_factory_.pending_requests()) {
+ if (pending_request.request.url.spec().find("/up") != std::string::npos)
+ return &pending_request;
+ }
+ return nullptr;
}
-TestURLFetcher* SpeechRecognitionEngineTest::GetDownstreamFetcher() {
- return url_fetcher_factory_.GetFetcherByID(
- SpeechRecognitionEngine::kDownstreamUrlFetcherIdForTesting);
+const network::TestURLLoaderFactory::PendingRequest*
+SpeechRecognitionEngineTest::GetDownstreamRequest() {
+ for (const auto& pending_request : *url_loader_factory_.pending_requests()) {
+ if (pending_request.request.url.spec().find("/down") != std::string::npos)
+ return &pending_request;
+ }
+ return nullptr;
}
// Starts recognition on the engine, ensuring that both stream fetchers are
@@ -448,13 +525,8 @@ void SpeechRecognitionEngineTest::StartMockRecognition() {
engine_under_test_->StartRecognition();
ASSERT_TRUE(engine_under_test_->IsRecognitionPending());
- TestURLFetcher* upstream_fetcher = GetUpstreamFetcher();
- ASSERT_TRUE(upstream_fetcher);
- upstream_fetcher->set_url(upstream_fetcher->GetOriginalURL());
-
- TestURLFetcher* downstream_fetcher = GetDownstreamFetcher();
- ASSERT_TRUE(downstream_fetcher);
- downstream_fetcher->set_url(downstream_fetcher->GetOriginalURL());
+ ASSERT_TRUE(GetUpstreamRequest());
+ ASSERT_TRUE(GetDownstreamRequest());
}
void SpeechRecognitionEngineTest::EndMockRecognition() {
@@ -470,7 +542,9 @@ void SpeechRecognitionEngineTest::EndMockRecognition() {
}
void SpeechRecognitionEngineTest::InjectDummyAudioChunk() {
- unsigned char dummy_audio_buffer_data[2] = {'\0', '\0'};
+ // Enough data so that the encoder will output something, as can't read 0
+ // bytes from a Mojo stream.
+ unsigned char dummy_audio_buffer_data[2000 * 2] = {'\0'};
scoped_refptr<AudioChunk> dummy_audio_chunk(
new AudioChunk(&dummy_audio_buffer_data[0],
sizeof(dummy_audio_buffer_data),
@@ -479,100 +553,135 @@ void SpeechRecognitionEngineTest::InjectDummyAudioChunk() {
engine_under_test_->TakeAudioChunk(*dummy_audio_chunk.get());
}
-size_t SpeechRecognitionEngineTest::UpstreamChunksUploadedFromLastCall() {
- TestURLFetcher* upstream_fetcher = GetUpstreamFetcher();
- DCHECK(upstream_fetcher);
- const size_t number_of_chunks = upstream_fetcher->upload_chunks().size();
- DCHECK_GE(number_of_chunks, last_number_of_upstream_chunks_seen_);
- const size_t new_chunks = number_of_chunks -
- last_number_of_upstream_chunks_seen_;
- last_number_of_upstream_chunks_seen_ = number_of_chunks;
- return new_chunks;
-}
-
-std::string SpeechRecognitionEngineTest::LastUpstreamChunkUploaded() {
- TestURLFetcher* upstream_fetcher = GetUpstreamFetcher();
- DCHECK(upstream_fetcher);
- DCHECK(!upstream_fetcher->upload_chunks().empty());
- return upstream_fetcher->upload_chunks().back();
+void SpeechRecognitionEngineTest::ProvideMockResponseStartDownstreamIfNeeded() {
+ if (downstream_data_pipe_.get())
+ return;
+ const network::TestURLLoaderFactory::PendingRequest* downstream_request =
+ GetDownstreamRequest();
+ ASSERT_TRUE(downstream_request);
+
+ network::ResourceResponseHead head;
+ std::string headers("HTTP/1.1 200 OK\n\n");
+ head.headers = new net::HttpResponseHeaders(
+ net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
+ downstream_request->client->OnReceiveResponse(head);
+
+ mojo::DataPipe data_pipe;
+ downstream_request->client->OnStartLoadingResponseBody(
+ std::move(data_pipe.consumer_handle));
+ downstream_data_pipe_ = std::move(data_pipe.producer_handle);
}
void SpeechRecognitionEngineTest::ProvideMockProtoResultDownstream(
const proto::SpeechRecognitionEvent& result) {
- TestURLFetcher* downstream_fetcher = GetDownstreamFetcher();
-
- ASSERT_TRUE(downstream_fetcher);
- downstream_fetcher->set_status(URLRequestStatus(/* default=SUCCESS */));
- downstream_fetcher->set_response_code(200);
+ ProvideMockResponseStartDownstreamIfNeeded();
+ ASSERT_TRUE(downstream_data_pipe_.get());
+ ASSERT_TRUE(downstream_data_pipe_.is_valid());
std::string response_string = SerializeProtobufResponse(result);
response_buffer_.append(response_string);
- downstream_fetcher->SetResponseString(response_buffer_);
- downstream_fetcher->delegate()->OnURLFetchDownloadProgress(
- downstream_fetcher, response_buffer_.size(),
- -1 /* total response length not used */, response_buffer_.size());
+ uint32_t written = 0;
+ while (written < response_string.size()) {
+ uint32_t write_bytes = response_string.size() - written;
+ MojoResult result = downstream_data_pipe_->WriteData(
+ response_string.data() + written, &write_bytes,
+ MOJO_WRITE_DATA_FLAG_NONE);
+ if (result == MOJO_RESULT_OK) {
+ written += write_bytes;
+ continue;
+ }
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ base::RunLoop().RunUntilIdle();
+ continue;
+ }
+
+ FAIL() << "Mojo pipe unexpectedly closed";
+ }
+ base::RunLoop().RunUntilIdle();
}
void SpeechRecognitionEngineTest::ProvideMockResultDownstream(
- const SpeechRecognitionResult& result) {
+ const blink::mojom::SpeechRecognitionResultPtr& result) {
proto::SpeechRecognitionEvent proto_event;
proto_event.set_status(proto::SpeechRecognitionEvent::STATUS_SUCCESS);
proto::SpeechRecognitionResult* proto_result = proto_event.add_result();
- proto_result->set_final(!result.is_provisional);
- for (size_t i = 0; i < result.hypotheses.size(); ++i) {
+ proto_result->set_final(!result->is_provisional);
+ for (size_t i = 0; i < result->hypotheses.size(); ++i) {
proto::SpeechRecognitionAlternative* proto_alternative =
proto_result->add_alternative();
- const SpeechRecognitionHypothesis& hypothesis = result.hypotheses[i];
- proto_alternative->set_confidence(hypothesis.confidence);
- proto_alternative->set_transcript(base::UTF16ToUTF8(hypothesis.utterance));
+ const blink::mojom::SpeechRecognitionHypothesisPtr& hypothesis =
+ result->hypotheses[i];
+ proto_alternative->set_confidence(hypothesis->confidence);
+ proto_alternative->set_transcript(base::UTF16ToUTF8(hypothesis->utterance));
}
ProvideMockProtoResultDownstream(proto_event);
+ base::RunLoop().RunUntilIdle();
}
void SpeechRecognitionEngineTest::CloseMockDownstream(
DownstreamError error) {
- TestURLFetcher* downstream_fetcher = GetDownstreamFetcher();
- ASSERT_TRUE(downstream_fetcher);
+ if (error == DOWNSTREAM_ERROR_HTTP500) {
+ // Can't provide a network error if already gave the consumer a 200
+ // response.
+ ASSERT_FALSE(downstream_data_pipe_.get());
+
+ const network::TestURLLoaderFactory::PendingRequest* downstream_request =
+ GetDownstreamRequest();
+ ASSERT_TRUE(downstream_request);
+ network::ResourceResponseHead head;
+ std::string headers("HTTP/1.1 500 Server Sad\n\n");
+ head.headers = new net::HttpResponseHeaders(
+ net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
+ downstream_request->client->OnReceiveResponse(head);
+ // Wait for the response to be handled.
+ base::RunLoop().RunUntilIdle();
+ return;
+ }
+
+ ProvideMockResponseStartDownstreamIfNeeded();
+ const network::TestURLLoaderFactory::PendingRequest* downstream_request =
+ GetDownstreamRequest();
+ ASSERT_TRUE(downstream_request);
- const net::Error net_error =
+ network::URLLoaderCompletionStatus status;
+ status.decoded_body_length = response_buffer_.size();
+ status.error_code =
(error == DOWNSTREAM_ERROR_NETWORK) ? net::ERR_FAILED : net::OK;
- downstream_fetcher->set_status(URLRequestStatus::FromError(net_error));
- downstream_fetcher->set_response_code(
- (error == DOWNSTREAM_ERROR_HTTP500) ? 500 : 200);
-
- if (error == DOWNSTREAM_ERROR_WEBSERVICE_NO_MATCH) {
- // Send empty response.
- proto::SpeechRecognitionEvent response;
- response_buffer_.append(SerializeProtobufResponse(response));
- }
- downstream_fetcher->SetResponseString(response_buffer_);
- downstream_fetcher->delegate()->OnURLFetchComplete(downstream_fetcher);
+ downstream_request->client->OnComplete(status);
+ downstream_data_pipe_.reset();
+ // Wait for the completion events to be handled.
+ base::RunLoop().RunUntilIdle();
}
void SpeechRecognitionEngineTest::ExpectResultsReceived(
- const SpeechRecognitionResults& results) {
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& results) {
ASSERT_GE(1U, results_.size());
ASSERT_TRUE(ResultsAreEqual(results, results_.front()));
results_.pop();
}
bool SpeechRecognitionEngineTest::ResultsAreEqual(
- const SpeechRecognitionResults& a, const SpeechRecognitionResults& b) {
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& a,
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& b) {
if (a.size() != b.size())
return false;
- SpeechRecognitionResults::const_iterator it_a = a.begin();
- SpeechRecognitionResults::const_iterator it_b = b.begin();
+ std::vector<blink::mojom::SpeechRecognitionResultPtr>::const_iterator it_a =
+ a.begin();
+ std::vector<blink::mojom::SpeechRecognitionResultPtr>::const_iterator it_b =
+ b.begin();
for (; it_a != a.end() && it_b != b.end(); ++it_a, ++it_b) {
- if (it_a->is_provisional != it_b->is_provisional ||
- it_a->hypotheses.size() != it_b->hypotheses.size()) {
+ if ((*it_a)->is_provisional != (*it_b)->is_provisional ||
+ (*it_a)->hypotheses.size() != (*it_b)->hypotheses.size()) {
return false;
}
- for (size_t i = 0; i < it_a->hypotheses.size(); ++i) {
- const SpeechRecognitionHypothesis& hyp_a = it_a->hypotheses[i];
- const SpeechRecognitionHypothesis& hyp_b = it_b->hypotheses[i];
- if (hyp_a.utterance != hyp_b.utterance ||
- hyp_a.confidence != hyp_b.confidence) {
+ for (size_t i = 0; i < (*it_a)->hypotheses.size(); ++i) {
+ const blink::mojom::SpeechRecognitionHypothesisPtr& hyp_a =
+ (*it_a)->hypotheses[i];
+ const blink::mojom::SpeechRecognitionHypothesisPtr& hyp_b =
+ (*it_b)->hypotheses[i];
+ if (hyp_a->utterance != hyp_b->utterance ||
+ hyp_a->confidence != hyp_b->confidence) {
return false;
}
}
@@ -590,6 +699,56 @@ void SpeechRecognitionEngineTest::ExpectFramedChunk(
EXPECT_EQ(type, value);
}
+std::string SpeechRecognitionEngineTest::ConsumeChunkedUploadData() {
+ std::string result;
+ base::RunLoop().RunUntilIdle();
+
+ if (!upstream_data_pipe_.get()) {
+ if (!chunked_data_pipe_getter_) {
+ const network::TestURLLoaderFactory::PendingRequest* upstream_request =
+ GetUpstreamRequest();
+ EXPECT_TRUE(upstream_request);
+ EXPECT_TRUE(upstream_request->request.request_body);
+ EXPECT_EQ(1u, upstream_request->request.request_body->elements()->size());
+ EXPECT_EQ(
+ network::DataElement::TYPE_CHUNKED_DATA_PIPE,
+ (*upstream_request->request.request_body->elements())[0].type());
+ network::TestURLLoaderFactory::PendingRequest* mutable_upstream_request =
+ const_cast<network::TestURLLoaderFactory::PendingRequest*>(
+ upstream_request);
+ chunked_data_pipe_getter_ = (*mutable_upstream_request->request
+ .request_body->elements_mutable())[0]
+ .ReleaseChunkedDataPipeGetter();
+ }
+ mojo::DataPipe data_pipe;
+ chunked_data_pipe_getter_->StartReading(
+ std::move(data_pipe.producer_handle));
+ upstream_data_pipe_ = std::move(data_pipe.consumer_handle);
+ }
+ EXPECT_TRUE(upstream_data_pipe_.is_valid());
+
+ std::string out;
+ while (true) {
+ base::RunLoop().RunUntilIdle();
+
+ const void* data;
+ uint32_t num_bytes;
+ MojoResult result = upstream_data_pipe_->BeginReadData(
+ &data, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
+ if (result == MOJO_RESULT_OK) {
+ out.append(static_cast<const char*>(data), num_bytes);
+ upstream_data_pipe_->EndReadData(num_bytes);
+ continue;
+ }
+ if (result == MOJO_RESULT_SHOULD_WAIT)
+ break;
+
+ ADD_FAILURE() << "Mojo pipe unexpectedly closed";
+ break;
+ }
+ return out;
+}
+
std::string SpeechRecognitionEngineTest::SerializeProtobufResponse(
const proto::SpeechRecognitionEvent& msg) {
std::string msg_string;
diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.cc b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
index e04810d1d03..0fe2c51770a 100644
--- a/chromium/content/browser/speech/speech_recognition_manager_impl.cc
+++ b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
@@ -21,6 +21,8 @@
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
#include "content/browser/speech/speech_recognition_engine.h"
#include "content/browser/speech/speech_recognizer_impl.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/resource_context.h"
@@ -30,9 +32,9 @@
#include "content/public/browser/speech_recognition_session_context.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
-#include "content/public/common/speech_recognition_error.h"
-#include "content/public/common/speech_recognition_result.h"
#include "media/audio/audio_device_description.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -281,7 +283,8 @@ int SpeechRecognitionManagerImpl::CreateSession(
remote_engine_config.preamble = config.preamble;
SpeechRecognitionEngine* google_remote_engine =
- new SpeechRecognitionEngine(config.url_request_context_getter.get());
+ new SpeechRecognitionEngine(config.shared_url_loader_factory,
+ config.deprecated_url_request_context_getter);
google_remote_engine->SetConfig(remote_engine_config);
session->recognizer = new SpeechRecognizerImpl(
@@ -360,8 +363,10 @@ void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id,
base::BindOnce(&SpeechRecognitionManagerImpl::DispatchEvent,
weak_factory_.GetWeakPtr(), session_id, EVENT_START));
} else {
- OnRecognitionError(session_id, SpeechRecognitionError(
- SPEECH_RECOGNITION_ERROR_NOT_ALLOWED));
+ OnRecognitionError(
+ session_id, blink::mojom::SpeechRecognitionError(
+ blink::mojom::SpeechRecognitionErrorCode::kNotAllowed,
+ blink::mojom::SpeechAudioErrorDetails::kNone));
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&SpeechRecognitionManagerImpl::DispatchEvent,
@@ -539,7 +544,8 @@ void SpeechRecognitionManagerImpl::OnAudioEnd(int session_id) {
}
void SpeechRecognitionManagerImpl::OnRecognitionResults(
- int session_id, const SpeechRecognitionResults& results) {
+ int session_id,
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& results) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!SessionExists(session_id))
return;
@@ -551,7 +557,8 @@ void SpeechRecognitionManagerImpl::OnRecognitionResults(
}
void SpeechRecognitionManagerImpl::OnRecognitionError(
- int session_id, const SpeechRecognitionError& error) {
+ int session_id,
+ const blink::mojom::SpeechRecognitionError& error) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!SessionExists(session_id))
return;
diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.h b/chromium/content/browser/speech/speech_recognition_manager_impl.h
index cf4468d3bef..8819223a3b6 100644
--- a/chromium/content/browser/speech/speech_recognition_manager_impl.h
+++ b/chromium/content/browser/speech/speech_recognition_manager_impl.h
@@ -16,7 +16,7 @@
#include "content/public/browser/speech_recognition_manager.h"
#include "content/public/browser/speech_recognition_session_config.h"
#include "content/public/browser/speech_recognition_session_context.h"
-#include "content/public/common/speech_recognition_error.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h"
namespace media {
class AudioSystem;
@@ -76,10 +76,13 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl
void OnSoundEnd(int session_id) override;
void OnAudioEnd(int session_id) override;
void OnRecognitionEnd(int session_id) override;
- void OnRecognitionResults(int session_id,
- const SpeechRecognitionResults& result) override;
- void OnRecognitionError(int session_id,
- const SpeechRecognitionError& error) override;
+ void OnRecognitionResults(
+ int session_id,
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& result)
+ override;
+ void OnRecognitionError(
+ int session_id,
+ const blink::mojom::SpeechRecognitionError& error) override;
void OnAudioLevelsChange(int session_id,
float volume,
float noise_volume) override;
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.cc b/chromium/content/browser/speech/speech_recognizer_impl.cc
index e05b95b8d48..95b6834df4d 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl.cc
@@ -306,9 +306,9 @@ void SpeechRecognizerImpl::OnCaptureError(const std::string& message) {
}
void SpeechRecognizerImpl::OnSpeechRecognitionEngineResults(
- const SpeechRecognitionResults& results) {
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& results) {
FSMEventArgs event_args(EVENT_ENGINE_RESULT);
- event_args.engine_results = results;
+ event_args.engine_results = mojo::Clone(results);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&SpeechRecognizerImpl::DispatchEvent, this, event_args));
@@ -320,7 +320,7 @@ void SpeechRecognizerImpl::OnSpeechRecognitionEngineEndOfUtterance() {
}
void SpeechRecognizerImpl::OnSpeechRecognitionEngineError(
- const SpeechRecognitionError& error) {
+ const blink::mojom::SpeechRecognitionError& error) {
FSMEventArgs event_args(EVENT_ENGINE_ERROR);
event_args.engine_error = error;
BrowserThread::PostTask(
@@ -576,8 +576,9 @@ SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) {
if (!device_params_.IsValid()) {
DLOG(ERROR) << "Audio input device not found";
- return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE,
- SPEECH_AUDIO_ERROR_DETAILS_NO_MIC));
+ return Abort(blink::mojom::SpeechRecognitionError(
+ blink::mojom::SpeechRecognitionErrorCode::kAudioCapture,
+ blink::mojom::SpeechAudioErrorDetails::kNoMic));
}
// Audio converter shall provide audio based on these parameters as output.
@@ -670,7 +671,9 @@ SpeechRecognizerImpl::DetectUserSpeechOrTimeout(const FSMEventArgs&) {
listener()->OnSoundStart(session_id());
return STATE_RECOGNIZING;
} else if (GetElapsedTimeMs() >= kNoSpeechTimeoutMs) {
- return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_NO_SPEECH));
+ return Abort(blink::mojom::SpeechRecognitionError(
+ blink::mojom::SpeechRecognitionErrorCode::kNoSpeech,
+ blink::mojom::SpeechAudioErrorDetails::kNone));
}
return STATE_WAITING_FOR_SPEECH;
}
@@ -701,22 +704,27 @@ SpeechRecognizerImpl::FSMState
SpeechRecognizerImpl::AbortSilently(const FSMEventArgs& event_args) {
DCHECK_NE(event_args.event, EVENT_AUDIO_ERROR);
DCHECK_NE(event_args.event, EVENT_ENGINE_ERROR);
- return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_NONE));
+ return Abort(blink::mojom::SpeechRecognitionError(
+ blink::mojom::SpeechRecognitionErrorCode::kNone,
+ blink::mojom::SpeechAudioErrorDetails::kNone));
}
SpeechRecognizerImpl::FSMState
SpeechRecognizerImpl::AbortWithError(const FSMEventArgs& event_args) {
if (event_args.event == EVENT_AUDIO_ERROR) {
- return Abort(
- SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE));
+ return Abort(blink::mojom::SpeechRecognitionError(
+ blink::mojom::SpeechRecognitionErrorCode::kAudioCapture,
+ blink::mojom::SpeechAudioErrorDetails::kNone));
} else if (event_args.event == EVENT_ENGINE_ERROR) {
return Abort(event_args.engine_error);
}
- return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_ABORTED));
+ return Abort(blink::mojom::SpeechRecognitionError(
+ blink::mojom::SpeechRecognitionErrorCode::kAborted,
+ blink::mojom::SpeechAudioErrorDetails::kNone));
}
SpeechRecognizerImpl::FSMState SpeechRecognizerImpl::Abort(
- const SpeechRecognitionError& error) {
+ const blink::mojom::SpeechRecognitionError& error) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (IsCapturingAudio())
@@ -741,7 +749,7 @@ SpeechRecognizerImpl::FSMState SpeechRecognizerImpl::Abort(
if (state_ > STATE_STARTING && state_ < STATE_WAITING_FINAL_RESULT)
listener()->OnAudioEnd(session_id());
- if (error.code != SPEECH_RECOGNITION_ERROR_NONE)
+ if (error.code != blink::mojom::SpeechRecognitionErrorCode::kNone)
listener()->OnRecognitionError(session_id(), error);
listener()->OnRecognitionEnd(session_id());
@@ -772,17 +780,19 @@ SpeechRecognizerImpl::FSMState SpeechRecognizerImpl::ProcessIntermediateResult(
SpeechRecognizerImpl::FSMState
SpeechRecognizerImpl::ProcessFinalResult(const FSMEventArgs& event_args) {
- const SpeechRecognitionResults& results = event_args.engine_results;
- SpeechRecognitionResults::const_iterator i = results.begin();
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& results =
+ event_args.engine_results;
+ std::vector<blink::mojom::SpeechRecognitionResultPtr>::const_iterator i =
+ results.begin();
bool provisional_results_pending = false;
bool results_are_empty = true;
for (; i != results.end(); ++i) {
- const SpeechRecognitionResult& result = *i;
- if (result.is_provisional) {
+ const blink::mojom::SpeechRecognitionResultPtr& result = *i;
+ if (result->is_provisional) {
DCHECK(provisional_results_);
provisional_results_pending = true;
} else if (results_are_empty) {
- results_are_empty = result.hypotheses.empty();
+ results_are_empty = result->hypotheses.empty();
}
}
@@ -889,12 +899,16 @@ media::AudioCapturerSource* SpeechRecognizerImpl::GetAudioCapturerSource() {
SpeechRecognizerImpl::FSMEventArgs::FSMEventArgs(FSMEvent event_value)
: event(event_value),
audio_data(nullptr),
- engine_error(SPEECH_RECOGNITION_ERROR_NONE) {}
+ engine_error(blink::mojom::SpeechRecognitionErrorCode::kNone,
+ blink::mojom::SpeechAudioErrorDetails::kNone) {}
-SpeechRecognizerImpl::FSMEventArgs::FSMEventArgs(const FSMEventArgs& other) =
- default;
-
-SpeechRecognizerImpl::FSMEventArgs::~FSMEventArgs() {
+SpeechRecognizerImpl::FSMEventArgs::FSMEventArgs(const FSMEventArgs& other)
+ : event(other.event),
+ audio_data(other.audio_data),
+ engine_error(other.engine_error) {
+ engine_results = mojo::Clone(other.engine_results);
}
+SpeechRecognizerImpl::FSMEventArgs::~FSMEventArgs() {}
+
} // namespace content
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.h b/chromium/content/browser/speech/speech_recognizer_impl.h
index d489585409f..fd6d57b8b8f 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.h
+++ b/chromium/content/browser/speech/speech_recognizer_impl.h
@@ -14,10 +14,10 @@
#include "content/browser/speech/endpointer/endpointer.h"
#include "content/browser/speech/speech_recognition_engine.h"
#include "content/browser/speech/speech_recognizer.h"
-#include "content/public/common/speech_recognition_error.h"
-#include "content/public/common/speech_recognition_result.h"
#include "media/base/audio_capturer_source.h"
#include "net/url_request/url_request_context_getter.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h"
namespace media {
class AudioBus;
@@ -96,8 +96,8 @@ class CONTENT_EXPORT SpeechRecognizerImpl
FSMEvent event;
scoped_refptr<AudioChunk> audio_data;
- SpeechRecognitionResults engine_results;
- SpeechRecognitionError engine_error;
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> engine_results;
+ blink::mojom::SpeechRecognitionError engine_error;
};
~SpeechRecognizerImpl() override;
@@ -126,7 +126,7 @@ class CONTENT_EXPORT SpeechRecognizerImpl
FSMState ProcessFinalResult(const FSMEventArgs& event_args);
FSMState AbortSilently(const FSMEventArgs& event_args);
FSMState AbortWithError(const FSMEventArgs& event_args);
- FSMState Abort(const SpeechRecognitionError& error);
+ FSMState Abort(const blink::mojom::SpeechRecognitionError& error);
FSMState DetectEndOfSpeech(const FSMEventArgs& event_args);
FSMState DoNothing(const FSMEventArgs& event_args) const;
FSMState NotFeasible(const FSMEventArgs& event_args);
@@ -151,10 +151,11 @@ class CONTENT_EXPORT SpeechRecognizerImpl
// SpeechRecognitionEngineDelegate methods.
void OnSpeechRecognitionEngineResults(
- const SpeechRecognitionResults& results) override;
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& results)
+ override;
void OnSpeechRecognitionEngineEndOfUtterance() override;
void OnSpeechRecognitionEngineError(
- const SpeechRecognitionError& error) override;
+ const blink::mojom::SpeechRecognitionError& error) override;
media::AudioSystem* GetAudioSystem();
void CreateAudioCapturerSource();
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_android.cc b/chromium/content/browser/speech/speech_recognizer_impl_android.cc
index 5ca639cd1fd..a2f7a606f30 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_android.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_android.cc
@@ -16,8 +16,8 @@
#include "content/public/browser/speech_recognition_event_listener.h"
#include "content/public/browser/speech_recognition_manager.h"
#include "content/public/browser/speech_recognition_session_config.h"
-#include "content/public/common/speech_recognition_result.h"
#include "jni/SpeechRecognitionImpl_jni.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h"
using base::android::AppendJavaStringArrayToStringVector;
using base::android::AttachCurrentThread;
@@ -174,24 +174,24 @@ void SpeechRecognizerImplAndroid::OnRecognitionResults(
std::vector<float> scores(options.size(), 0.0);
if (floats != NULL)
JavaFloatArrayToFloatVector(env, floats, &scores);
- SpeechRecognitionResults results;
- results.push_back(SpeechRecognitionResult());
- SpeechRecognitionResult& result = results.back();
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results;
+ results.push_back(blink::mojom::SpeechRecognitionResult::New());
+ blink::mojom::SpeechRecognitionResultPtr& result = results.back();
CHECK_EQ(options.size(), scores.size());
for (size_t i = 0; i < options.size(); ++i) {
- result.hypotheses.push_back(SpeechRecognitionHypothesis(
+ result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
options[i], static_cast<double>(scores[i])));
}
- result.is_provisional = provisional;
+ result->is_provisional = provisional;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&SpeechRecognizerImplAndroid::OnRecognitionResultsOnIOThread, this,
- results));
+ std::move(results)));
}
void SpeechRecognizerImplAndroid::OnRecognitionResultsOnIOThread(
- SpeechRecognitionResults const &results) {
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
listener()->OnRecognitionResults(session_id(), results);
}
@@ -208,9 +208,11 @@ void SpeechRecognizerImplAndroid::OnRecognitionError(
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- SpeechRecognitionErrorCode code =
- static_cast<SpeechRecognitionErrorCode>(error);
- listener()->OnRecognitionError(session_id(), SpeechRecognitionError(code));
+ listener()->OnRecognitionError(
+ session_id(),
+ blink::mojom::SpeechRecognitionError(
+ static_cast<blink::mojom::SpeechRecognitionErrorCode>(error),
+ blink::mojom::SpeechAudioErrorDetails::kNone));
}
void SpeechRecognizerImplAndroid::OnRecognitionEnd(
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_android.h b/chromium/content/browser/speech/speech_recognizer_impl_android.h
index 9f12627dcac..c15356fec44 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_android.h
+++ b/chromium/content/browser/speech/speech_recognizer_impl_android.h
@@ -13,8 +13,8 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/browser/speech/speech_recognizer.h"
-#include "content/public/common/speech_recognition_error.h"
-#include "content/public/common/speech_recognition_result.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h"
namespace content {
@@ -61,7 +61,8 @@ class CONTENT_EXPORT SpeechRecognizerImplAndroid : public SpeechRecognizer {
void StartRecognitionOnUIThread(const std::string& language,
bool continuous,
bool interim_results);
- void OnRecognitionResultsOnIOThread(SpeechRecognitionResults const &results);
+ void OnRecognitionResultsOnIOThread(
+ std::vector<blink::mojom::SpeechRecognitionResultPtr> results);
~SpeechRecognizerImplAndroid() override;
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
index 21c79cb7445..0ef14a5d5ea 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -8,7 +8,10 @@
#include <vector>
#include "base/bind_helpers.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
+#include "base/stl_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/sys_byteorder.h"
#include "base/threading/thread.h"
@@ -26,9 +29,15 @@
#include "media/audio/test_audio_thread.h"
#include "media/base/audio_bus.h"
#include "media/base/test_helpers.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/data_pipe_utils.h"
#include "net/base/net_errors.h"
-#include "net/url_request/test_url_fetcher_factory.h"
-#include "net/url_request/url_request_status.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
using media::AudioInputStream;
@@ -70,11 +79,13 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
audio_ended_(false),
sound_started_(false),
sound_ended_(false),
- error_(SPEECH_RECOGNITION_ERROR_NONE),
+ error_(blink::mojom::SpeechRecognitionErrorCode::kNone),
volume_(-1.0f) {
// SpeechRecognizer takes ownership of sr_engine.
- SpeechRecognitionEngine* sr_engine =
- new SpeechRecognitionEngine(nullptr /* URLRequestContextGetter */);
+ SpeechRecognitionEngine* sr_engine = new SpeechRecognitionEngine(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ &url_loader_factory_),
+ nullptr /* URLRequestContextGetter */);
SpeechRecognitionEngine::Config config;
config.audio_num_bits_per_sample =
SpeechRecognizerImpl::kNumBitsPerAudioSample;
@@ -115,6 +126,31 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
audio_manager_->Shutdown();
}
+ bool GetUpstreamRequest(const network::TestURLLoaderFactory::PendingRequest**
+ pending_request_out) WARN_UNUSED_RESULT {
+ return GetPendingRequest(pending_request_out, "/up");
+ }
+
+ bool GetDownstreamRequest(
+ const network::TestURLLoaderFactory::PendingRequest** pending_request_out)
+ WARN_UNUSED_RESULT {
+ return GetPendingRequest(pending_request_out, "/down");
+ }
+
+ bool GetPendingRequest(
+ const network::TestURLLoaderFactory::PendingRequest** pending_request_out,
+ const char* url_substring) WARN_UNUSED_RESULT {
+ for (const auto& pending_request :
+ *url_loader_factory_.pending_requests()) {
+ if (pending_request.request.url.spec().find(url_substring) !=
+ std::string::npos) {
+ *pending_request_out = &pending_request;
+ return true;
+ }
+ }
+ return false;
+ }
+
void CheckEventsConsistency() {
// Note: "!x || y" == "x implies y".
EXPECT_TRUE(!recognition_ended_ || recognition_started_);
@@ -144,13 +180,16 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
CheckEventsConsistency();
}
- void OnRecognitionResults(int session_id,
- const SpeechRecognitionResults& results) override {
+ void OnRecognitionResults(
+ int session_id,
+ const std::vector<blink::mojom::SpeechRecognitionResultPtr>& results)
+ override {
result_received_ = true;
}
- void OnRecognitionError(int session_id,
- const SpeechRecognitionError& error) override {
+ void OnRecognitionError(
+ int session_id,
+ const blink::mojom::SpeechRecognitionError& error) override {
EXPECT_TRUE(recognition_started_);
EXPECT_FALSE(recognition_ended_);
error_ = error.code;
@@ -234,6 +273,7 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
protected:
TestBrowserThreadBundle thread_bundle_;
+ network::TestURLLoaderFactory url_loader_factory_;
scoped_refptr<SpeechRecognizerImpl> recognizer_;
std::unique_ptr<media::MockAudioManager> audio_manager_;
std::unique_ptr<media::AudioSystem> audio_system_;
@@ -245,8 +285,7 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
bool audio_ended_;
bool sound_started_;
bool sound_ended_;
- SpeechRecognitionErrorCode error_;
- net::TestURLFetcherFactory url_fetcher_factory_;
+ blink::mojom::SpeechRecognitionErrorCode error_;
std::vector<uint8_t> audio_packet_;
std::unique_ptr<media::AudioBus> audio_bus_;
int bytes_per_sample_;
@@ -265,7 +304,7 @@ TEST_F(SpeechRecognizerImplTest, StartNoInputDevices) {
EXPECT_TRUE(recognition_started_);
EXPECT_FALSE(audio_started_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kAudioCapture, error_);
CheckFinalEventsConsistency();
}
@@ -293,7 +332,7 @@ TEST_F(SpeechRecognizerImplTest, StopBeforeDeviceInfoReceived) {
EXPECT_TRUE(recognition_started_);
EXPECT_FALSE(audio_started_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
CheckFinalEventsConsistency();
}
@@ -321,7 +360,7 @@ TEST_F(SpeechRecognizerImplTest, CancelBeforeDeviceInfoReceived) {
EXPECT_TRUE(recognition_started_);
EXPECT_FALSE(audio_started_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
CheckFinalEventsConsistency();
}
@@ -336,7 +375,7 @@ TEST_F(SpeechRecognizerImplTest, StopNoData) {
EXPECT_TRUE(recognition_started_);
EXPECT_FALSE(audio_started_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
CheckFinalEventsConsistency();
}
@@ -352,7 +391,7 @@ TEST_F(SpeechRecognizerImplTest, CancelNoData) {
EXPECT_TRUE(recognition_started_);
EXPECT_FALSE(audio_started_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_ABORTED, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kAborted, error_);
CheckFinalEventsConsistency();
}
@@ -370,12 +409,56 @@ TEST_F(SpeechRecognizerImplTest, StopWithData) {
// that we are streaming out encoded data as chunks without waiting for the
// full recording to complete.
const size_t kNumChunks = 5;
+ network::mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter;
+ mojo::DataPipe data_pipe;
for (size_t i = 0; i < kNumChunks; ++i) {
Capture(audio_bus_.get());
- base::RunLoop().RunUntilIdle();
- net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
- ASSERT_TRUE(fetcher);
- EXPECT_EQ(i + 1, fetcher->upload_chunks().size());
+
+ if (i == 0) {
+ // Set up data channel to read chunked upload data. Must be done after the
+ // first OnData() call.
+ base::RunLoop().RunUntilIdle();
+ const network::TestURLLoaderFactory::PendingRequest* upstream_request;
+ ASSERT_TRUE(GetUpstreamRequest(&upstream_request));
+ ASSERT_TRUE(upstream_request->request.request_body);
+ ASSERT_EQ(1u, upstream_request->request.request_body->elements()->size());
+ ASSERT_EQ(
+ network::DataElement::TYPE_CHUNKED_DATA_PIPE,
+ (*upstream_request->request.request_body->elements())[0].type());
+ network::TestURLLoaderFactory::PendingRequest* mutable_upstream_request =
+ const_cast<network::TestURLLoaderFactory::PendingRequest*>(
+ upstream_request);
+ chunked_data_pipe_getter = (*mutable_upstream_request->request
+ .request_body->elements_mutable())[0]
+ .ReleaseChunkedDataPipeGetter();
+ chunked_data_pipe_getter->StartReading(
+ std::move(data_pipe.producer_handle));
+ }
+
+ std::string data;
+ while (true) {
+ base::RunLoop().RunUntilIdle();
+
+ const void* buffer;
+ uint32_t num_bytes;
+ MojoResult result = data_pipe.consumer_handle->BeginReadData(
+ &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
+ if (result == MOJO_RESULT_OK) {
+ data.append(static_cast<const char*>(buffer), num_bytes);
+ data_pipe.consumer_handle->EndReadData(num_bytes);
+ continue;
+ }
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ // Some data has already been read, assume there's no more to read.
+ if (!data.empty())
+ break;
+ continue;
+ }
+
+ FAIL() << "Mojo pipe closed unexpectedly";
+ }
+
+ EXPECT_FALSE(data.empty());
}
recognizer_->StopAudioCapture();
@@ -384,7 +467,7 @@ TEST_F(SpeechRecognizerImplTest, StopWithData) {
EXPECT_TRUE(audio_ended_);
EXPECT_FALSE(recognition_ended_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
// Create a response string.
proto::SpeechRecognitionEvent proto_event;
@@ -402,19 +485,15 @@ TEST_F(SpeechRecognizerImplTest, StopWithData) {
msg_string.insert(0, reinterpret_cast<char*>(&prefix), sizeof(prefix));
// Issue the network callback to complete the process.
- net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(
- SpeechRecognitionEngine::kDownstreamUrlFetcherIdForTesting);
- ASSERT_TRUE(fetcher);
- fetcher->set_url(fetcher->GetOriginalURL());
- fetcher->set_status(net::URLRequestStatus());
- fetcher->set_response_code(200);
- fetcher->SetResponseString(msg_string);
- fetcher->delegate()->OnURLFetchComplete(fetcher);
-
+ const network::TestURLLoaderFactory::PendingRequest* downstream_request;
+ ASSERT_TRUE(GetDownstreamRequest(&downstream_request));
+ url_loader_factory_.AddResponse(downstream_request->request.url.spec(),
+ msg_string);
base::RunLoop().RunUntilIdle();
+
EXPECT_TRUE(recognition_ended_);
EXPECT_TRUE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
CheckFinalEventsConsistency();
}
@@ -429,11 +508,12 @@ TEST_F(SpeechRecognizerImplTest, CancelWithData) {
base::RunLoop().RunUntilIdle();
recognizer_->AbortRecognition();
base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(url_fetcher_factory_.GetFetcherByID(0));
+ // There should be both upstream and downstream pending requests.
+ ASSERT_EQ(2u, url_loader_factory_.pending_requests()->size());
EXPECT_TRUE(recognition_started_);
EXPECT_TRUE(audio_started_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_ABORTED, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kAborted, error_);
CheckFinalEventsConsistency();
}
@@ -447,8 +527,8 @@ TEST_F(SpeechRecognizerImplTest, ConnectionError) {
base::RunLoop().RunUntilIdle(); // EVENT_START processing.
Capture(audio_bus_.get());
base::RunLoop().RunUntilIdle();
- net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
- ASSERT_TRUE(fetcher);
+ // There should be both upstream and downstream pending requests.
+ ASSERT_EQ(2u, url_loader_factory_.pending_requests()->size());
recognizer_->StopAudioCapture();
base::RunLoop().RunUntilIdle();
@@ -456,19 +536,19 @@ TEST_F(SpeechRecognizerImplTest, ConnectionError) {
EXPECT_TRUE(audio_ended_);
EXPECT_FALSE(recognition_ended_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
// Issue the network callback to complete the process.
- fetcher->set_url(fetcher->GetOriginalURL());
- fetcher->set_status(
- net::URLRequestStatus::FromError(net::ERR_CONNECTION_REFUSED));
- fetcher->set_response_code(0);
- fetcher->SetResponseString(std::string());
- fetcher->delegate()->OnURLFetchComplete(fetcher);
+ const network::TestURLLoaderFactory::PendingRequest* pending_request;
+ ASSERT_TRUE(GetUpstreamRequest(&pending_request));
+ url_loader_factory_.AddResponse(
+ pending_request->request.url, network::ResourceResponseHead(), "",
+ network::URLLoaderCompletionStatus(net::ERR_CONNECTION_REFUSED));
+
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_ended_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NETWORK, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNetwork, error_);
CheckFinalEventsConsistency();
}
@@ -482,8 +562,8 @@ TEST_F(SpeechRecognizerImplTest, ServerError) {
base::RunLoop().RunUntilIdle(); // EVENT_START processing.
Capture(audio_bus_.get());
base::RunLoop().RunUntilIdle();
- net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
- ASSERT_TRUE(fetcher);
+ // There should be both upstream and downstream pending requests.
+ ASSERT_EQ(2u, url_loader_factory_.pending_requests()->size());
recognizer_->StopAudioCapture();
base::RunLoop().RunUntilIdle();
@@ -491,18 +571,21 @@ TEST_F(SpeechRecognizerImplTest, ServerError) {
EXPECT_TRUE(audio_ended_);
EXPECT_FALSE(recognition_ended_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
+
+ const network::TestURLLoaderFactory::PendingRequest* pending_request;
+ ASSERT_TRUE(GetUpstreamRequest(&pending_request));
+ network::ResourceResponseHead response;
+ const char kHeaders[] = "HTTP/1.0 500 Internal Server Error";
+ response.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(kHeaders, base::size(kHeaders)));
+ url_loader_factory_.AddResponse(pending_request->request.url, response, "",
+ network::URLLoaderCompletionStatus());
- // Issue the network callback to complete the process.
- fetcher->set_url(fetcher->GetOriginalURL());
- fetcher->set_status(net::URLRequestStatus());
- fetcher->set_response_code(500);
- fetcher->SetResponseString("Internal Server Error");
- fetcher->delegate()->OnURLFetchComplete(fetcher);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_ended_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NETWORK, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNetwork, error_);
CheckFinalEventsConsistency();
}
@@ -519,7 +602,7 @@ TEST_F(SpeechRecognizerImplTest, OnCaptureError_PropagatesError) {
EXPECT_TRUE(recognition_started_);
EXPECT_FALSE(audio_started_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kAudioCapture, error_);
CheckFinalEventsConsistency();
}
@@ -542,7 +625,7 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackIssued) {
EXPECT_TRUE(recognition_started_);
EXPECT_TRUE(audio_started_);
EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NO_SPEECH, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNoSpeech, error_);
CheckFinalEventsConsistency();
}
@@ -571,7 +654,7 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackNotIssued) {
}
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
EXPECT_TRUE(audio_started_);
EXPECT_FALSE(audio_ended_);
EXPECT_FALSE(recognition_ended_);
@@ -612,7 +695,7 @@ TEST_F(SpeechRecognizerImplTest, SetInputVolumeCallback) {
EXPECT_NEAR(0.89926866f, volume_, 0.00001f);
EXPECT_FLOAT_EQ(0.75071919f, noise_volume_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
+ EXPECT_EQ(blink::mojom::SpeechRecognitionErrorCode::kNone, error_);
EXPECT_FALSE(audio_ended_);
EXPECT_FALSE(recognition_ended_);
recognizer_->AbortRecognition();
diff --git a/chromium/content/browser/startup_data_impl.cc b/chromium/content/browser/startup_data_impl.cc
new file mode 100644
index 00000000000..625dbe6672e
--- /dev/null
+++ b/chromium/content/browser/startup_data_impl.cc
@@ -0,0 +1,13 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/startup_data_impl.h"
+
+namespace content {
+
+StartupDataImpl::StartupDataImpl() = default;
+
+StartupDataImpl::~StartupDataImpl() = default;
+
+} // namespace content
diff --git a/chromium/content/browser/startup_data_impl.h b/chromium/content/browser/startup_data_impl.h
new file mode 100644
index 00000000000..e3f06271c27
--- /dev/null
+++ b/chromium/content/browser/startup_data_impl.h
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium Authors. All 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_STARTUP_DATA_IMPL_H_
+#define CONTENT_BROWSER_STARTUP_DATA_IMPL_H_
+
+#include <memory>
+
+#include "content/browser/browser_process_sub_thread.h"
+#include "content/public/browser/startup_data.h"
+
+namespace content {
+
+// The browser implementation of StartupData.
+struct StartupDataImpl : public StartupData {
+ StartupDataImpl();
+ ~StartupDataImpl() override;
+
+ // TODO(hanxi): add ServiceManagerContext* here.
+ std::unique_ptr<BrowserProcessSubThread> thread;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_STARTUP_DATA_IMPL_H_
diff --git a/chromium/content/browser/startup_task_runner.cc b/chromium/content/browser/startup_task_runner.cc
index 36259dd2ec7..319bc8f10b4 100644
--- a/chromium/content/browser/startup_task_runner.cc
+++ b/chromium/content/browser/startup_task_runner.cc
@@ -10,9 +10,10 @@
namespace content {
StartupTaskRunner::StartupTaskRunner(
- base::Callback<void(int)> const startup_complete_callback,
+ base::OnceCallback<void(int)> startup_complete_callback,
scoped_refptr<base::SingleThreadTaskRunner> proxy)
- : startup_complete_callback_(startup_complete_callback), proxy_(proxy) {}
+ : startup_complete_callback_(std::move(startup_complete_callback)),
+ proxy_(proxy) {}
StartupTaskRunner::~StartupTaskRunner() {}
@@ -25,9 +26,7 @@ void StartupTaskRunner::StartRunningTasksAsync() {
int result = 0;
if (task_list_.empty()) {
if (!startup_complete_callback_.is_null()) {
- startup_complete_callback_.Run(result);
- // Clear the callback to prevent it being called a second time
- startup_complete_callback_.Reset();
+ std::move(startup_complete_callback_).Run(result);
}
} else {
const base::Closure next_task =
@@ -46,9 +45,7 @@ void StartupTaskRunner::RunAllTasksNow() {
}
task_list_.clear();
if (!startup_complete_callback_.is_null()) {
- startup_complete_callback_.Run(result);
- // Clear the callback to prevent it being called a second time
- startup_complete_callback_.Reset();
+ std::move(startup_complete_callback_).Run(result);
}
}
@@ -67,9 +64,7 @@ void StartupTaskRunner::WrappedTask() {
}
if (task_list_.empty()) {
if (!startup_complete_callback_.is_null()) {
- startup_complete_callback_.Run(result);
- // Clear the callback to prevent it being called a second time
- startup_complete_callback_.Reset();
+ std::move(startup_complete_callback_).Run(result);
}
} else {
const base::Closure next_task =
diff --git a/chromium/content/browser/startup_task_runner.h b/chromium/content/browser/startup_task_runner.h
index c5f09f66e45..a38776d147e 100644
--- a/chromium/content/browser/startup_task_runner.h
+++ b/chromium/content/browser/startup_task_runner.h
@@ -37,7 +37,7 @@ class CONTENT_EXPORT StartupTaskRunner {
public:
// Constructor: Note that |startup_complete_callback| is optional. If it is
// not null it will be called once all the startup tasks have run.
- StartupTaskRunner(base::Callback<void(int)> startup_complete_callback,
+ StartupTaskRunner(base::OnceCallback<void(int)> startup_complete_callback,
scoped_refptr<base::SingleThreadTaskRunner> proxy);
~StartupTaskRunner();
@@ -57,7 +57,7 @@ class CONTENT_EXPORT StartupTaskRunner {
std::list<StartupTask> task_list_;
void WrappedTask();
- base::Callback<void(int)> startup_complete_callback_;
+ base::OnceCallback<void(int)> startup_complete_callback_;
scoped_refptr<base::SingleThreadTaskRunner> proxy_;
DISALLOW_COPY_AND_ASSIGN(StartupTaskRunner);
diff --git a/chromium/content/browser/startup_task_runner_unittest.cc b/chromium/content/browser/startup_task_runner_unittest.cc
index 738940a0a07..3e7857c212b 100644
--- a/chromium/content/browser/startup_task_runner_unittest.cc
+++ b/chromium/content/browser/startup_task_runner_unittest.cc
@@ -116,7 +116,7 @@ TEST_F(StartupTaskRunnerTest, SynchronousExecution) {
EXPECT_CALL(mock_runner, PostDelayedTask(_, _)).Times(0);
EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _)).Times(0);
- StartupTaskRunner runner(base::Bind(&Observer), proxy);
+ StartupTaskRunner runner(base::BindOnce(&Observer), proxy);
StartupTask task1 =
base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
@@ -154,7 +154,7 @@ TEST_F(StartupTaskRunnerTest, NullObserver) {
EXPECT_CALL(mock_runner, PostDelayedTask(_, _)).Times(0);
EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _)).Times(0);
- StartupTaskRunner runner(base::Callback<void(int)>(), proxy);
+ StartupTaskRunner runner(base::OnceCallback<void(int)>(), proxy);
StartupTask task1 =
base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
@@ -189,7 +189,7 @@ TEST_F(StartupTaskRunnerTest, SynchronousExecutionFailedTask) {
EXPECT_CALL(mock_runner, PostDelayedTask(_, _)).Times(0);
EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _)).Times(0);
- StartupTaskRunner runner(base::Bind(&Observer), proxy);
+ StartupTaskRunner runner(base::BindOnce(&Observer), proxy);
StartupTask task3 =
base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this));
@@ -230,7 +230,7 @@ TEST_F(StartupTaskRunnerTest, AsynchronousExecution) {
.Times(testing::Between(2, 3))
.WillRepeatedly(testing::Return(true));
- StartupTaskRunner runner(base::Bind(&Observer), proxy);
+ StartupTaskRunner runner(base::BindOnce(&Observer), proxy);
StartupTask task1 =
base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
@@ -276,7 +276,7 @@ TEST_F(StartupTaskRunnerTest, AsynchronousExecutionFailedTask) {
.Times(testing::Between(1, 2))
.WillRepeatedly(testing::Return(true));
- StartupTaskRunner runner(base::Bind(&Observer), proxy);
+ StartupTaskRunner runner(base::BindOnce(&Observer), proxy);
StartupTask task3 =
base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this));
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index b9165dd4ab7..ab6a04d6ec9 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -53,6 +53,7 @@
#include "services/network/cookie_manager.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
+#include "services/network/public/cpp/cross_thread_shared_url_loader_factory_info.h"
#include "services/network/public/cpp/features.h"
#include "services/service_manager/public/cpp/connector.h"
#include "storage/browser/blob/blob_registry_impl.h"
@@ -221,12 +222,6 @@ void ClearSessionStorageOnUIThread(
special_storage_policy, origin_matcher, callback));
}
-base::WeakPtr<storage::BlobStorageContext> BlobStorageContextGetterForStorage(
- scoped_refptr<ChromeBlobStorageContext> blob_context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return blob_context->context()->AsWeakPtr();
-}
-
} // namespace
// Class to own the NetworkContext wrapping a storage partitions
@@ -296,9 +291,9 @@ class StoragePartitionImpl::URLLoaderFactoryForBrowserProcess
// SharedURLLoaderFactory implementation:
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override {
- NOTREACHED() << "This isn't supported. If you need a SharedURLLoaderFactory"
- " on the IO thread, get it from URLLoaderFactoryGetter.";
- return nullptr;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ return std::make_unique<network::CrossThreadSharedURLLoaderFactoryInfo>(
+ this);
}
void Shutdown() { storage_partition_ = nullptr; }
@@ -539,6 +534,9 @@ StoragePartitionImpl::~StoragePartitionImpl() {
if (GetPaymentAppContext())
GetPaymentAppContext()->Shutdown();
+ if (GetBackgroundFetchContext())
+ GetBackgroundFetchContext()->Shutdown();
+
if (GetAppCacheService()) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
@@ -609,7 +607,7 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->service_worker_context_->set_storage_partition(partition.get());
partition->shared_worker_service_ = std::make_unique<SharedWorkerServiceImpl>(
- partition->service_worker_context_);
+ partition.get(), partition->service_worker_context_);
partition->appcache_service_ =
new ChromeAppCacheService(quota_manager_proxy.get());
@@ -630,7 +628,9 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->web_package_context_ = std::make_unique<WebPackageContextImpl>();
partition->background_fetch_context_ =
- new BackgroundFetchContext(context, partition->service_worker_context_);
+ base::MakeRefCounted<BackgroundFetchContext>(
+ context, partition->service_worker_context_,
+ partition->cache_storage_context_);
partition->background_sync_context_ =
base::MakeRefCounted<BackgroundSyncContext>();
@@ -646,14 +646,6 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
scoped_refptr<ChromeBlobStorageContext> blob_context =
ChromeBlobStorageContext::GetFor(context);
- if (base::FeatureList::IsEnabled(network::features::kNetworkService) ||
- ServiceWorkerUtils::IsServicificationEnabled()) {
- BlobURLLoaderFactory::BlobContextGetter blob_getter =
- base::BindOnce(&BlobStorageContextGetterForStorage, blob_context);
- partition->blob_url_loader_factory_ =
- BlobURLLoaderFactory::Create(std::move(blob_getter));
- }
-
partition->url_loader_factory_getter_ = new URLLoaderFactoryGetter();
partition->url_loader_factory_getter_->Initialize(partition.get());
@@ -668,8 +660,7 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->url_loader_factory_getter_.get());
partition->prefetch_url_loader_service_ =
- base::MakeRefCounted<PrefetchURLLoaderService>(
- partition->url_loader_factory_getter_);
+ base::MakeRefCounted<PrefetchURLLoaderService>();
partition->cookie_store_context_ = base::MakeRefCounted<CookieStoreContext>();
// Unit tests use the Initialize() callback to crash early if restoring the
@@ -827,10 +818,6 @@ StoragePartitionImpl::GetBluetoothAllowedDevicesMap() {
return bluetooth_allowed_devices_map_.get();
}
-BlobURLLoaderFactory* StoragePartitionImpl::GetBlobURLLoaderFactory() {
- return blob_url_loader_factory_.get();
-}
-
BlobRegistryWrapper* StoragePartitionImpl::GetBlobRegistry() {
return blob_registry_.get();
}
@@ -845,7 +832,7 @@ CookieStoreContext* StoragePartitionImpl::GetCookieStoreContext() {
void StoragePartitionImpl::OpenLocalStorage(
const url::Origin& origin,
- mojom::LevelDBWrapperRequest request) {
+ blink::mojom::StorageAreaRequest request) {
int process_id = bindings_.dispatch_context();
if (!ChildProcessSecurityPolicy::GetInstance()->CanAccessDataForOrigin(
process_id, origin.GetURL())) {
@@ -858,7 +845,7 @@ void StoragePartitionImpl::OpenLocalStorage(
void StoragePartitionImpl::OpenSessionStorage(
const std::string& namespace_id,
- mojom::SessionStorageNamespaceRequest request) {
+ blink::mojom::SessionStorageNamespaceRequest request) {
int process_id = bindings_.dispatch_context();
dom_storage_context_->OpenSessionStorage(process_id, namespace_id,
std::move(request));
@@ -1210,13 +1197,17 @@ void StoragePartitionImpl::WaitForDeletionTasksForTesting() {
}
}
+void StoragePartitionImpl::ResetURLLoaderFactoryForBrowserProcessForTesting() {
+ url_loader_factory_for_browser_process_.reset();
+}
+
BrowserContext* StoragePartitionImpl::browser_context() const {
return browser_context_;
}
mojo::BindingId StoragePartitionImpl::Bind(
int process_id,
- mojo::InterfaceRequest<mojom::StoragePartitionService> request) {
+ mojo::InterfaceRequest<blink::mojom::StoragePartitionService> request) {
return bindings_.AddBinding(this, std::move(request), process_id);
}
@@ -1248,9 +1239,12 @@ void StoragePartitionImpl::GetQuotaSettings(
network::mojom::URLLoaderFactory*
StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessInternal() {
- // Create the URLLoaderFactory as needed.
+ // Create the URLLoaderFactory as needed, but make sure not to reuse a
+ // previously created one if the test override has changed.
if (url_loader_factory_for_browser_process_ &&
- !url_loader_factory_for_browser_process_.encountered_error()) {
+ !url_loader_factory_for_browser_process_.encountered_error() &&
+ is_test_url_loader_factory_for_browser_process_ !=
+ g_url_loader_factory_callback_for_test.Get().is_null()) {
return url_loader_factory_for_browser_process_.get();
}
@@ -1258,10 +1252,16 @@ StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessInternal() {
network::mojom::URLLoaderFactoryParams::New();
params->process_id = network::mojom::kBrowserProcessId;
params->is_corb_enabled = false;
+ params->disable_web_security =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity);
if (g_url_loader_factory_callback_for_test.Get().is_null()) {
- GetNetworkContext()->CreateURLLoaderFactory(
- mojo::MakeRequest(&url_loader_factory_for_browser_process_),
- std::move(params));
+ auto request = mojo::MakeRequest(&url_loader_factory_for_browser_process_);
+ GetContentClient()->browser()->WillCreateURLLoaderFactory(
+ browser_context(), nullptr, false /* is_navigation */, &request);
+ GetNetworkContext()->CreateURLLoaderFactory(std::move(request),
+ std::move(params));
+ is_test_url_loader_factory_for_browser_process_ = false;
return url_loader_factory_for_browser_process_.get();
}
@@ -1271,6 +1271,7 @@ StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessInternal() {
url_loader_factory_for_browser_process_ =
g_url_loader_factory_callback_for_test.Get().Run(
std::move(original_factory));
+ is_test_url_loader_factory_for_browser_process_ = true;
return url_loader_factory_for_browser_process_.get();
}
diff --git a/chromium/content/browser/storage_partition_impl.h b/chromium/content/browser/storage_partition_impl.h
index 102e3ff8e47..e79f8775a1b 100644
--- a/chromium/content/browser/storage_partition_impl.h
+++ b/chromium/content/browser/storage_partition_impl.h
@@ -18,7 +18,6 @@
#include "base/process/process_handle.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/background_sync/background_sync_context.h"
-#include "content/browser/blob_storage/blob_url_loader_factory.h"
#include "content/browser/bluetooth/bluetooth_allowed_devices_map.h"
#include "content/browser/broadcast_channel/broadcast_channel_provider.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
@@ -32,12 +31,12 @@
#include "content/browser/shared_worker/shared_worker_service_impl.h"
#include "content/browser/url_loader_factory_getter.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 "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "storage/browser/quota/special_storage_policy.h"
+#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom.h"
#if !defined(OS_ANDROID)
#include "content/browser/host_zoom_level_context.h"
@@ -48,13 +47,12 @@ namespace content {
class BackgroundFetchContext;
class CookieStoreContext;
class BlobRegistryWrapper;
-class BlobURLLoaderFactory;
class PrefetchURLLoaderService;
class WebPackageContextImpl;
class CONTENT_EXPORT StoragePartitionImpl
: public StoragePartition,
- public mojom::StoragePartitionService {
+ public blink::mojom::StoragePartitionService {
public:
// It is guaranteed that storage partitions are destructed before the
// browser context starts shutting down its corresponding IO thread residents
@@ -134,23 +132,23 @@ class CONTENT_EXPORT StoragePartitionImpl
void ClearBluetoothAllowedDevicesMapForTesting() override;
void FlushNetworkInterfaceForTesting() override;
void WaitForDeletionTasksForTesting() override;
+ void ResetURLLoaderFactoryForBrowserProcessForTesting() override;
BackgroundFetchContext* GetBackgroundFetchContext();
BackgroundSyncContext* GetBackgroundSyncContext();
PaymentAppContextImpl* GetPaymentAppContext();
BroadcastChannelProvider* GetBroadcastChannelProvider();
BluetoothAllowedDevicesMap* GetBluetoothAllowedDevicesMap();
- BlobURLLoaderFactory* GetBlobURLLoaderFactory();
BlobRegistryWrapper* GetBlobRegistry();
PrefetchURLLoaderService* GetPrefetchURLLoaderService();
CookieStoreContext* GetCookieStoreContext();
- // mojom::StoragePartitionService interface.
+ // blink::mojom::StoragePartitionService interface.
void OpenLocalStorage(const url::Origin& origin,
- mojom::LevelDBWrapperRequest request) override;
+ blink::mojom::StorageAreaRequest request) override;
void OpenSessionStorage(
const std::string& namespace_id,
- mojom::SessionStorageNamespaceRequest request) override;
+ blink::mojom::SessionStorageNamespaceRequest request) override;
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter() {
return url_loader_factory_getter_;
@@ -163,7 +161,7 @@ class CONTENT_EXPORT StoragePartitionImpl
// binding.
mojo::BindingId Bind(
int process_id,
- mojo::InterfaceRequest<mojom::StoragePartitionService> request);
+ mojo::InterfaceRequest<blink::mojom::StoragePartitionService> request);
auto& bindings_for_testing() { return bindings_; }
@@ -309,7 +307,6 @@ class CONTENT_EXPORT StoragePartitionImpl
scoped_refptr<PaymentAppContextImpl> payment_app_context_;
scoped_refptr<BroadcastChannelProvider> broadcast_channel_provider_;
scoped_refptr<BluetoothAllowedDevicesMap> bluetooth_allowed_devices_map_;
- scoped_refptr<BlobURLLoaderFactory> blob_url_loader_factory_;
scoped_refptr<BlobRegistryWrapper> blob_registry_;
scoped_refptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
scoped_refptr<CookieStoreContext> cookie_store_context_;
@@ -317,7 +314,7 @@ class CONTENT_EXPORT StoragePartitionImpl
// BindingSet for StoragePartitionService, using the process id as the
// binding context type. The process id can subsequently be used during
// interface method calls to enforce security checks.
- mojo::BindingSet<mojom::StoragePartitionService, int> bindings_;
+ mojo::BindingSet<blink::mojom::StoragePartitionService, int> bindings_;
// This is the NetworkContext used to
// make requests for the StoragePartition. When the network service is
@@ -335,7 +332,8 @@ class CONTENT_EXPORT StoragePartitionImpl
// StoragePartition::GetURLLoaderFactoryForBrowserProcess() for
// more details
network::mojom::URLLoaderFactoryPtr url_loader_factory_for_browser_process_;
- ::network::mojom::CookieManagerPtr cookie_manager_for_browser_process_;
+ bool is_test_url_loader_factory_for_browser_process_ = false;
+ network::mojom::CookieManagerPtr cookie_manager_for_browser_process_;
// When the network service is disabled, a NetworkContext is created on the IO
// thread that wraps access to the URLRequestContext.
diff --git a/chromium/content/browser/storage_partition_impl_browsertest.cc b/chromium/content/browser/storage_partition_impl_browsertest.cc
index e2d5a2c13db..a1f42c9a6be 100644
--- a/chromium/content/browser/storage_partition_impl_browsertest.cc
+++ b/chromium/content/browser/storage_partition_impl_browsertest.cc
@@ -6,20 +6,25 @@
#include <string>
+#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/content_browser_test.h"
+#include "content/public/test/simple_url_loader_test_helper.h"
+#include "content/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
#include "content/test/storage_partition_test_utils.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/http/http_response_headers.h"
+#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/resource_response_info.h"
+#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
@@ -29,6 +34,8 @@
namespace content {
+namespace {
+
enum class NetworkServiceState {
kDisabled,
kEnabled,
@@ -54,6 +61,39 @@ class StoragePartititionImplBrowsertest
base::test::ScopedFeatureList feature_list_;
};
+// Creates a SimpleURLLoader and starts it to download |url|. Blocks until the
+// load is complete.
+std::unique_ptr<network::SimpleURLLoader> DownloadUrl(
+ const GURL& url,
+ StoragePartition* partition) {
+ auto request = std::make_unique<network::ResourceRequest>();
+ request->url = url;
+ std::unique_ptr<network::SimpleURLLoader> url_loader =
+ network::SimpleURLLoader::Create(std::move(request),
+ TRAFFIC_ANNOTATION_FOR_TESTS);
+ SimpleURLLoaderTestHelper url_loader_helper;
+ url_loader->DownloadToString(
+ partition->GetURLLoaderFactoryForBrowserProcess().get(),
+ url_loader_helper.GetCallback(),
+ /*max_body_size=*/1024 * 1024);
+ url_loader_helper.WaitForCallback();
+ return url_loader;
+}
+
+void CheckSimpleURLLoaderState(network::SimpleURLLoader* url_loader,
+ int net_error,
+ net::HttpStatusCode http_status_code) {
+ EXPECT_EQ(net_error, url_loader->NetError());
+ if (net_error != net::OK)
+ return;
+ ASSERT_TRUE(url_loader->ResponseInfo());
+ ASSERT_TRUE(url_loader->ResponseInfo()->headers);
+ EXPECT_EQ(http_status_code,
+ url_loader->ResponseInfo()->headers->response_code());
+}
+
+} // namespace
+
// Make sure that the NetworkContext returned by a StoragePartition works, both
// with the network service enabled and with it disabled, when one is created
// that wraps the URLRequestContext created by the BrowserContext.
@@ -158,6 +198,54 @@ IN_PROC_BROWSER_TEST_P(StoragePartititionImplBrowsertest,
factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
}
+// Checks that the network::URLLoaderIntercpetor works as expected with the
+// SharedURLLoaderFactory returned by StoragePartititionImpl.
+IN_PROC_BROWSER_TEST_P(StoragePartititionImplBrowsertest,
+ URLLoaderInterceptor) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ const GURL kEchoUrl(embedded_test_server()->GetURL("/echo"));
+
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ std::unique_ptr<ShellBrowserContext> browser_context =
+ std::make_unique<ShellBrowserContext>(true, nullptr);
+ auto* partition =
+ BrowserContext::GetDefaultStoragePartition(browser_context.get());
+
+ // Run a request the first time without the interceptor set, as the
+ // StoragePartitionImpl lazily creates the factory and we want to make sure
+ // it will create a new one once the interceptor is set (and not simply reuse
+ // the cached one).
+ {
+ std::unique_ptr<network::SimpleURLLoader> url_loader =
+ DownloadUrl(kEchoUrl, partition);
+ CheckSimpleURLLoaderState(url_loader.get(), net::OK, net::HTTP_OK);
+ }
+
+ // Use a URLLoaderInterceptor to simulate an error.
+ {
+ URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
+ [&](URLLoaderInterceptor::RequestParams* params) -> bool {
+ if (params->url_request.url != kEchoUrl)
+ return false;
+ params->client->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_NOT_IMPLEMENTED));
+ return true;
+ }));
+ std::unique_ptr<network::SimpleURLLoader> url_loader =
+ DownloadUrl(kEchoUrl, partition);
+ CheckSimpleURLLoaderState(url_loader.get(), net::ERR_NOT_IMPLEMENTED,
+ net::HTTP_OK);
+ }
+
+ // Run one more time without the interceptor, we should be back to the
+ // original behavior.
+ {
+ std::unique_ptr<network::SimpleURLLoader> url_loader =
+ DownloadUrl(kEchoUrl, partition);
+ CheckSimpleURLLoaderState(url_loader.get(), net::OK, net::HTTP_OK);
+ }
+}
+
// NetworkServiceState::kEnabled currently DCHECKs on Android, as Android isn't
// expected to create extra processes.
#if defined(OS_ANDROID)
diff --git a/chromium/content/browser/storage_partition_impl_map.cc b/chromium/content/browser/storage_partition_impl_map.cc
index 3be6979bde8..9f56c4c29c5 100644
--- a/chromium/content/browser/storage_partition_impl_map.cc
+++ b/chromium/content/browser/storage_partition_impl_map.cc
@@ -586,6 +586,11 @@ void StoragePartitionImplMap::PostCreateInitialization(
browser_context_->GetResourceContext(),
base::RetainedRef(partition->GetURLRequestContext())));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&BackgroundFetchContext::InitializeOnIOThread,
+ partition->GetBackgroundFetchContext()));
+
// We do not call InitializeURLRequestContext() for media contexts because,
// other than the HTTP cache, the media contexts share the same backing
// objects as their associated "normal" request context. Thus, the previous
diff --git a/chromium/content/browser/tracing/background_memory_tracing_observer.cc b/chromium/content/browser/tracing/background_memory_tracing_observer.cc
index f3dd9e3cd08..cf1f294d09a 100644
--- a/chromium/content/browser/tracing/background_memory_tracing_observer.cc
+++ b/chromium/content/browser/tracing/background_memory_tracing_observer.cc
@@ -4,23 +4,10 @@
#include "content/browser/tracing/background_memory_tracing_observer.h"
-#include "base/trace_event/heap_profiler_event_filter.h"
-#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_request_args.h"
-#include "base/trace_event/trace_log.h"
-#include "content/browser/tracing/background_tracing_rule.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
-using base::trace_event::MemoryDumpManager;
-using base::trace_event::TraceConfig;
-using base::trace_event::TraceLog;
-
namespace content {
-namespace {
-const char kEnableHeapProfilerModeName[] = "enable_heap_profiler_mode";
-const char kBackgroundModeName[] = "background";
-const char kHeapProfilerCategoryFilter[] = "heap_profiler_category_filter";
-} // namespace
// static
BackgroundMemoryTracingObserver*
@@ -33,65 +20,9 @@ BackgroundMemoryTracingObserver::BackgroundMemoryTracingObserver() {}
BackgroundMemoryTracingObserver::~BackgroundMemoryTracingObserver() {}
void BackgroundMemoryTracingObserver::OnScenarioActivated(
- const BackgroundTracingConfigImpl* config) {
- if (!config) {
- DCHECK(!heap_profiling_enabled_);
- return;
- }
-
- const BackgroundTracingRule* heap_profiling_rule = nullptr;
- for (const auto& rule : config->rules()) {
- if (rule->category_preset() == BackgroundTracingConfigImpl::CategoryPreset::
- BENCHMARK_MEMORY_LIGHT &&
- rule->args()) {
- heap_profiling_rule = rule.get();
- break;
- }
- }
- if (!heap_profiling_rule)
- return;
- std::string mode;
- if (!heap_profiling_rule->args()->GetString(kEnableHeapProfilerModeName,
- &mode) ||
- mode != kBackgroundModeName) {
- return;
- }
-
- heap_profiling_enabled_ = true;
- // TODO(ssid): Add ability to enable profiling on all processes,
- // crbug.com/700245.
- MemoryDumpManager::GetInstance()->EnableHeapProfiling(
- base::trace_event::kHeapProfilingModeBackground);
+ const BackgroundTracingConfigImpl* config) {}
- std::string filter_string;
- if (base::trace_event::AllocationContextTracker::capture_mode() ==
- base::trace_event::AllocationContextTracker::CaptureMode::DISABLED ||
- (TraceLog::GetInstance()->enabled_modes() & TraceLog::FILTERING_MODE) ||
- !heap_profiling_rule->args()->GetString(kHeapProfilerCategoryFilter,
- &filter_string)) {
- return;
- }
- base::trace_event::TraceConfigCategoryFilter category_filter;
- category_filter.InitializeFromString(filter_string);
- TraceConfig::EventFilterConfig heap_profiler_filter_config(
- base::trace_event::HeapProfilerEventFilter::kName);
- heap_profiler_filter_config.SetCategoryFilter(category_filter);
- TraceConfig::EventFilters filters;
- filters.push_back(heap_profiler_filter_config);
- TraceConfig filtering_trace_config;
- filtering_trace_config.SetEventFilters(filters);
- TraceLog::GetInstance()->SetEnabled(filtering_trace_config,
- TraceLog::FILTERING_MODE);
-}
-
-void BackgroundMemoryTracingObserver::OnScenarioAborted() {
- if (!heap_profiling_enabled_)
- return;
- heap_profiling_enabled_ = false;
- MemoryDumpManager::GetInstance()->EnableHeapProfiling(
- base::trace_event::kHeapProfilingModeDisabled);
- TraceLog::GetInstance()->SetDisabled(TraceLog::FILTERING_MODE);
-}
+void BackgroundMemoryTracingObserver::OnScenarioAborted() {}
void BackgroundMemoryTracingObserver::OnTracingEnabled(
BackgroundTracingConfigImpl::CategoryPreset preset) {
diff --git a/chromium/content/browser/tracing/background_memory_tracing_observer.h b/chromium/content/browser/tracing/background_memory_tracing_observer.h
index a49b00e61bb..4123e45f4cd 100644
--- a/chromium/content/browser/tracing/background_memory_tracing_observer.h
+++ b/chromium/content/browser/tracing/background_memory_tracing_observer.h
@@ -19,16 +19,10 @@ class CONTENT_EXPORT BackgroundMemoryTracingObserver
void OnTracingEnabled(
BackgroundTracingConfigImpl::CategoryPreset preset) override;
- bool heap_profiling_enabled_for_testing() const {
- return heap_profiling_enabled_;
- }
-
private:
BackgroundMemoryTracingObserver();
~BackgroundMemoryTracingObserver() override;
- bool heap_profiling_enabled_ = false;
-
DISALLOW_COPY_AND_ASSIGN(BackgroundMemoryTracingObserver);
};
diff --git a/chromium/content/browser/tracing/background_memory_tracing_observer_unittest.cc b/chromium/content/browser/tracing/background_memory_tracing_observer_unittest.cc
deleted file mode 100644
index 68762c78c36..00000000000
--- a/chromium/content/browser/tracing/background_memory_tracing_observer_unittest.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights 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/background_memory_tracing_observer.h"
-
-#include "base/allocator/buildflags.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/message_loop/message_loop.h"
-#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/memory_dump_manager_test_utils.h"
-#include "base/trace_event/trace_log.h"
-#include "build/build_config.h"
-#include "content/browser/tracing/background_tracing_config_impl.h"
-#include "content/public/test/test_browser_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::trace_event::AllocationContextTracker;
-using base::trace_event::MemoryDumpManager;
-using base::trace_event::TraceConfig;
-using base::trace_event::TraceLog;
-using base::trace_event::InitializeMemoryDumpManagerForInProcessTesting;
-
-namespace content {
-namespace {
-
-std::unique_ptr<BackgroundTracingConfigImpl> ReadFromJSONString(
- const std::string& json_text) {
- std::unique_ptr<base::Value> json_value(base::JSONReader::Read(json_text));
-
- base::DictionaryValue* dict = nullptr;
- if (json_value)
- json_value->GetAsDictionary(&dict);
-
- std::unique_ptr<BackgroundTracingConfigImpl> config(
- static_cast<BackgroundTracingConfigImpl*>(
- BackgroundTracingConfig::FromDict(dict).release()));
- CHECK(config);
- return config;
-}
-
-} // namespace
-
-class BackgroundMemoryTracingObserverTest : public testing::Test {
- public:
- BackgroundMemoryTracingObserverTest()
- : ui_thread_(BrowserThread::UI, &message_loop_) {}
-
- void SetUp() override {
- mdm_ = MemoryDumpManager::CreateInstanceForTesting();
- InitializeMemoryDumpManagerForInProcessTesting(
- /*is_coordinator_process=*/false);
- }
-
- void TearDown() override { mdm_ = nullptr; }
-
- private:
- std::unique_ptr<MemoryDumpManager> mdm_;
- base::MessageLoop message_loop_;
- TestBrowserThread ui_thread_;
-};
-
-TEST_F(BackgroundMemoryTracingObserverTest, NoOpOnNonMemoryConfig) {
- auto* observer = BackgroundMemoryTracingObserver::GetInstance();
- auto config = ReadFromJSONString(
- "{\"mode\":\"REACTIVE_TRACING_MODE\", \"configs\": [{\"category\": "
- "\"BENCHMARK\", \"rule\": "
- "\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", "
- "\"histogram_name\":\"foo\", \"histogram_lower_value\": 1, "
- "\"histogram_upper_value\": 2}]}");
- observer->OnScenarioActivated(config.get());
- EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
- observer->OnTracingEnabled(BackgroundTracingConfigImpl::BENCHMARK);
- EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
- EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
- AllocationContextTracker::capture_mode());
-
- observer->OnScenarioAborted();
- EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
- EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
- EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
- AllocationContextTracker::capture_mode());
-}
-
-TEST_F(BackgroundMemoryTracingObserverTest, OnlyBackgroundDumpConfig) {
- auto* observer = BackgroundMemoryTracingObserver::GetInstance();
- auto config = ReadFromJSONString(
- "{\"mode\":\"REACTIVE_TRACING_MODE\", \"configs\": [{\"category\": "
- "\"BENCHMARK_MEMORY_LIGHT\", \"rule\": "
- "\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", "
- "\"histogram_name\":\"foo\", \"histogram_lower_value\": 1, "
- "\"histogram_upper_value\": 2}]}");
- observer->OnScenarioActivated(config.get());
- EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
- observer->OnTracingEnabled(BackgroundTracingConfigImpl::BENCHMARK);
- EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
- EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
- AllocationContextTracker::capture_mode());
-
- observer->OnScenarioAborted();
- EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
- EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
- EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
- AllocationContextTracker::capture_mode());
-}
-
-TEST_F(BackgroundMemoryTracingObserverTest, DISABLED_HeapProfilingConfig) {
- auto* observer = BackgroundMemoryTracingObserver::GetInstance();
- auto config = ReadFromJSONString(
- "{\"mode\":\"REACTIVE_TRACING_MODE\", \"configs\": [{\"category\": "
- "\"BENCHMARK_MEMORY_LIGHT\", \"rule\": "
- "\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", "
- "\"histogram_name\":\"foo\", \"histogram_lower_value\": 1, "
- "\"histogram_upper_value\": 2, \"args\": {\"enable_heap_profiler_mode\": "
- "\"background\"}}]}");
- observer->OnScenarioActivated(config.get());
- EXPECT_TRUE(observer->heap_profiling_enabled_for_testing());
- observer->OnTracingEnabled(BackgroundTracingConfigImpl::BENCHMARK);
- EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
-#if BUILDFLAG(USE_ALLOCATOR_SHIM) && !defined(OS_NACL)
- EXPECT_EQ(AllocationContextTracker::CaptureMode::PSEUDO_STACK,
- AllocationContextTracker::capture_mode());
-#else
- EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
- AllocationContextTracker::capture_mode());
-#endif
-
- observer->OnScenarioAborted();
- EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
- EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
- EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
- AllocationContextTracker::capture_mode());
-}
-
-TEST_F(BackgroundMemoryTracingObserverTest, DISABLED_HeapProfilingWithFilters) {
- auto* observer = BackgroundMemoryTracingObserver::GetInstance();
- auto config = ReadFromJSONString(
- "{\"mode\":\"REACTIVE_TRACING_MODE\", \"configs\": [{\"category\": "
- "\"BENCHMARK_MEMORY_LIGHT\", \"rule\": "
- "\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", "
- "\"histogram_name\":\"foo\", \"histogram_lower_value\": 1, "
- "\"histogram_upper_value\": 2, \"args\": {\"enable_heap_profiler_mode\": "
- "\"background\", \"heap_profiler_category_filter\": \"cat,dog\"}}]}");
- observer->OnScenarioActivated(config.get());
- EXPECT_TRUE(observer->heap_profiling_enabled_for_testing());
- observer->OnTracingEnabled(BackgroundTracingConfigImpl::BENCHMARK);
-#if BUILDFLAG(USE_ALLOCATOR_SHIM) && !defined(OS_NACL)
- EXPECT_EQ(AllocationContextTracker::CaptureMode::PSEUDO_STACK,
- AllocationContextTracker::capture_mode());
- EXPECT_EQ(TraceLog::FILTERING_MODE, TraceLog::GetInstance()->enabled_modes());
- const char kExpectedConfig[] =
- "{\"filter_predicate\":\"heap_profiler_predicate\","
- "\"included_categories\":[\"cat\",\"dog\"]}";
- auto trace_config = TraceLog::GetInstance()->GetCurrentTraceConfig();
- ASSERT_EQ(1u, trace_config.event_filters().size());
- base::DictionaryValue filter_dict;
- trace_config.event_filters()[0].ToDict(&filter_dict);
- std::string filter_str;
- base::JSONWriter::Write(filter_dict, &filter_str);
- EXPECT_EQ(kExpectedConfig, filter_str);
-#else // BUILDFLAG(USE_ALLOCATOR_SHIM) && !defined(OS_NACL)
- EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
- EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
- AllocationContextTracker::capture_mode());
-#endif // BUILDFLAG(USE_ALLOCATOR_SHIM) && !defined(OS_NACL)
-
- observer->OnScenarioAborted();
- EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
- EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
- EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
- AllocationContextTracker::capture_mode());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
index 374da5bb307..d419bace500 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
@@ -144,6 +144,10 @@ class BackgroundTracingManagerUploadConfigWrapper {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(callback_));
}
+ void SetUploadCallback(base::OnceClosure callback) {
+ callback_ = std::move(callback);
+ }
+
bool TraceHasMatchingString(const char* str) {
return last_file_contents_.find(str) != std::string::npos;
}
@@ -151,8 +155,9 @@ class BackgroundTracingManagerUploadConfigWrapper {
int get_receive_count() const { return receive_count_; }
BackgroundTracingManager::ReceiveCallback get_receive_callback() {
- return base::BindOnce(&BackgroundTracingManagerUploadConfigWrapper::Upload,
- base::Unretained(this));
+ return base::BindRepeating(
+ &BackgroundTracingManagerUploadConfigWrapper::Upload,
+ base::Unretained(this));
}
private:
@@ -1335,6 +1340,57 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
#if defined(OS_ANDROID)
// Flaky on android: https://crbug.com/639706
+#define MAYBE_ReactiveSecondUpload DISABLED_ReactiveSecondUpload
+#else
+#define MAYBE_ReactiveSecondUpload ReactiveSecondUpload
+#endif
+
+// This tests that reactive mode uploads on a second set of triggers.
+IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
+ MAYBE_ReactiveSecondUpload) {
+ {
+ SetupBackgroundTracingManager();
+
+ base::RunLoop run_loop;
+ BackgroundTracingManagerUploadConfigWrapper upload_config_wrapper(
+ run_loop.QuitClosure());
+
+ std::unique_ptr<BackgroundTracingConfig> config = CreateReactiveConfig();
+
+ BackgroundTracingManager::TriggerHandle handle =
+ BackgroundTracingManager::GetInstance()->RegisterTriggerType(
+ "reactive_test");
+
+ EXPECT_TRUE(BackgroundTracingManager::GetInstance()->SetActiveScenario(
+ std::move(config), upload_config_wrapper.get_receive_callback(),
+ BackgroundTracingManager::NO_DATA_FILTERING));
+
+ BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
+ handle, base::Bind(&StartedFinalizingCallback, base::Closure(), true));
+ // second trigger to terminate.
+ BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
+ handle, base::Bind(&StartedFinalizingCallback, base::Closure(), true));
+
+ run_loop.Run();
+
+ base::RunLoop second_upload_run_loop;
+ upload_config_wrapper.SetUploadCallback(
+ second_upload_run_loop.QuitClosure());
+
+ BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
+ handle, base::Bind(&StartedFinalizingCallback, base::Closure(), true));
+ // second trigger to terminate.
+ BackgroundTracingManager::GetInstance()->TriggerNamedEvent(
+ handle, base::Bind(&StartedFinalizingCallback, base::Closure(), true));
+
+ second_upload_run_loop.Run();
+
+ EXPECT_TRUE(upload_config_wrapper.get_receive_count() == 2);
+ }
+}
+
+#if defined(OS_ANDROID)
+// Flaky on android: https://crbug.com/639706
#define MAYBE_ReactiveSecondTriggerMustMatchForTermination \
DISABLED_ReactiveSecondTriggerMustMatchForTermination
#else
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.cc b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
index c6aefd65be1..30d131e9d11 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
@@ -507,11 +507,12 @@ void BackgroundTracingManagerImpl::OnFinalizeStarted(
file_contents->size() / 1024);
if (!receive_callback_.is_null()) {
- std::move(receive_callback_)
- .Run(file_contents, std::move(metadata),
- base::BindOnce(&BackgroundTracingManagerImpl::OnFinalizeComplete,
- base::Unretained(this)));
+ receive_callback_.Run(
+ file_contents, std::move(metadata),
+ base::BindOnce(&BackgroundTracingManagerImpl::OnFinalizeComplete,
+ base::Unretained(this)));
}
+
if (!started_finalizing_closure.is_null())
std::move(started_finalizing_closure).Run();
}
diff --git a/chromium/content/browser/tracing/cast_tracing_agent.cc b/chromium/content/browser/tracing/cast_tracing_agent.cc
index 41b62141455..29e016250bc 100644
--- a/chromium/content/browser/tracing/cast_tracing_agent.cc
+++ b/chromium/content/browser/tracing/cast_tracing_agent.cc
@@ -45,7 +45,8 @@ CastTracingAgent::CastTracingAgent(service_manager::Connector* connector)
: BaseAgent(connector,
"systemTraceEvents",
tracing::mojom::TraceDataType::STRING,
- false /* supports_explicit_clock_sync */) {
+ false /* supports_explicit_clock_sync */,
+ base::kNullProcessId) {
task_runner_ =
base::TaskScheduler::GetInstance()->CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND,
diff --git a/chromium/content/browser/tracing/cros_tracing_agent.cc b/chromium/content/browser/tracing/cros_tracing_agent.cc
index 30bb8757a81..7a1cb3536ab 100644
--- a/chromium/content/browser/tracing/cros_tracing_agent.cc
+++ b/chromium/content/browser/tracing/cros_tracing_agent.cc
@@ -26,7 +26,8 @@ CrOSTracingAgent::CrOSTracingAgent(service_manager::Connector* connector)
: BaseAgent(connector,
kCrOSTraceLabel,
tracing::mojom::TraceDataType::STRING,
- false /* supports_explicit_clock_sync */) {}
+ false /* supports_explicit_clock_sync */,
+ base::kNullProcessId) {}
CrOSTracingAgent::~CrOSTracingAgent() = default;
diff --git a/chromium/content/browser/tracing/etw_tracing_agent_win.cc b/chromium/content/browser/tracing/etw_tracing_agent_win.cc
index f25811775f2..94dba186e96 100644
--- a/chromium/content/browser/tracing/etw_tracing_agent_win.cc
+++ b/chromium/content/browser/tracing/etw_tracing_agent_win.cc
@@ -46,7 +46,8 @@ EtwTracingAgent::EtwTracingAgent(service_manager::Connector* connector)
: BaseAgent(connector,
kETWTraceLabel,
tracing::mojom::TraceDataType::OBJECT,
- false /* supports_explicit_clock_sync */),
+ false /* supports_explicit_clock_sync */,
+ base::kNullProcessId),
thread_("EtwConsumerThread"),
is_tracing_(false) {
DCHECK(!g_etw_tracing_agent);
diff --git a/chromium/content/browser/tracing/memory_instrumentation_browsertest.cc b/chromium/content/browser/tracing/memory_instrumentation_browsertest.cc
index 1eeb12aa138..564cadfff62 100644
--- a/chromium/content/browser/tracing/memory_instrumentation_browsertest.cc
+++ b/chromium/content/browser/tracing/memory_instrumentation_browsertest.cc
@@ -53,15 +53,16 @@ std::unique_ptr<GlobalMemoryDump> DoGlobalDump() {
std::unique_ptr<GlobalMemoryDump> result = nullptr;
base::RunLoop run_loop;
memory_instrumentation::MemoryInstrumentation::GetInstance()
- ->RequestGlobalDump(base::Bind(
- [](base::Closure quit_closure,
- std::unique_ptr<GlobalMemoryDump>* out_result, bool success,
- std::unique_ptr<GlobalMemoryDump> result) {
- EXPECT_TRUE(success);
- *out_result = std::move(result);
- std::move(quit_closure).Run();
- },
- run_loop.QuitClosure(), &result));
+ ->RequestGlobalDump(
+ {}, base::Bind(
+ [](base::Closure quit_closure,
+ std::unique_ptr<GlobalMemoryDump>* out_result,
+ bool success, std::unique_ptr<GlobalMemoryDump> result) {
+ EXPECT_TRUE(success);
+ *out_result = std::move(result);
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure(), &result));
run_loop.Run();
return result;
}
diff --git a/chromium/content/browser/tracing/power_tracing_agent.cc b/chromium/content/browser/tracing/power_tracing_agent.cc
index 2ae2a4d50da..c1b6bb29b29 100644
--- a/chromium/content/browser/tracing/power_tracing_agent.cc
+++ b/chromium/content/browser/tracing/power_tracing_agent.cc
@@ -43,9 +43,9 @@ PowerTracingAgent::PowerTracingAgent(service_manager::Connector* connector)
// Register this agent.
tracing::mojom::AgentPtr agent;
binding_.Bind(mojo::MakeRequest(&agent));
- agent_registry->RegisterAgent(std::move(agent), kPowerTraceLabel,
- tracing::mojom::TraceDataType::STRING,
- true /* supports_explicit_clock_sync */);
+ agent_registry->RegisterAgent(
+ std::move(agent), kPowerTraceLabel, tracing::mojom::TraceDataType::STRING,
+ true /* supports_explicit_clock_sync */, base::kNullProcessId);
}
PowerTracingAgent::PowerTracingAgent() : binding_(this) {}
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.cc b/chromium/content/browser/tracing/tracing_controller_impl.cc
index 0ae496ae61e..ee4fa86896e 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -21,11 +21,11 @@
#include "base/values.h"
#include "build/build_config.h"
#include "components/tracing/common/trace_startup_config.h"
+#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/tracing/file_tracing_provider_impl.h"
#include "content/browser/tracing/tracing_ui.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/browser/tracing_controller.h"
#include "content/public/browser/tracing_delegate.h"
#include "content/public/common/content_client.h"
@@ -236,14 +236,16 @@ TracingControllerImpl::GenerateMetadataDict() const {
metadata_dict->SetString("cpu-brand", cpu.cpu_brand());
// GPU
- gpu::GPUInfo gpu_info = content::GpuDataManager::GetInstance()->GetGPUInfo();
+ const gpu::GPUInfo gpu_info =
+ content::GpuDataManagerImpl::GetInstance()->GetGPUInfo();
+ const gpu::GPUInfo::GPUDevice& active_gpu = gpu_info.active_gpu();
#if !defined(OS_ANDROID)
- metadata_dict->SetInteger("gpu-venid", gpu_info.gpu.vendor_id);
- metadata_dict->SetInteger("gpu-devid", gpu_info.gpu.device_id);
+ metadata_dict->SetInteger("gpu-venid", active_gpu.vendor_id);
+ metadata_dict->SetInteger("gpu-devid", active_gpu.device_id);
#endif
- metadata_dict->SetString("gpu-driver", gpu_info.driver_version);
+ metadata_dict->SetString("gpu-driver", active_gpu.driver_version);
metadata_dict->SetString("gpu-psver", gpu_info.pixel_shader_version);
metadata_dict->SetString("gpu-vsver", gpu_info.vertex_shader_version);
@@ -321,8 +323,23 @@ bool TracingControllerImpl::StartTracing(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// TODO(chiniforooshan): The actual value should be received by callback and
// this function should return void.
- if (IsTracing())
- return false;
+ if (IsTracing()) {
+ // Do not allow updating trace config when process filter is not used.
+ if (trace_config.process_filter_config().empty() ||
+ trace_config_->process_filter_config().empty()) {
+ return false;
+ }
+ // Make sure other parts of trace_config (besides process filter)
+ // did not change.
+ base::trace_event::TraceConfig old_config_copy(*trace_config_);
+ base::trace_event::TraceConfig new_config_copy(trace_config);
+ old_config_copy.SetProcessFilterConfig(
+ base::trace_event::TraceConfig::ProcessFilterConfig());
+ new_config_copy.SetProcessFilterConfig(
+ base::trace_event::TraceConfig::ProcessFilterConfig());
+ if (old_config_copy.ToString() != new_config_copy.ToString())
+ return false;
+ }
trace_config_ =
std::make_unique<base::trace_event::TraceConfig>(trace_config);
coordinator_->StartTracing(
diff --git a/chromium/content/browser/url_loader_factory_getter.cc b/chromium/content/browser/url_loader_factory_getter.cc
index e0593366a2a..d3f03804253 100644
--- a/chromium/content/browser/url_loader_factory_getter.cc
+++ b/chromium/content/browser/url_loader_factory_getter.cc
@@ -8,10 +8,12 @@
#include <utility>
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/lazy_instance.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/common/content_switches.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/network_service.mojom.h"
@@ -114,13 +116,10 @@ URLLoaderFactoryGetter::URLLoaderFactoryGetter() {}
void URLLoaderFactoryGetter::Initialize(StoragePartitionImpl* partition) {
DCHECK(partition);
DCHECK(!pending_network_factory_request_.is_pending());
- DCHECK(!pending_blob_factory_request_.is_pending());
partition_ = partition;
network::mojom::URLLoaderFactoryPtr network_factory;
- network::mojom::URLLoaderFactoryPtr blob_factory;
pending_network_factory_request_ = MakeRequest(&network_factory);
- pending_blob_factory_request_ = mojo::MakeRequest(&blob_factory);
// If NetworkService is disabled, HandleFactoryRequests should be called after
// NetworkContext in |partition_| is ready.
@@ -130,26 +129,14 @@ void URLLoaderFactoryGetter::Initialize(StoragePartitionImpl* partition) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&URLLoaderFactoryGetter::InitializeOnIOThread, this,
- network_factory.PassInterface(),
- blob_factory.PassInterface()));
+ network_factory.PassInterface()));
}
void URLLoaderFactoryGetter::HandleFactoryRequests() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(pending_network_factory_request_.is_pending());
- DCHECK(pending_blob_factory_request_.is_pending());
HandleNetworkFactoryRequestOnUIThread(
std::move(pending_network_factory_request_));
-
- // |partition->blob_url_loader_factory_| is not available without the feature.
- if (base::FeatureList::IsEnabled(network::features::kNetworkService) ||
- ServiceWorkerUtils::IsServicificationEnabled()) {
- DCHECK(partition_->GetBlobURLLoaderFactory());
- partition_->GetBlobURLLoaderFactory()->HandleRequest(
- std::move(pending_blob_factory_request_));
- } else {
- pending_blob_factory_request_ = nullptr;
- }
}
void URLLoaderFactoryGetter::OnStoragePartitionDestroyed() {
@@ -195,11 +182,6 @@ void URLLoaderFactoryGetter::CloneNetworkFactory(
GetURLLoaderFactory()->Clone(std::move(network_factory_request));
}
-network::mojom::URLLoaderFactory* URLLoaderFactoryGetter::GetBlobFactory() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return blob_factory_.get();
-}
-
void URLLoaderFactoryGetter::SetNetworkFactoryForTesting(
network::mojom::URLLoaderFactory* test_factory) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -236,10 +218,8 @@ void URLLoaderFactoryGetter::FlushNetworkInterfaceForTesting() {
URLLoaderFactoryGetter::~URLLoaderFactoryGetter() {}
void URLLoaderFactoryGetter::InitializeOnIOThread(
- network::mojom::URLLoaderFactoryPtrInfo network_factory,
- network::mojom::URLLoaderFactoryPtrInfo blob_factory) {
+ network::mojom::URLLoaderFactoryPtrInfo network_factory) {
network_factory_.Bind(std::move(network_factory));
- blob_factory_.Bind(std::move(blob_factory));
}
void URLLoaderFactoryGetter::HandleNetworkFactoryRequestOnUIThread(
@@ -253,6 +233,9 @@ void URLLoaderFactoryGetter::HandleNetworkFactoryRequestOnUIThread(
network::mojom::URLLoaderFactoryParams::New();
params->process_id = network::mojom::kBrowserProcessId;
params->is_corb_enabled = false;
+ params->disable_web_security =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity);
partition_->GetNetworkContext()->CreateURLLoaderFactory(
std::move(network_factory_request), std::move(params));
}
diff --git a/chromium/content/browser/url_loader_factory_getter.h b/chromium/content/browser/url_loader_factory_getter.h
index da31f8cf52e..39bfbab5b7e 100644
--- a/chromium/content/browser/url_loader_factory_getter.h
+++ b/chromium/content/browser/url_loader_factory_getter.h
@@ -66,11 +66,6 @@ class URLLoaderFactoryGetter
CONTENT_EXPORT void CloneNetworkFactory(
network::mojom::URLLoaderFactoryRequest network_factory_request);
- // Called on the IO thread to get the URLLoaderFactory to the blob service.
- // Must be used only if the network service or servicified service worker is
- // enabled. The pointer shouldn't be cached.
- CONTENT_EXPORT network::mojom::URLLoaderFactory* GetBlobFactory();
-
// Overrides the network URLLoaderFactory for subsequent requests. Passing a
// null pointer will restore the default behavior.
CONTENT_EXPORT void SetNetworkFactoryForTesting(
@@ -102,8 +97,7 @@ class URLLoaderFactoryGetter
CONTENT_EXPORT ~URLLoaderFactoryGetter();
void InitializeOnIOThread(
- network::mojom::URLLoaderFactoryPtrInfo network_factory,
- network::mojom::URLLoaderFactoryPtrInfo blob_factory);
+ network::mojom::URLLoaderFactoryPtrInfo network_factory);
// Send |network_factory_request| to cached |StoragePartitionImpl|.
void HandleNetworkFactoryRequestOnUIThread(
@@ -118,11 +112,9 @@ class URLLoaderFactoryGetter
// Bound with appropriate URLLoaderFactories at HandleFactoryRequests().
network::mojom::URLLoaderFactoryRequest pending_network_factory_request_;
- network::mojom::URLLoaderFactoryRequest pending_blob_factory_request_;
// Only accessed on IO thread.
network::mojom::URLLoaderFactoryPtr network_factory_;
- network::mojom::URLLoaderFactoryPtr blob_factory_;
network::mojom::URLLoaderFactory* test_factory_ = nullptr;
// Used to re-create |network_factory_| when connection error happens. Can
diff --git a/chromium/content/browser/utility_process_host.cc b/chromium/content/browser/utility_process_host.cc
index 3b6dfc16d83..9d7c9791bd9 100644
--- a/chromium/content/browser/utility_process_host.cc
+++ b/chromium/content/browser/utility_process_host.cc
@@ -11,6 +11,7 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
+#include "base/i18n/base_i18n_switches.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "components/network_session_configurator/common/network_switches.h"
@@ -41,6 +42,7 @@
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_types.h"
+#include "services/audio/audio_sandbox_win.h"
#include "services/network/network_sandbox_win.h"
#endif
@@ -74,7 +76,8 @@ class UtilitySandboxedProcessLauncherDelegate
sandbox_type_ == service_manager::SANDBOX_TYPE_CDM ||
sandbox_type_ == service_manager::SANDBOX_TYPE_PDF_COMPOSITOR ||
sandbox_type_ == service_manager::SANDBOX_TYPE_PROFILING ||
- sandbox_type_ == service_manager::SANDBOX_TYPE_PPAPI;
+ sandbox_type_ == service_manager::SANDBOX_TYPE_PPAPI ||
+ sandbox_type_ == service_manager::SANDBOX_TYPE_AUDIO;
DCHECK(supported_sandbox_type);
#endif // DCHECK_IS_ON()
}
@@ -91,6 +94,9 @@ class UtilitySandboxedProcessLauncherDelegate
if (sandbox_type_ == service_manager::SANDBOX_TYPE_NETWORK)
return network::NetworkPreSpawnTarget(policy);
+ if (sandbox_type_ == service_manager::SANDBOX_TYPE_AUDIO)
+ return audio::AudioPreSpawnTarget(policy);
+
return true;
}
#endif // OS_WIN
@@ -187,6 +193,10 @@ void UtilityProcessHost::BindInterface(
std::move(interface_pipe));
}
+void UtilityProcessHost::SetMetricsName(const std::string& metrics_name) {
+ metrics_name_ = metrics_name;
+}
+
void UtilityProcessHost::SetName(const base::string16& name) {
name_ = name;
}
@@ -208,6 +218,7 @@ bool UtilityProcessHost::StartProcess() {
started_ = true;
process_->SetName(name_);
+ process_->SetMetricsName(metrics_name_);
process_->GetHost()->CreateChannelMojo();
if (RenderProcessHost::run_renderer_in_process()) {
@@ -217,7 +228,7 @@ bool UtilityProcessHost::StartProcess() {
in_process_thread_.reset(
g_utility_main_thread_factory(InProcessChildThreadParams(
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- process_->GetInProcessBrokerClientInvitation(),
+ process_->GetInProcessMojoInvitation(),
process_->child_connection()->service_token())));
in_process_thread_->Start();
} else {
@@ -279,11 +290,15 @@ bool UtilityProcessHost::StartProcess() {
#if defined(OS_MACOSX)
service_manager::switches::kEnableSandboxLogging,
#endif
+ switches::kForceTextDirection,
+ switches::kForceUIDirection,
switches::kIgnoreCertificateErrors,
switches::kOverrideUseSoftwareGLForTests,
switches::kOverrideEnabledCdmInterfaceVersion,
switches::kProxyServer,
+ switches::kDisableAcceleratedMjpegDecode,
switches::kUseFakeDeviceForMediaStream,
+ switches::kUseFakeJpegDecodeAccelerator,
switches::kUseFileForFakeVideoCapture,
switches::kUseMockCertVerifierForTesting,
switches::kUtilityStartupDialog,
@@ -374,22 +389,4 @@ void UtilityProcessHost::OnProcessCrashed(int exit_code) {
client_, exit_code));
}
-void UtilityProcessHost::NotifyAndDelete(int error_code) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&UtilityProcessHost::NotifyLaunchFailedAndDelete,
- weak_ptr_factory_.GetWeakPtr(), error_code));
-}
-
-// static
-void UtilityProcessHost::NotifyLaunchFailedAndDelete(
- base::WeakPtr<UtilityProcessHost> host,
- int error_code) {
- if (!host)
- return;
-
- host->OnProcessLaunchFailed(error_code);
- delete host.get();
-}
-
} // namespace content
diff --git a/chromium/content/browser/utility_process_host.h b/chromium/content/browser/utility_process_host.h
index 0185b68cc8a..39edbdf0dbc 100644
--- a/chromium/content/browser/utility_process_host.h
+++ b/chromium/content/browser/utility_process_host.h
@@ -89,6 +89,11 @@ class CONTENT_EXPORT UtilityProcessHost
// Sets the name of the process to appear in the task manager.
void SetName(const base::string16& name);
+ // Sets the name used for metrics reporting. This should not be a localized
+ // name. This is recorded to metrics, so update UtilityProcessNameHash enum in
+ // enums.xml if new values are passed here.
+ void SetMetricsName(const std::string& metrics_name);
+
void set_child_flags(int flags) { child_flags_ = flags; }
// Used when the utility process is going to host a service. |identity| is
@@ -113,14 +118,6 @@ class CONTENT_EXPORT UtilityProcessHost
void OnProcessLaunchFailed(int error_code) override;
void OnProcessCrashed(int exit_code) override;
- // Cleans up |this| as a result of a failed Start().
- void NotifyAndDelete(int error_code);
-
- // Notifies the client that the launch failed and deletes |host|.
- static void NotifyLaunchFailedAndDelete(
- base::WeakPtr<UtilityProcessHost> host,
- int error_code);
-
// Pointer to our client interface used for progress notifications.
scoped_refptr<UtilityProcessHostClient> client_;
@@ -142,6 +139,9 @@ class CONTENT_EXPORT UtilityProcessHost
// The process name used to identify the process in task manager.
base::string16 name_;
+ // The non-localized name used for metrics reporting.
+ std::string metrics_name_;
+
// Child process host implementation.
std::unique_ptr<BrowserChildProcessHostImpl> process_;
diff --git a/chromium/content/browser/utility_process_host_browsertest.cc b/chromium/content/browser/utility_process_host_browsertest.cc
index 44ed195c008..670a457de87 100644
--- a/chromium/content/browser/utility_process_host_browsertest.cc
+++ b/chromium/content/browser/utility_process_host_browsertest.cc
@@ -8,33 +8,67 @@
#include "build/build_config.h"
#include "content/browser/utility_process_host.h"
#include "content/browser/utility_process_host_client.h"
+#include "content/public/browser/browser_child_process_observer.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/child_process_data.h"
+#include "content/public/browser/child_process_termination_info.h"
#include "content/public/common/bind_interface_helpers.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_service.mojom.h"
+#if defined(OS_MACOSX) || defined(OS_LINUX)
+#include <sys/wait.h>
+#endif
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif // OS_WIN
+
namespace content {
-class UtilityProcessHostBrowserTest : public ContentBrowserTest {
+namespace {
+
+const char kTestProcessName[] = "test_process";
+
+} // namespace
+
+class UtilityProcessHostBrowserTest : public BrowserChildProcessObserver,
+ public ContentBrowserTest {
public:
- void RunUtilityProcess(bool elevated) {
+ void RunUtilityProcess(bool elevated, bool crash) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ BrowserChildProcessObserver::Add(this);
+ has_launched = false;
+ has_crashed = false;
base::RunLoop run_loop;
- done_closure_ = run_loop.QuitClosure();
+ done_closure_ =
+ base::BindOnce(&UtilityProcessHostBrowserTest::DoneRunning,
+ base::Unretained(this), run_loop.QuitClosure(), crash);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&UtilityProcessHostBrowserTest::RunUtilityProcessOnIOThread,
- base::Unretained(this), elevated));
+ base::Unretained(this), elevated, crash));
run_loop.Run();
}
protected:
- void RunUtilityProcessOnIOThread(bool elevated) {
+ void DoneRunning(base::OnceClosure quit_closure, bool expect_crashed) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ BrowserChildProcessObserver::Remove(this);
+ EXPECT_EQ(true, has_launched);
+ EXPECT_EQ(expect_crashed, has_crashed);
+ std::move(quit_closure).Run();
+ }
+
+ void RunUtilityProcessOnIOThread(bool elevated, bool crash) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
UtilityProcessHost* host =
new UtilityProcessHost(/*client=*/nullptr,
/*client_task_runner=*/nullptr);
host->SetName(base::ASCIIToUTF16("TestProcess"));
+ host->SetMetricsName(kTestProcessName);
#if defined(OS_WIN)
if (elevated)
host->SetSandboxType(service_manager::SandboxType::
@@ -43,26 +77,102 @@ class UtilityProcessHostBrowserTest : public ContentBrowserTest {
EXPECT_TRUE(host->Start());
BindInterface(host, &service_);
- service_->DoSomething(base::BindOnce(
- &UtilityProcessHostBrowserTest::OnSomething, base::Unretained(this)));
+ if (crash) {
+ service_->DoCrashImmediately(
+ base::BindOnce(&UtilityProcessHostBrowserTest::OnSomethingOnIOThread,
+ base::Unretained(this), crash));
+ } else {
+ service_->DoSomething(
+ base::BindOnce(&UtilityProcessHostBrowserTest::OnSomethingOnIOThread,
+ base::Unretained(this), crash));
+ }
}
- void OnSomething() {
+ void ResetServiceOnIOThread() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_.reset();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_);
+ }
+
+ void OnSomethingOnIOThread(bool expect_crash) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // If service crashes then this never gets called.
+ ASSERT_EQ(false, expect_crash);
+ ResetServiceOnIOThread();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ std::move(done_closure_));
}
mojom::TestServicePtr service_;
- base::Closure done_closure_;
+ base::OnceClosure done_closure_;
+
+ // Access on UI thread.
+ bool has_launched;
+ bool has_crashed;
+
+ private:
+ // content::BrowserChildProcessObserver implementation:
+ void BrowserChildProcessKilled(
+ const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+#if defined(OS_ANDROID)
+ // Android does not send crash notifications but sends kills. See comment in
+ // browser_child_process_observer.h.
+ BrowserChildProcessCrashed(data, info);
+#else
+ FAIL() << "Killed notifications should only happen on Android.";
+#endif
+ }
+
+ void BrowserChildProcessCrashed(
+ const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ EXPECT_EQ(true, has_launched);
+#if defined(OS_WIN)
+ EXPECT_EQ(EXCEPTION_BREAKPOINT, DWORD{info.exit_code});
+#elif defined(OS_MACOSX) || defined(OS_LINUX)
+ EXPECT_TRUE(WIFSIGNALED(info.exit_code));
+ EXPECT_EQ(SIGTRAP, WTERMSIG(info.exit_code));
+#endif
+ EXPECT_EQ(kTestProcessName, data.metrics_name);
+ EXPECT_EQ(false, has_crashed);
+ has_crashed = true;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&UtilityProcessHostBrowserTest::ResetServiceOnIOThread,
+ base::Unretained(this)));
+ std::move(done_closure_).Run();
+ }
+
+ void BrowserChildProcessLaunchedAndConnected(
+ const ChildProcessData& data) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Multiple child processes might be launched, check just for ours.
+ if (data.metrics_name == kTestProcessName) {
+ EXPECT_EQ(false, has_launched);
+ has_launched = true;
+ }
+ }
};
IN_PROC_BROWSER_TEST_F(UtilityProcessHostBrowserTest, LaunchProcess) {
- RunUtilityProcess(false);
+ RunUtilityProcess(false, false);
+}
+
+IN_PROC_BROWSER_TEST_F(UtilityProcessHostBrowserTest, LaunchProcessAndCrash) {
+ RunUtilityProcess(false, true);
}
#if defined(OS_WIN)
IN_PROC_BROWSER_TEST_F(UtilityProcessHostBrowserTest, LaunchElevatedProcess) {
- RunUtilityProcess(true);
+ RunUtilityProcess(true, false);
+}
+
+// Disabled because currently this causes a WER dialog to appear.
+IN_PROC_BROWSER_TEST_F(UtilityProcessHostBrowserTest,
+ LaunchElevatedProcessAndCrash_DISABLED) {
+ RunUtilityProcess(true, true);
}
#endif
diff --git a/chromium/content/browser/vibration_browsertest.cc b/chromium/content/browser/vibration_browsertest.cc
index ec6b12a21c7..842c049b978 100644
--- a/chromium/content/browser/vibration_browsertest.cc
+++ b/chromium/content/browser/vibration_browsertest.cc
@@ -26,9 +26,7 @@ namespace {
class VibrationTest : public ContentBrowserTest,
public device::mojom::VibrationManager {
public:
- VibrationTest() : binding_(this){};
-
- void SetUpOnMainThread() override {
+ VibrationTest() : binding_(this) {
// Because Device Service also runs in this process(browser process), here
// we can directly set our binder to intercept interface requests against
// it.
@@ -38,6 +36,11 @@ class VibrationTest : public ContentBrowserTest,
base::Unretained(this)));
}
+ ~VibrationTest() override {
+ service_manager::ServiceContext::ClearGlobalBindersForTesting(
+ device::mojom::kServiceName);
+ }
+
void BindVibrationManager(
const std::string& interface_name,
mojo::ScopedMessagePipeHandle handle,
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 559ee9bdcfd..bf1f7668e32 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
@@ -9,8 +9,8 @@
#include <vector>
#include "base/macros.h"
-#include "base/test/histogram_tester.h"
-#include "base/test/user_action_tester.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/metrics/user_action_tester.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/web_contents/aura/types.h"
#include "content/browser/web_contents/web_contents_view.h"
diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc
index 634d995b762..8cb3bf4b93e 100644
--- a/chromium/content/browser/web_contents/web_contents_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_android.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <string>
+#include <utility>
#include <vector>
#include "base/android/callback_android.h"
@@ -21,7 +22,6 @@
#include "base/task_scheduler/post_task.h"
#include "content/browser/accessibility/browser_accessibility_android.h"
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
-#include "content/browser/android/content_view_core.h"
#include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/media/android/browser_media_player_manager.h"
@@ -644,7 +644,7 @@ void WebContentsAndroid::SetOverscrollRefreshHandler(
overscroll_refresh_handler));
}
-void WebContentsAndroid::GetContentBitmap(
+void WebContentsAndroid::WriteContentBitmapToDisk(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint width,
@@ -769,7 +769,6 @@ void WebContentsAndroid::OnFinishGetContentBitmap(
const std::string& path,
const SkBitmap& bitmap) {
JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jobject> java_bitmap;
if (!bitmap.drawsNothing()) {
auto task_runner = base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
@@ -843,10 +842,24 @@ void WebContentsAndroid::OnScaleFactorChanged(
if (rwhva) {
// |SendScreenRects()| indirectly calls GetViewSize() that asks Java layer.
web_contents_->SendScreenRects();
- rwhva->SynchronizeVisualProperties();
+ rwhva->SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+ base::nullopt);
}
}
+void WebContentsAndroid::SetFocus(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jboolean focused) {
+ WebContentsViewAndroid* view =
+ static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
+ view->SetFocus(focused);
+}
+
+bool WebContentsAndroid::IsBeingDestroyed(JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ return web_contents_->IsBeingDestroyed();
+}
+
int WebContentsAndroid::GetTopControlsShrinkBlinkHeightPixForTesting(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
@@ -857,4 +870,15 @@ int WebContentsAndroid::GetTopControlsShrinkBlinkHeightPixForTesting(
: 0;
}
+void WebContentsAndroid::SetDisplayCutoutSafeArea(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ int top,
+ int left,
+ int bottom,
+ int right) {
+ web_contents()->SetDisplayCutoutSafeArea(
+ gfx::Insets(top, left, bottom, right));
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_android.h b/chromium/content/browser/web_contents/web_contents_android.h
index 04455bd0666..d5094a6ad5c 100644
--- a/chromium/content/browser/web_contents/web_contents_android.h
+++ b/chromium/content/browser/web_contents/web_contents_android.h
@@ -178,12 +178,13 @@ class CONTENT_EXPORT WebContentsAndroid
const base::android::JavaParamRef<jobject>& overscroll_refresh_handler);
// Relay the access from Java layer to RWHV::CopyFromSurface() through JNI.
- void GetContentBitmap(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jint width,
- jint height,
- const base::android::JavaParamRef<jstring>& jpath,
- const base::android::JavaParamRef<jobject>& jcallback);
+ void WriteContentBitmapToDisk(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint width,
+ jint height,
+ const base::android::JavaParamRef<jstring>& jpath,
+ const base::android::JavaParamRef<jobject>& jcallback);
void ReloadLoFiImages(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
@@ -236,6 +237,11 @@ class CONTENT_EXPORT WebContentsAndroid
void OnScaleFactorChanged(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
+ void SetFocus(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jboolean focused);
+ bool IsBeingDestroyed(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
// Returns the amount of the top controls height if controls are in the state
// of shrinking Blink's view size, otherwise 0.
@@ -243,6 +249,13 @@ class CONTENT_EXPORT WebContentsAndroid
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
+ void SetDisplayCutoutSafeArea(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ int top,
+ int left,
+ int bottom,
+ int right);
+
private:
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid();
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index 6ae9bf2f9c6..26384f823b5 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -42,6 +42,7 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/protocol/page_handler.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/display_cutout/display_cutout_host_impl.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/download/mhtml_generation_manager.h"
@@ -113,6 +114,7 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents_binding_set.h"
#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
@@ -136,6 +138,7 @@
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "third_party/blink/public/platform/web_security_style.h"
@@ -152,7 +155,6 @@
#endif
#if defined(OS_ANDROID)
-#include "content/browser/android/content_video_view.h"
#include "content/browser/android/date_time_chooser_android.h"
#include "content/browser/android/java_interfaces_impl.h"
#include "content/browser/media/android/media_web_contents_observer_android.h"
@@ -238,6 +240,25 @@ RenderFrameHostImpl* FindOpenerRFH(const WebContents::CreateParams& params) {
return opener_rfh;
}
+// Returns |true| if |type| is the kind of user input that should trigger the
+// user interaction observers.
+bool IsUserInteractionInputType(blink::WebInputEvent::Type type) {
+ // Ideally, this list would be based more off of
+ // https://whatwg.org/C/interaction.html#triggered-by-user-activation.
+ return type == blink::WebInputEvent::kMouseDown ||
+ type == blink::WebInputEvent::kGestureScrollBegin ||
+ type == blink::WebInputEvent::kTouchStart ||
+ type == blink::WebInputEvent::kRawKeyDown;
+}
+
+// Returns |true| if |type| is the kind of user input that should be used as
+// a user gesture signal for resource load dispatches.
+bool IsResourceLoadUserInteractionInputType(blink::WebInputEvent::Type type) {
+ return type == blink::WebInputEvent::kMouseDown ||
+ type == blink::WebInputEvent::kTouchStart ||
+ type == blink::WebInputEvent::kRawKeyDown;
+}
+
// Ensures that OnDialogClosed is only called once.
class CloseDialogCallbackWrapper
: public base::RefCountedThreadSafe<CloseDialogCallbackWrapper> {
@@ -516,7 +537,6 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
fullscreen_widget_process_id_(ChildProcessHost::kInvalidUniqueID),
fullscreen_widget_routing_id_(MSG_ROUTING_NONE),
fullscreen_widget_had_focus_at_shutdown_(false),
- is_subframe_(false),
force_disable_overscroll_content_(false),
last_dialog_suppressed_(false),
accessibility_mode_(
@@ -549,6 +569,14 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
host_zoom_map_observer_.reset(new HostZoomMapObserver(this));
#endif // !defined(OS_ANDROID)
+#if defined(OS_ANDROID)
+ if (base::FeatureList::IsEnabled(features::kDisplayCutoutAPI)) {
+ display_cutout_host_impl_ = std::make_unique<DisplayCutoutHostImpl>(
+ this, base::BindRepeating(&WebContentsImpl::NotifyViewportFitChanged,
+ base::Unretained(this)));
+ }
+#endif
+
registry_.AddInterface(base::BindRepeating(
&WebContentsImpl::OnColorChooserFactoryRequest, base::Unretained(this)));
}
@@ -634,6 +662,17 @@ WebContentsImpl::~WebContentsImpl() {
pepper_playback_observer_.reset();
#endif // defined(ENABLED_PLUGINS)
+ // If audio is playing then notify external observers of the audio stream
+ // disappearing.
+ if (is_currently_audible_) {
+ is_currently_audible_ = false;
+ for (auto& observer : observers_)
+ observer.OnAudioStateChanged(false);
+
+ if (GetOuterWebContents())
+ GetOuterWebContents()->OnAudioStateChanged();
+ }
+
for (auto& observer : observers_)
observer.FrameDeleted(root->current_frame_host());
@@ -692,9 +731,6 @@ std::unique_ptr<WebContentsImpl> WebContentsImpl::CreateWithOpener(
// This makes |new_contents| act as a guest.
// For more info, see comment above class BrowserPluginGuest.
BrowserPluginGuest::Create(new_contents.get(), params.guest_delegate);
- // We are instantiating a WebContents for browser plugin. Set its subframe
- // bit to true.
- new_contents->is_subframe_ = true;
}
new_contents->Init(params);
@@ -1005,7 +1041,7 @@ WebContentsView* WebContentsImpl::GetView() const {
void WebContentsImpl::OnScreenOrientationChange() {
DCHECK(screen_orientation_provider_);
- return screen_orientation_provider_->OnOrientationChange();
+ screen_orientation_provider_->OnOrientationChange();
}
SkColor WebContentsImpl::GetThemeColor() const {
@@ -1105,27 +1141,22 @@ void WebContentsImpl::RecursiveRequestAXTreeSnapshotOnFrame(
}
}
-#if !defined(OS_ANDROID)
-void WebContentsImpl::SetTemporaryZoomLevel(double level,
- bool temporary_zoom_enabled) {
- SendPageMessage(new PageMsg_SetZoomLevel(
- MSG_ROUTING_NONE,
- temporary_zoom_enabled ? PageMsg_SetZoomLevel_Command::SET_TEMPORARY
- : PageMsg_SetZoomLevel_Command::CLEAR_TEMPORARY,
- level));
+void WebContentsImpl::NotifyViewportFitChanged(
+ blink::mojom::ViewportFit value) {
+ for (auto& observer : observers_)
+ observer.ViewportFitChanged(value);
}
-void WebContentsImpl::UpdateZoom(double level) {
- // Individual frames may still ignore the new zoom level if their RenderView
- // contains a plugin document or if it uses a temporary zoom level.
- SendPageMessage(new PageMsg_SetZoomLevel(
- MSG_ROUTING_NONE,
- PageMsg_SetZoomLevel_Command::USE_CURRENT_TEMPORARY_MODE, level));
+#if !defined(OS_ANDROID)
+void WebContentsImpl::UpdateZoom() {
+ RenderWidgetHostImpl* rwh = GetRenderViewHost()->GetWidget();
+ if (rwh->GetView())
+ rwh->SynchronizeVisualProperties();
}
+
void WebContentsImpl::UpdateZoomIfNecessary(const std::string& scheme,
- const std::string& host,
- double level) {
+ const std::string& host) {
NavigationEntry* entry = GetController().GetLastCommittedEntry();
if (!entry)
return;
@@ -1136,7 +1167,7 @@ void WebContentsImpl::UpdateZoomIfNecessary(const std::string& scheme,
return;
}
- UpdateZoom(level);
+ UpdateZoom();
}
#endif // !defined(OS_ANDROID)
@@ -1254,6 +1285,15 @@ const std::string& WebContentsImpl::GetMediaDeviceGroupIDSaltBase() const {
return media_device_group_id_salt_base_;
}
+#if defined(OS_ANDROID)
+
+void WebContentsImpl::SetDisplayCutoutSafeArea(gfx::Insets insets) {
+ if (display_cutout_host_impl_)
+ display_cutout_host_impl_->SetDisplayCutoutSafeArea(insets);
+}
+
+#endif
+
const base::string16& WebContentsImpl::GetTitle() const {
// Transient entries take precedence. They are used for interstitial pages
// that are shown on top of existing pages.
@@ -1435,7 +1475,7 @@ void WebContentsImpl::SetAudioMuted(bool mute) {
}
bool WebContentsImpl::IsCurrentlyAudible() {
- return audio_stream_monitor()->IsCurrentlyAudible();
+ return is_currently_audible_;
}
bool WebContentsImpl::IsConnectedToBluetoothDevice() const {
@@ -1456,14 +1496,29 @@ void WebContentsImpl::SetHasPictureInPictureVideo(
}
bool WebContentsImpl::IsCrashed() const {
- return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED ||
- crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
- crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ||
+ switch (crashed_status_) {
+ case base::TERMINATION_STATUS_PROCESS_CRASHED:
+ case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
+ case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
+ case base::TERMINATION_STATUS_OOM:
+ case base::TERMINATION_STATUS_LAUNCH_FAILED:
#if defined(OS_CHROMEOS)
- crashed_status_ ==
- base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM ||
+ case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
+#endif
+#if defined(OS_ANDROID)
+ case base::TERMINATION_STATUS_OOM_PROTECTED:
#endif
- crashed_status_ == base::TERMINATION_STATUS_LAUNCH_FAILED);
+ return true;
+ case base::TERMINATION_STATUS_NORMAL_TERMINATION:
+ case base::TERMINATION_STATUS_STILL_RUNNING:
+ return false;
+ case base::TERMINATION_STATUS_MAX_ENUM:
+ NOTREACHED();
+ return false;
+ }
+
+ NOTREACHED();
+ return false;
}
void WebContentsImpl::SetIsCrashed(base::TerminationStatus status,
@@ -1502,26 +1557,40 @@ void WebContentsImpl::NotifyNavigationStateChanged(
GetOuterWebContents()->NotifyNavigationStateChanged(changed_flags);
}
-void WebContentsImpl::OnAudioStateChanged(bool is_audible) {
- SendPageMessage(new PageMsg_AudioStateChanged(MSG_ROUTING_NONE, is_audible));
+void WebContentsImpl::OnAudioStateChanged() {
+ // This notification can come from any embedded contents or from this
+ // WebContents' stream monitor. Aggregate these signals to get the actual
+ // state.
+ bool is_currently_audible =
+ audio_stream_monitor_.IsCurrentlyAudible() ||
+ (browser_plugin_embedder_ &&
+ browser_plugin_embedder_->AreAnyGuestsCurrentlyAudible());
+ if (is_currently_audible == is_currently_audible_)
+ return;
+
+ // Update internal state.
+ is_currently_audible_ = is_currently_audible;
+ was_ever_audible_ = was_ever_audible_ || is_currently_audible_;
+
+ SendPageMessage(
+ new PageMsg_AudioStateChanged(MSG_ROUTING_NONE, is_currently_audible_));
// Notification for UI updates in response to the changed audio state.
NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
- was_ever_audible_ = was_ever_audible_ || is_audible;
+ // Ensure that audio state changes propagate from innermost to outermost
+ // WebContents.
+ if (GetOuterWebContents())
+ GetOuterWebContents()->OnAudioStateChanged();
for (auto& observer : observers_)
- observer.OnAudioStateChanged(is_audible);
+ observer.OnAudioStateChanged(is_currently_audible_);
}
base::TimeTicks WebContentsImpl::GetLastActiveTime() const {
return last_active_time_;
}
-void WebContentsImpl::SetLastActiveTime(base::TimeTicks last_active_time) {
- last_active_time_ = last_active_time;
-}
-
void WebContentsImpl::WasShown() {
controller_.SetActive(true);
@@ -1555,9 +1624,10 @@ void WebContentsImpl::WasShown() {
}
void WebContentsImpl::WasHidden() {
- // If there are entities capturing screenshots or video (e.g., mirroring),
- // don't activate the "disable rendering" optimization.
- if (!IsBeingCaptured()) {
+ // If there are entities capturing screenshots or video (e.g. mirroring),
+ // or in Picture-in-Picture mode, don't activate the "disable rendering"
+ // optimization.
+ if (!IsBeingCaptured() && !HasPictureInPictureVideo()) {
// |GetRenderViewHost()| can be NULL if the user middle clicks a link to
// open a tab in the background, then closes the tab before selecting it.
// This is because closing the tab calls WebContentsImpl::Destroy(), which
@@ -1653,9 +1723,16 @@ void WebContentsImpl::DispatchBeforeUnload() {
void WebContentsImpl::AttachToOuterWebContentsFrame(
WebContents* outer_web_contents,
RenderFrameHost* outer_contents_frame) {
- CHECK(GuestMode::IsCrossProcessFrameGuest(this));
+ DCHECK(!node_.outer_web_contents());
+
RenderFrameHostManager* render_manager = GetRenderManager();
+ // When attaching a WebContents as an inner WebContents, we need to replace
+ // the Webcontents' view with a WebContentsViewChildFrame.
+ view_.reset(new WebContentsViewChildFrame(
+ this, GetContentClient()->browser()->GetWebContentsViewDelegate(this),
+ &render_view_host_delegate_view_));
+
// 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
@@ -1745,8 +1822,11 @@ void WebContentsImpl::Stop() {
observer.NavigationStopped();
}
-void WebContentsImpl::FreezePage() {
- SendPageMessage(new PageMsg_FreezePage(MSG_ROUTING_NONE));
+void WebContentsImpl::SetPageFrozen(bool frozen) {
+ // A visible page is never frozen.
+ DCHECK_NE(Visibility::VISIBLE, GetVisibility());
+
+ SendPageMessage(new PageMsg_SetPageFrozen(MSG_ROUTING_NONE, frozen));
}
std::unique_ptr<WebContents> WebContentsImpl::Clone() {
@@ -1808,6 +1888,9 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
visibility_ =
params.initially_hidden ? Visibility::HIDDEN : Visibility::VISIBLE;
+ if (!params.last_active_time.is_null())
+ last_active_time_ = params.last_active_time;
+
// The routing ids must either all be set or all be unset.
DCHECK((params.routing_id == MSG_ROUTING_NONE &&
params.main_frame_routing_id == MSG_ROUTING_NONE &&
@@ -1832,10 +1915,13 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
int32_t view_routing_id = params.routing_id;
int32_t main_frame_widget_routing_id = params.main_frame_widget_routing_id;
if (main_frame_widget_routing_id == MSG_ROUTING_NONE) {
- view_routing_id = main_frame_widget_routing_id =
+ view_routing_id = site_instance->GetProcess()->GetNextRoutingID();
+ main_frame_widget_routing_id =
site_instance->GetProcess()->GetNextRoutingID();
}
+ DCHECK_NE(view_routing_id, main_frame_widget_routing_id);
+
GetRenderManager()->Init(
site_instance.get(), view_routing_id, params.main_frame_routing_id,
main_frame_widget_routing_id, params.renderer_initiated_creation);
@@ -1985,6 +2071,10 @@ void WebContentsImpl::LostCapture(RenderWidgetHostImpl* render_widget_host) {
delegate_->LostCapture();
}
+ukm::SourceId WebContentsImpl::GetUkmSourceIdForLastCommittedSource() const {
+ return last_committed_source_id_;
+}
+
void WebContentsImpl::RenderWidgetCreated(
RenderWidgetHostImpl* render_widget_host) {
created_widgets_.insert(render_widget_host);
@@ -2207,12 +2297,6 @@ void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
->ShutdownAndDestroyWidget(true);
}
-#if defined(OS_ANDROID)
- ContentVideoView* video_view = ContentVideoView::GetInstance();
- if (video_view != NULL)
- video_view->ExitFullscreen();
-#endif
-
if (delegate_) {
delegate_->ExitFullscreenModeForTab(this);
@@ -2235,12 +2319,83 @@ void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
}
}
+ // Clear the current fullscreen frame ID.
+ current_fullscreen_frame_tree_node_id_ = RenderFrameHost::kNoFrameTreeNodeId;
+
for (auto& observer : observers_) {
observer.DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(),
will_cause_resize);
}
}
+void WebContentsImpl::FullscreenStateChanged(RenderFrameHost* rfh,
+ bool is_fullscreen) {
+ int frame_tree_node_id = rfh->GetFrameTreeNodeId();
+ auto it = fullscreen_frame_tree_nodes_.find(frame_tree_node_id);
+ bool changed = false;
+
+ if (is_fullscreen) {
+ // If we are fullscreen then add the FrameTreeNode ID to the set.
+ if (it == fullscreen_frame_tree_nodes_.end()) {
+ fullscreen_frame_tree_nodes_.insert(frame_tree_node_id);
+ changed = true;
+ }
+ } else {
+ FrameTreeNode* ancestor =
+ static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
+ DCHECK(ancestor);
+
+ // If we are not fullscreen then remove this frame and any descendants
+ // from the set.
+ for (it = fullscreen_frame_tree_nodes_.begin();
+ it != fullscreen_frame_tree_nodes_.end();) {
+ FrameTreeNode* node = FrameTreeNode::GloballyFindByID(*it);
+
+ if (!node || frame_tree_node_id == *it ||
+ node->IsDescendantOf(ancestor)) {
+ it = fullscreen_frame_tree_nodes_.erase(it);
+ changed = true;
+ } else {
+ ++it;
+ }
+ }
+ }
+
+ // If we have changed then find the current fullscreen FrameTreeNode
+ // and call the observers. If we have exited fullscreen then this
+ // will be the last frame that was fullscreen.
+ if (changed && fullscreen_frame_tree_nodes_.size() > 0) {
+ unsigned int max_depth = 0;
+ RenderFrameHost* max_depth_rfh = nullptr;
+
+ for (auto node_id : fullscreen_frame_tree_nodes_) {
+ FrameTreeNode* fullscreen_node = FrameTreeNode::GloballyFindByID(node_id);
+ DCHECK(fullscreen_node);
+
+ if (max_depth_rfh == nullptr || fullscreen_node->depth() > max_depth) {
+ max_depth = fullscreen_node->depth();
+ max_depth_rfh = fullscreen_node->current_frame_host();
+ }
+ }
+
+ // If we have already notified observers about this frame then we should not
+ // fire the observers again.
+ DCHECK(max_depth_rfh);
+ if (max_depth_rfh->GetFrameTreeNodeId() ==
+ current_fullscreen_frame_tree_node_id_)
+ return;
+
+ current_fullscreen_frame_tree_node_id_ =
+ max_depth_rfh->GetFrameTreeNodeId();
+
+ for (auto& observer : observers_)
+ observer.DidAcquireFullscreen(max_depth_rfh);
+ } else if (fullscreen_frame_tree_nodes_.size() == 0) {
+ current_fullscreen_frame_tree_node_id_ =
+ RenderFrameHost::kNoFrameTreeNodeId;
+ }
+}
+
bool WebContentsImpl::IsFullscreenForCurrentTab() const {
return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false;
}
@@ -2501,6 +2656,10 @@ void WebContentsImpl::CreateNewWindow(
}
// Save the created window associated with the route so we can show it
// later.
+ //
+ // TODO(ajwong): This should be keyed off the RenderFrame routing id or the
+ // FrameTreeNode id instead of the routing id of the Widget for the main
+ // frame. https://crbug.com/545684
DCHECK_NE(MSG_ROUTING_NONE, main_frame_widget_route_id);
pending_contents_[std::make_pair(render_process_id,
main_frame_widget_route_id)] =
@@ -2541,7 +2700,7 @@ void WebContentsImpl::CreateNewWindow(
delegate_->AddNewContents(this, std::move(new_contents),
params.disposition, initial_rect,
- params.user_gesture, &was_blocked);
+ params.mimic_user_gesture, &was_blocked);
if (!weak_new_contents)
return; // The delegate deleted |new_contents| during AddNewContents().
}
@@ -2551,7 +2710,7 @@ void WebContentsImpl::CreateNewWindow(
WindowOpenDisposition::CURRENT_TAB,
ui::PAGE_TRANSITION_LINK,
true /* is_renderer_initiated */);
- open_params.user_gesture = params.user_gesture;
+ open_params.user_gesture = params.mimic_user_gesture;
if (delegate_ && !is_guest &&
!delegate_->ShouldResumeRequestsForCreatedWindow()) {
@@ -2638,7 +2797,7 @@ void WebContentsImpl::ShowCreatedWindow(int process_id,
RenderWidgetHostImpl* rwh =
weak_popup->GetMainFrame()->GetRenderWidgetHost();
DCHECK_EQ(main_frame_widget_route_id, rwh->GetRoutingID());
- rwh->Send(new ViewMsg_Move_ACK(rwh->GetRoutingID()));
+ rwh->Send(new ViewMsg_SetBounds_ACK(rwh->GetRoutingID()));
}
}
@@ -2719,7 +2878,7 @@ std::unique_ptr<WebContents> WebContentsImpl::GetCreatedWindow(
if (BrowserPluginGuest::IsGuest(raw_new_contents))
return new_contents;
- if (!new_contents->GetMainFrame()->GetProcess()->HasConnection() ||
+ if (!new_contents->GetMainFrame()->GetProcess()->IsInitializedAndNotDead() ||
!new_contents->GetMainFrame()->GetView()) {
return nullptr;
}
@@ -2739,7 +2898,7 @@ RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int process_id,
pending_widget_views_.erase(std::make_pair(process_id, route_id));
RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost();
- if (!widget_host->GetProcess()->HasConnection()) {
+ if (!widget_host->GetProcess()->IsInitializedAndNotDead()) {
// The view has gone away or the renderer crashed. Nothing to do.
return nullptr;
}
@@ -2749,12 +2908,13 @@ RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int process_id,
void WebContentsImpl::RequestMediaAccessPermission(
const MediaStreamRequest& request,
- const MediaResponseCallback& callback) {
+ MediaResponseCallback callback) {
if (delegate_) {
- delegate_->RequestMediaAccessPermission(this, request, callback);
+ delegate_->RequestMediaAccessPermission(this, request, std::move(callback));
} else {
- callback.Run(MediaStreamDevices(), MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
- std::unique_ptr<MediaStreamUI>());
+ std::move(callback).Run(MediaStreamDevices(),
+ MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
+ std::unique_ptr<MediaStreamUI>());
}
}
@@ -2810,7 +2970,7 @@ ui::AXMode WebContentsImpl::GetAccessibilityMode() const {
}
void WebContentsImpl::AccessibilityEventReceived(
- const std::vector<AXEventNotificationDetails>& details) {
+ const AXEventNotificationDetails& details) {
for (auto& observer : observers_)
observer.AccessibilityEventReceived(details);
}
@@ -2977,6 +3137,14 @@ void WebContentsImpl::SelectRange(const gfx::Point& base,
focused_frame->GetFrameInputHandler()->SelectRange(base, extent);
}
+#if defined(OS_MACOSX)
+void WebContentsImpl::DidChangeTextSelection(const base::string16& text,
+ const gfx::Range& range) {
+ for (auto& observer : observers_)
+ observer.DidChangeTextSelection(text, range);
+}
+#endif
+
void WebContentsImpl::MoveCaret(const gfx::Point& extent) {
RenderFrameHostImpl* focused_frame = GetFocusedFrame();
if (!focused_frame)
@@ -3039,8 +3207,14 @@ void WebContentsImpl::ResetAutoResizeSize() {
}
WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) {
- if (!delegate_)
+ if (!delegate_) {
+ // Embedder can delay setting a delegate on new WebContents with
+ // WebContentsDelegate::ShouldResumeRequestsForCreatedWindow. In the mean
+ // time, navigations, including the initial one, that goes through OpenURL
+ // should be delayed until embedder is ready to resume loading.
+ delayed_open_url_params_ = std::make_unique<OpenURLParams>(params);
return nullptr;
+ }
WebContents* new_contents = delegate_->OpenURLFromTab(this, params);
@@ -3211,6 +3385,17 @@ void WebContentsImpl::ReloadLoFiImages() {
SendToAllFrames(new FrameMsg_ReloadLoFiImages(MSG_ROUTING_NONE));
}
+std::vector<blink::mojom::PauseSubresourceLoadingHandlePtr>
+WebContentsImpl::PauseSubresourceLoading() {
+ std::vector<blink::mojom::PauseSubresourceLoadingHandlePtr> handles;
+ for (RenderFrameHost* rfh : GetAllFrames()) {
+ if (!rfh->IsRenderFrameLive())
+ continue;
+ handles.push_back(rfh->PauseSubresourceLoading());
+ }
+ return handles;
+}
+
void WebContentsImpl::Undo() {
RenderFrameHostImpl* focused_frame = GetFocusedFrame();
if (!focused_frame)
@@ -3618,7 +3803,7 @@ void WebContentsImpl::SystemDragEnded(RenderWidgetHost* source_rwh) {
}
void WebContentsImpl::NavigatedByUser() {
- OnUserInteraction(blink::WebInputEvent::kUndefined);
+ SendUserGestureForResourceDispatchHost();
}
void WebContentsImpl::SetClosedByUserGesture(bool value) {
@@ -3747,10 +3932,6 @@ int WebContentsImpl::DownloadImage(
return download_id;
}
-bool WebContentsImpl::IsSubframe() const {
- return is_subframe_;
-}
-
void WebContentsImpl::Find(int request_id,
const base::string16& search_text,
const blink::WebFindOptions& options) {
@@ -3768,12 +3949,6 @@ void WebContentsImpl::StopFinding(StopFindAction action) {
manager->StopFinding(action);
}
-bool WebContentsImpl::WasRecentlyAudible() {
- return audio_stream_monitor_.WasRecentlyAudible() ||
- (browser_plugin_embedder_ &&
- browser_plugin_embedder_->WereAnyGuestsRecentlyAudible());
-}
-
bool WebContentsImpl::WasEverAudible() {
return was_ever_audible_;
}
@@ -3903,6 +4078,7 @@ void WebContentsImpl::ReadyToCommitNavigation(
void WebContentsImpl::DidFinishNavigation(NavigationHandle* navigation_handle) {
TRACE_EVENT1("navigation", "WebContentsImpl::DidFinishNavigation",
"navigation_handle", navigation_handle);
+
for (auto& observer : observers_)
observer.DidFinishNavigation(navigation_handle);
@@ -3922,6 +4098,9 @@ void WebContentsImpl::DidFinishNavigation(NavigationHandle* navigation_handle) {
if (navigation_handle->IsInMainFrame() &&
!navigation_handle->IsSameDocument()) {
was_ever_audible_ = false;
+ last_committed_source_id_ =
+ ukm::ConvertToSourceId(navigation_handle->GetNavigationId(),
+ ukm::SourceIdType::NAVIGATION_ID);
}
}
}
@@ -4698,6 +4877,8 @@ void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
for (auto& observer : observers_)
observer.RenderViewHostChanged(old_host, new_host);
+ view_->RenderViewHostChanged(old_host, new_host);
+
// Ensure that the associated embedder gets cleared after a RenderViewHost
// gets swapped, so we don't reuse the same embedder next time a
// RenderViewHost is attached to this WebContents.
@@ -4705,7 +4886,8 @@ void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
}
void WebContentsImpl::NotifyFrameSwapped(RenderFrameHost* old_host,
- RenderFrameHost* new_host) {
+ RenderFrameHost* new_host,
+ bool is_main_frame) {
#if defined(OS_ANDROID)
// Copy importance from |old_host| if |new_host| is a main frame.
if (old_host && !new_host->GetParent()) {
@@ -4811,6 +4993,9 @@ void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
#if BUILDFLAG(ENABLE_PLUGINS)
pepper_playback_observer_->RenderFrameDeleted(render_frame_host);
#endif
+
+ // Remove any fullscreen state that the frame has stored.
+ FullscreenStateChanged(render_frame_host, false /* is_fullscreen */);
}
void WebContentsImpl::ShowContextMenu(RenderFrameHost* render_frame_host,
@@ -4974,7 +5159,7 @@ WebContents* WebContentsImpl::GetAsWebContents() {
}
#if !defined(OS_ANDROID)
-double WebContentsImpl::GetPendingPageZoomLevel() {
+double WebContentsImpl::GetPendingPageZoomLevel() const {
NavigationEntry* pending_entry = GetController().GetPendingEntry();
if (!pending_entry)
return HostZoomMap::GetZoomLevel(this);
@@ -5058,7 +5243,7 @@ WebContentsImpl* WebContentsImpl::GetOuterWebContents() {
if (browser_plugin_guest_)
return browser_plugin_guest_->embedder_web_contents();
- return nullptr;
+ return node_.outer_web_contents();
}
WebContentsImpl* WebContentsImpl::GetFocusedWebContents() {
@@ -5146,6 +5331,8 @@ void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
for (auto& observer : observers_)
observer.RenderViewReady();
+
+ view_->RenderViewReady();
}
void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
@@ -5161,6 +5348,11 @@ void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
if (IsFullscreenForCurrentTab())
ExitFullscreenMode(false);
+ // Ensure any video in Picture-in-Picture is exited in the |delegate_| since
+ // a crashed renderer may not have made a clean exit.
+ if (HasPictureInPictureVideo())
+ ExitPictureInPicture();
+
// Cancel any visible dialogs so they are not left dangling over the sad tab.
CancelActiveAndPendingDialogs();
@@ -5229,9 +5421,9 @@ void WebContentsImpl::Close(RenderViewHost* rvh) {
delegate_->CloseContents(this);
}
-void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) {
- if (delegate_ && delegate_->IsPopupOrPanel(this))
- delegate_->MoveContents(this, new_bounds);
+void WebContentsImpl::RequestSetBounds(const gfx::Rect& new_bounds) {
+ if (delegate_)
+ delegate_->SetContentsBounds(this, new_bounds);
}
void WebContentsImpl::DidStartLoading(FrameTreeNode* frame_tree_node,
@@ -5639,12 +5831,7 @@ bool WebContentsImpl::DidAddMessageToConsole(int32_t level,
void WebContentsImpl::DidReceiveInputEvent(
RenderWidgetHostImpl* render_widget_host,
const blink::WebInputEvent::Type type) {
- // Ideally, this list would be based more off of
- // https://whatwg.org/C/interaction.html#triggered-by-user-activation.
- if (type != blink::WebInputEvent::kMouseDown &&
- type != blink::WebInputEvent::kGestureScrollBegin &&
- type != blink::WebInputEvent::kTouchStart &&
- type != blink::WebInputEvent::kRawKeyDown)
+ if (!IsUserInteractionInputType(type))
return;
// Ignore unless the widget is currently in the frame tree.
@@ -5654,7 +5841,11 @@ void WebContentsImpl::DidReceiveInputEvent(
if (type != blink::WebInputEvent::kGestureScrollBegin)
last_interactive_input_event_time_ = ui::EventTimeForNow();
- OnUserInteraction(type);
+ for (auto& observer : observers_)
+ observer.DidGetUserInteraction(type);
+
+ if (IsResourceLoadUserInteractionInputType(type))
+ SendUserGestureForResourceDispatchHost();
}
void WebContentsImpl::FocusOwningWebContents(
@@ -5681,7 +5872,8 @@ void WebContentsImpl::OnIgnoredUIEvent() {
}
void WebContentsImpl::RendererUnresponsive(
- RenderWidgetHostImpl* render_widget_host) {
+ RenderWidgetHostImpl* render_widget_host,
+ base::RepeatingClosure hang_monitor_restarter) {
for (auto& observer : observers_)
observer.OnRendererUnresponsive(render_widget_host->GetProcess());
@@ -5692,7 +5884,8 @@ void WebContentsImpl::RendererUnresponsive(
return;
if (delegate_)
- delegate_->RendererUnresponsive(this, render_widget_host);
+ delegate_->RendererUnresponsive(this, render_widget_host,
+ std::move(hang_monitor_restarter));
}
void WebContentsImpl::RendererResponsive(
@@ -5753,21 +5946,20 @@ void WebContentsImpl::NotifySwappedFromRenderManager(RenderFrameHost* old_host,
if (delegate_)
view_->SetOverscrollControllerEnabled(CanOverscrollContent());
- view_->RenderViewSwappedIn(new_host->GetRenderViewHost());
-
RenderWidgetHostViewBase* rwhv =
static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView());
if (rwhv)
rwhv->SetMainFrameAXTreeID(GetMainFrame()->GetAXTreeID());
}
- NotifyFrameSwapped(old_host, new_host);
+ NotifyFrameSwapped(old_host, new_host, is_main_frame);
}
void WebContentsImpl::NotifyMainFrameSwappedFromRenderManager(
- RenderViewHost* old_host,
- RenderViewHost* new_host) {
- NotifyViewSwapped(old_host, new_host);
+ RenderFrameHost* old_host,
+ RenderFrameHost* new_host) {
+ NotifyViewSwapped(old_host ? old_host->GetRenderViewHost() : nullptr,
+ new_host->GetRenderViewHost());
}
NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() {
@@ -6041,28 +6233,22 @@ void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) {
delegate_->UpdatePreferredSize(this, new_size);
}
-void WebContentsImpl::OnUserInteraction(const blink::WebInputEvent::Type type) {
- for (auto& observer : observers_)
- observer.DidGetUserInteraction(type);
-
- // TODO(https://crbug.com/827659): This used to check if type != kMouseWheel.
- // However, due to the caller already filtering event types, this would never
- // be called with type == kMouseWheel so checking for that here is pointless.
- // However, mouse wheel events *also* generate a kGestureScrollBegin event...
- // which is *not* filtered out. Maybe they should be?
+void WebContentsImpl::SendUserGestureForResourceDispatchHost() {
+ // This is null in unittests. =(
ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
- if (rdh) // null in unittests. =(
+
+ if (rdh)
rdh->OnUserGesture();
}
std::unique_ptr<WebUIImpl> WebContentsImpl::CreateWebUI(const GURL& url) {
std::unique_ptr<WebUIImpl> web_ui = std::make_unique<WebUIImpl>(this);
- WebUIController* controller =
+ std::unique_ptr<WebUIController> controller(
WebUIControllerFactoryRegistry::GetInstance()
- ->CreateWebUIControllerForURL(web_ui.get(), url);
+ ->CreateWebUIControllerForURL(web_ui.get(), url));
if (controller) {
web_ui->AddMessageHandler(std::make_unique<GenericHandler>());
- web_ui->SetController(controller);
+ web_ui->SetController(std::move(controller));
return web_ui;
}
@@ -6337,13 +6523,6 @@ bool WebContentsImpl::AddDomainInfoToRapporSample(rappor::Sample* sample) {
return true;
}
-void WebContentsImpl::UpdateUrlForUkmSource(ukm::UkmRecorder* service,
- ukm::SourceId ukm_source_id) {
- // Here we associate this metric to the main frame URL regardless of what
- // caused it.
- service->UpdateSourceURL(ukm_source_id, GetLastCommittedURL());
-}
-
void WebContentsImpl::FocusedNodeTouched(bool editable) {
#if defined(OS_WIN)
RenderWidgetHostView* view = GetRenderWidgetHostView();
diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h
index cd1c992c773..d16a9912277 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -57,6 +57,7 @@
#include "services/device/public/mojom/wake_lock.mojom.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/public/mojom/color_chooser/color_chooser.mojom.h"
+#include "third_party/blink/public/mojom/page/display_cutout.mojom.h"
#include "third_party/blink/public/platform/web_drag_operation.h"
#include "ui/accessibility/ax_modes.h"
#include "ui/base/page_transition_types.h"
@@ -78,6 +79,7 @@ namespace content {
class BrowserPluginEmbedder;
class BrowserPluginGuest;
class DateTimeChooserAndroid;
+class DisplayCutoutHostImpl;
class FindRequestManager;
class InterstitialPageImpl;
class JavaScriptDialogManager;
@@ -85,6 +87,7 @@ class LoaderIOThreadNotifier;
class ManifestManagerHost;
class MediaWebContentsObserver;
class PluginContentOriginWhitelist;
+class RenderFrameHost;
class RenderViewHost;
class RenderViewHostDelegateView;
class RenderWidgetHostImpl;
@@ -234,20 +237,15 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void AddAccessibilityMode(ui::AXMode mode);
#if !defined(OS_ANDROID)
- // Set a temporary zoom level for the frames associated with this WebContents.
- // If |is_temporary| is true, we are setting a new temporary zoom level,
- // otherwise we are clearing a previously set temporary zoom level.
- void SetTemporaryZoomLevel(double level, bool temporary_zoom_enabled);
-
// Sets the zoom level for frames associated with this WebContents.
- void UpdateZoom(double level);
+ void UpdateZoom();
// Sets the zoom level for frames associated with this WebContents if it
// matches |host| and (if non-empty) |scheme|. Matching is done on the
// last committed entry.
void UpdateZoomIfNecessary(const std::string& scheme,
- const std::string& host,
- double level);
+ const std::string& host);
+
#endif // !defined(OS_ANDROID)
// Adds a new binding set to the WebContents. Returns a closure which may be
@@ -356,9 +354,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
int GetCrashedErrorCode() const override;
bool IsBeingDestroyed() const override;
void NotifyNavigationStateChanged(InvalidateTypes changed_flags) override;
- void OnAudioStateChanged(bool is_audible) override;
+ void OnAudioStateChanged() override;
base::TimeTicks GetLastActiveTime() const override;
- void SetLastActiveTime(base::TimeTicks last_active_time) override;
void WasShown() override;
void WasHidden() override;
void WasOccluded() override;
@@ -373,7 +370,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void NotifyPreferencesChanged() override;
void Stop() override;
- void FreezePage() override;
+ void SetPageFrozen(bool frozen) override;
std::unique_ptr<WebContents> Clone() override;
void ReloadFocusedFrame(bool bypass_cache) override;
void Undo() override;
@@ -391,6 +388,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void NotifyContextMenuClosed(
const CustomContextMenuContext& context) override;
void ReloadLoFiImages() override;
+ std::vector<blink::mojom::PauseSubresourceLoadingHandlePtr>
+ PauseSubresourceLoading() override;
void ExecuteCustomContextMenuCommand(
int action,
const CustomContextMenuContext& context) override;
@@ -445,12 +444,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
uint32_t max_bitmap_size,
bool bypass_cache,
ImageDownloadCallback callback) override;
- bool IsSubframe() const override;
void Find(int request_id,
const base::string16& search_text,
const blink::WebFindOptions& options) override;
void StopFinding(StopFindAction action) override;
- bool WasRecentlyAudible() override;
bool WasEverAudible() override;
void GetManifest(GetManifestCallback callback) override;
bool IsFullscreenForCurrentTab() const override;
@@ -523,7 +520,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
bool IsNeverVisible() override;
ui::AXMode GetAccessibilityMode() const override;
void AccessibilityEventReceived(
- const std::vector<AXEventNotificationDetails>& details) override;
+ const AXEventNotificationDetails& details) override;
void AccessibilityLocationChangesReceived(
const std::vector<AXLocationChangeNotificationDetails>& details) override;
RenderFrameHost* GetGuestByInstanceID(
@@ -538,6 +535,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void EnterFullscreenMode(const GURL& origin,
const blink::WebFullscreenOptions& options) override;
void ExitFullscreenMode(bool will_cause_resize) override;
+ void FullscreenStateChanged(RenderFrameHost* rfh,
+ bool is_fullscreen) override;
bool ShouldRouteMessageEvent(
RenderFrameHost* target_rfh,
SiteInstance* source_site_instance) const override;
@@ -600,7 +599,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void UpdateTargetURL(RenderViewHost* render_view_host,
const GURL& url) override;
void Close(RenderViewHost* render_view_host) override;
- void RequestMove(const gfx::Rect& new_bounds) override;
+ void RequestSetBounds(const gfx::Rect& new_bounds) override;
void DocumentAvailableInMainFrame(RenderViewHost* render_view_host) override;
void RouteCloseEvent(RenderViewHost* rvh) override;
bool DidAddMessageToConsole(int32_t level,
@@ -625,9 +624,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
int route_id,
const gfx::Rect& initial_rect) override;
void ShowCreatedFullscreenWidget(int process_id, int route_id) override;
- void RequestMediaAccessPermission(
- const MediaStreamRequest& request,
- const MediaResponseCallback& callback) override;
+ void RequestMediaAccessPermission(const MediaStreamRequest& request,
+ MediaResponseCallback callback) override;
bool CheckMediaAccessPermission(RenderFrameHost* render_frame_host,
const url::Origin& security_origin,
MediaStreamType type) override;
@@ -635,9 +633,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
SessionStorageNamespace* GetSessionStorageNamespace(
SiteInstance* instance) override;
SessionStorageNamespaceMap GetSessionStorageNamespaceMap() override;
-#if !defined(OS_ANDROID)
- double GetPendingPageZoomLevel() override;
-#endif // !defined(OS_ANDROID)
FrameTree* GetFrameTree() override;
bool IsOverridingUserAgent() override;
bool IsJavaScriptDialogShowing() const override;
@@ -683,6 +678,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// RenderWidgetHostDelegate --------------------------------------------------
+ ukm::SourceId GetUkmSourceIdForLastCommittedSource() const override;
void RenderWidgetCreated(RenderWidgetHostImpl* render_widget_host) override;
void RenderWidgetDeleted(RenderWidgetHostImpl* render_widget_host) override;
void RenderWidgetGotFocus(RenderWidgetHostImpl* render_widget_host) override;
@@ -694,6 +690,11 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
const gfx::Size& new_size) override;
gfx::Size GetAutoResizeSize() override;
void ResetAutoResizeSize() override;
+
+#if !defined(OS_ANDROID)
+ double GetPendingPageZoomLevel() const override;
+#endif // !defined(OS_ANDROID)
+
KeyboardEventProcessingResult PreHandleKeyboardEvent(
const NativeWebKeyboardEvent& event) override;
void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override;
@@ -711,6 +712,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
const base::Optional<base::string16>& value) override;
void MoveRangeSelectionExtent(const gfx::Point& extent) override;
void SelectRange(const gfx::Point& base, const gfx::Point& extent) override;
+#if defined(OS_MACOSX)
+ void DidChangeTextSelection(const base::string16& text,
+ const gfx::Range& range) override;
+#endif
void MoveCaret(const gfx::Point& extent) override;
void AdjustSelectionByCharacterOffset(int start_adjust,
int end_adjust,
@@ -722,7 +727,9 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
RenderWidgetHostImpl* GetRenderWidgetHostWithPageFocus() override;
void FocusOwningWebContents(
RenderWidgetHostImpl* render_widget_host) override;
- void RendererUnresponsive(RenderWidgetHostImpl* render_widget_host) override;
+ void RendererUnresponsive(
+ RenderWidgetHostImpl* render_widget_host,
+ base::RepeatingClosure hang_monitor_restarter) override;
void RendererResponsive(RenderWidgetHostImpl* render_widget_host) override;
void RequestToLockMouse(RenderWidgetHostImpl* render_widget_host,
bool user_gesture,
@@ -746,8 +753,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
bool OnUpdateDragCursor() override;
bool IsWidgetForMainFrame(RenderWidgetHostImpl* render_widget_host) override;
bool AddDomainInfoToRapporSample(rappor::Sample* sample) override;
- void UpdateUrlForUkmSource(ukm::UkmRecorder* service,
- ukm::SourceId ukm_source_id) override;
void FocusedNodeTouched(bool editable) override;
void DidReceiveCompositorFrame() override;
bool IsShowingContextMenuOnPage() const override;
@@ -780,8 +785,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
RenderFrameHost* new_host,
bool is_main_frame) override;
void NotifyMainFrameSwappedFromRenderManager(
- RenderViewHost* old_host,
- RenderViewHost* new_host) override;
+ RenderFrameHost* old_host,
+ RenderFrameHost* new_host) override;
NavigationControllerImpl& GetControllerForRenderManager() override;
NavigationEntry* GetLastCommittedNavigationEntryForRenderManager() override;
InterstitialPageImpl* GetInterstitialForRenderManager() override;
@@ -957,11 +962,18 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// enumerations.
const std::string& GetMediaDeviceGroupIDSaltBase() const;
+#if defined(OS_ANDROID)
+ // Called by WebContentsAndroid to send the Display Cutout safe area to
+ // DisplayCutoutHostImpl.
+ void SetDisplayCutoutSafeArea(gfx::Insets insets);
+#endif
+
private:
friend class WebContentsObserver;
friend class WebContents; // To implement factory methods.
friend class RenderFrameHostImplBeforeUnloadBrowserTest;
+ friend class WebContentsImplBrowserTest;
FRIEND_TEST_ALL_PREFIXES(WebContentsImplTest, NoJSMessageOnInterstitials);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplTest, UpdateTitle);
@@ -979,6 +991,12 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
FRIEND_TEST_ALL_PREFIXES(WebContentsImplTest,
ResetJavaScriptDialogOnUserNavigate);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplTest, ParseDownloadHeaders);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
+ NotifyFullscreenAcquired);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
+ NotifyFullscreenAcquired_Navigate);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
+ NotifyFullscreenAcquired_SameOrigin);
FRIEND_TEST_ALL_PREFIXES(FormStructureBrowserTest, HTMLFiles);
FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest, HistoryNavigate);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, PageDoesBackAndReload);
@@ -1304,7 +1322,9 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// Helper functions for sending notifications.
void NotifyViewSwapped(RenderViewHost* old_host, RenderViewHost* new_host);
- void NotifyFrameSwapped(RenderFrameHost* old_host, RenderFrameHost* new_host);
+ void NotifyFrameSwapped(RenderFrameHost* old_host,
+ RenderFrameHost* new_host,
+ bool is_main_frame);
void NotifyDisconnected();
void SetEncoding(const std::string& encoding);
@@ -1326,7 +1346,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// |delegate_|.
void OnPreferredSizeChanged(const gfx::Size& old_size);
- void OnUserInteraction(const blink::WebInputEvent::Type type);
+ void SendUserGestureForResourceDispatchHost();
// Internal helper to create WebUI objects associated with |this|. |url| is
// used to determine which WebUI should be created (if any).
@@ -1370,6 +1390,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
AXTreeSnapshotCombiner* combiner,
ui::AXMode ax_mode);
+ // Notify observers that the viewport fit value changed. This is called by
+ // |DisplayCutoutHostImpl|.
+ void NotifyViewportFitChanged(blink::mojom::ViewportFit value);
+
// Data for core operation ---------------------------------------------------
// Delegate for notifying our owner about stuff. Not owned by us.
@@ -1492,6 +1516,9 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// Whether the first visually non-empty paint has occurred.
bool did_first_visually_non_empty_paint_;
+ // SourceId for current page.
+ ukm::SourceId last_committed_source_id_ = ukm::kInvalidSourceId;
+
// Data for misc internal state ----------------------------------------------
// When > 0, the WebContents is currently being captured (e.g., for
@@ -1614,10 +1641,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// completed making layout changes to effect an exit from fullscreen mode.
bool fullscreen_widget_had_focus_at_shutdown_;
- // Whether this WebContents is responsible for displaying a subframe in a
- // different process from its parent page.
- bool is_subframe_;
-
// When a new tab is created asynchronously, stores the OpenURLParams needed
// to continue loading the page once the tab is ready.
std::unique_ptr<OpenURLParams> delayed_open_url_params_;
@@ -1724,6 +1747,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
bool has_persistent_video_ = false;
+ bool is_currently_audible_ = false;
bool was_ever_audible_ = false;
// Helper variable for resolving races in UpdateTargetURL / ClearTargetURL.
@@ -1732,6 +1756,18 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// Whether we should override user agent in new tabs.
bool should_override_user_agent_in_new_tabs_ = false;
+ // Gets notified about changes in viewport fit events.
+ std::unique_ptr<DisplayCutoutHostImpl> display_cutout_host_impl_;
+
+ // Stores a set of FrameTreeNode ids that are fullscreen.
+ using FullscreenFrameNodes = std::set<int>;
+ FullscreenFrameNodes fullscreen_frame_tree_nodes_;
+
+ // Stores the ID of the current fullscreen |FrameTreeNode| or
+ // |kNoFrameTreeNodeId| if the tab is not currently fullscreen.
+ int current_fullscreen_frame_tree_node_id_ =
+ RenderFrameHost::kNoFrameTreeNodeId;
+
base::WeakPtrFactory<WebContentsImpl> loading_weak_factory_;
base::WeakPtrFactory<WebContentsImpl> weak_factory_;
diff --git a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
index 7c85b1f8fe1..4286d9a5c62 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -6,6 +6,7 @@
#include <utility>
#include <vector>
+#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
@@ -33,9 +34,11 @@
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_frame_host.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/site_isolation_policy.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
@@ -120,6 +123,13 @@ class WebContentsImplBrowserTest : public ContentBrowserTest {
host_resolver()->AddRule("*", "127.0.0.1");
}
+ bool CurrentFullscreenFrameTreeNodeIsEmpty() {
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ return web_contents->current_fullscreen_frame_tree_node_id_ ==
+ RenderFrameHost::kNoFrameTreeNodeId;
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(WebContentsImplBrowserTest);
};
@@ -1735,7 +1745,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
RenderProcessHost* process = web_contents->GetMainFrame()->GetProcess();
int renderer_id = process->GetID();
ASSERT_TRUE(process);
- EXPECT_TRUE(process->HasConnection());
+ EXPECT_TRUE(process->IsInitializedAndNotDead());
// Navigate the WebContents.
GURL url(embedded_test_server()->GetURL("c.com", "/title3.html"));
@@ -1788,7 +1798,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
RenderProcessHost* process = web_contents->GetMainFrame()->GetProcess();
int renderer_id = process->GetID();
ASSERT_TRUE(process);
- EXPECT_FALSE(process->HasConnection());
+ EXPECT_FALSE(process->IsInitializedAndNotDead());
EXPECT_EQ(base::kNullProcessHandle, process->GetProcess().Handle());
// Navigate the WebContents.
@@ -1802,7 +1812,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_TRUE(same_tab_observer.last_navigation_succeeded());
// The process should be launched now.
- EXPECT_TRUE(process->HasConnection());
+ EXPECT_TRUE(process->IsInitializedAndNotDead());
EXPECT_NE(base::kNullProcessHandle, process->GetProcess().Handle());
// Check that the RenderProcessHost and its ID didn't change.
@@ -2481,4 +2491,259 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, PausePageScheduledTasks) {
EXPECT_GT(next_text_length, text_length);
}
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ PopupWindowBrowserNavResumeLoad) {
+ // This test verifies a pop up that requires navigation from browser side
+ // works with a delegate that delays navigations of pop ups.
+ // Create a file: scheme pop up from a file: scheme page, which requires
+ // requires an OpenURL IPC to the browser process.
+ base::FilePath test_data_dir;
+ CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir));
+ base::FilePath simple_links_path =
+ test_data_dir.Append(GetTestDataFilePath())
+ .Append(FILE_PATH_LITERAL("simple_links.html"));
+ GURL url(base::FilePath::StringType(FILE_PATH_LITERAL("file://")) +
+ simple_links_path.value());
+
+ shell()->set_delay_popup_contents_delegate_for_testing(true);
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ Shell* new_shell = nullptr;
+ WebContents* new_contents = nullptr;
+ {
+ ShellAddedObserver new_shell_observer;
+ bool success = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ shell(),
+ "window.domAutomationController.send(clickDeadFileNewWindowLink());",
+ &success));
+ new_shell = new_shell_observer.GetShell();
+ new_contents = new_shell->web_contents();
+ // Delaying popup holds the initial load.
+ EXPECT_FALSE(WaitForLoadStop(new_contents));
+ }
+
+ EXPECT_FALSE(new_contents->GetDelegate());
+ new_contents->SetDelegate(new_shell);
+ new_contents->ResumeLoadingCreatedWebContents();
+ // Dead file link may or may not load depending on OS. The result is not
+ // relevant for this test, so not checking the the result.
+ WaitForLoadStop(new_contents);
+ EXPECT_TRUE(new_contents->GetLastCommittedURL().SchemeIs("file"));
+}
+
+namespace {
+
+class FullscreenWebContentsObserver : public WebContentsObserver {
+ public:
+ FullscreenWebContentsObserver(WebContents* web_contents,
+ RenderFrameHost* wanted_rfh)
+ : WebContentsObserver(web_contents), wanted_rfh_(wanted_rfh) {}
+
+ // WebContentsObserver override.
+ void DidAcquireFullscreen(RenderFrameHost* rfh) override {
+ EXPECT_EQ(wanted_rfh_, rfh);
+ EXPECT_FALSE(found_value_);
+
+ if (rfh == wanted_rfh_) {
+ found_value_ = true;
+ run_loop_.Quit();
+ }
+ }
+
+ void Wait() {
+ if (!found_value_)
+ run_loop_.Run();
+ }
+
+ private:
+ base::RunLoop run_loop_;
+ bool found_value_ = false;
+ RenderFrameHost* wanted_rfh_;
+
+ DISALLOW_COPY_AND_ASSIGN(FullscreenWebContentsObserver);
+};
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NotifyFullscreenAcquired) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ TestWCDelegateForDialogsAndFullscreen test_delegate;
+ web_contents->SetDelegate(&test_delegate);
+
+ GURL url = embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b{allowfullscreen})");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ RenderFrameHost* main_frame = web_contents->GetMainFrame();
+ int main_frame_id = main_frame->GetFrameTreeNodeId();
+
+ RenderFrameHost* child_frame = ChildFrameAt(main_frame, 0);
+ int child_frame_id = child_frame->GetFrameTreeNodeId();
+
+ WebContentsImpl::FullscreenFrameNodes nodes;
+ EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
+ EXPECT_TRUE(CurrentFullscreenFrameTreeNodeIsEmpty());
+
+ // Make the top page fullscreen.
+ {
+ FullscreenWebContentsObserver observer(web_contents, main_frame);
+ EXPECT_TRUE(
+ ExecuteScript(main_frame, "document.body.webkitRequestFullscreen();"));
+ observer.Wait();
+ }
+
+ nodes.insert(main_frame_id);
+ EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
+ EXPECT_EQ(main_frame_id,
+ web_contents->current_fullscreen_frame_tree_node_id_);
+
+ // Make the child frame fullscreen.
+ {
+ FullscreenWebContentsObserver observer(web_contents, child_frame);
+ EXPECT_TRUE(
+ ExecuteScript(child_frame, "document.body.webkitRequestFullscreen();"));
+ observer.Wait();
+ }
+
+ nodes.insert(child_frame_id);
+ EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
+ EXPECT_EQ(child_frame_id,
+ web_contents->current_fullscreen_frame_tree_node_id_);
+
+ // Exit fullscreen on the child frame.
+ // This will not work with --site-per-process until crbug.com/617369
+ // is fixed.
+ if (!SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+ {
+ FullscreenWebContentsObserver observer(web_contents, main_frame);
+ EXPECT_TRUE(
+ ExecuteScript(child_frame, "document.webkitExitFullscreen();"));
+ observer.Wait();
+ }
+
+ nodes.erase(child_frame_id);
+ EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
+ EXPECT_EQ(main_frame_id,
+ web_contents->current_fullscreen_frame_tree_node_id_);
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ NotifyFullscreenAcquired_Navigate) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ TestWCDelegateForDialogsAndFullscreen test_delegate;
+ test_delegate.WillWaitForFullscreenExit();
+ web_contents->SetDelegate(&test_delegate);
+
+ GURL url = embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b{allowfullscreen})");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ RenderFrameHost* main_frame = web_contents->GetMainFrame();
+ int main_frame_id = main_frame->GetFrameTreeNodeId();
+
+ RenderFrameHost* child_frame = ChildFrameAt(main_frame, 0);
+ int child_frame_id = child_frame->GetFrameTreeNodeId();
+
+ WebContentsImpl::FullscreenFrameNodes nodes;
+ EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
+ EXPECT_TRUE(CurrentFullscreenFrameTreeNodeIsEmpty());
+
+ // Make the top page fullscreen.
+ {
+ FullscreenWebContentsObserver observer(web_contents, main_frame);
+ EXPECT_TRUE(
+ ExecuteScript(main_frame, "document.body.webkitRequestFullscreen();"));
+ observer.Wait();
+ }
+
+ nodes.insert(main_frame_id);
+ EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
+ EXPECT_EQ(main_frame_id,
+ web_contents->current_fullscreen_frame_tree_node_id_);
+
+ // Make the child frame fullscreen.
+ {
+ FullscreenWebContentsObserver observer(web_contents, child_frame);
+ EXPECT_TRUE(
+ ExecuteScript(child_frame, "document.body.webkitRequestFullscreen();"));
+ observer.Wait();
+ }
+
+ nodes.insert(child_frame_id);
+ EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
+ EXPECT_EQ(child_frame_id,
+ web_contents->current_fullscreen_frame_tree_node_id_);
+
+ // Perform a cross origin navigation on the main frame.
+ EXPECT_TRUE(
+ NavigateToURL(shell(), embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html")));
+ EXPECT_EQ(0u, web_contents->fullscreen_frame_tree_nodes_.size());
+ EXPECT_TRUE(CurrentFullscreenFrameTreeNodeIsEmpty());
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ NotifyFullscreenAcquired_SameOrigin) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ TestWCDelegateForDialogsAndFullscreen test_delegate;
+ web_contents->SetDelegate(&test_delegate);
+
+ GURL url = embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a{allowfullscreen})");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ RenderFrameHost* main_frame = web_contents->GetMainFrame();
+ int main_frame_id = main_frame->GetFrameTreeNodeId();
+
+ RenderFrameHost* child_frame = ChildFrameAt(main_frame, 0);
+ int child_frame_id = child_frame->GetFrameTreeNodeId();
+
+ WebContentsImpl::FullscreenFrameNodes nodes;
+ EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
+ EXPECT_TRUE(CurrentFullscreenFrameTreeNodeIsEmpty());
+
+ // Make the top page fullscreen.
+ {
+ FullscreenWebContentsObserver observer(web_contents, main_frame);
+ EXPECT_TRUE(
+ ExecuteScript(main_frame, "document.body.webkitRequestFullscreen();"));
+ observer.Wait();
+ }
+
+ nodes.insert(main_frame_id);
+ EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
+ EXPECT_EQ(main_frame_id,
+ web_contents->current_fullscreen_frame_tree_node_id_);
+
+ // Make the child frame fullscreen.
+ {
+ FullscreenWebContentsObserver observer(web_contents, child_frame);
+ EXPECT_TRUE(
+ ExecuteScript(child_frame, "document.body.webkitRequestFullscreen();"));
+ observer.Wait();
+ }
+
+ nodes.insert(child_frame_id);
+ EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
+ EXPECT_EQ(child_frame_id,
+ web_contents->current_fullscreen_frame_tree_node_id_);
+
+ // Exit fullscreen on the child frame.
+ {
+ FullscreenWebContentsObserver observer(web_contents, main_frame);
+ EXPECT_TRUE(ExecuteScript(child_frame, "document.webkitExitFullscreen();"));
+ observer.Wait();
+ }
+
+ nodes.erase(child_frame_id);
+ EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
+ EXPECT_EQ(main_frame_id,
+ web_contents->current_fullscreen_frame_tree_node_id_);
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
index 9b07e24d464..c403c397331 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -34,6 +34,7 @@
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
+#include "content/public/browser/overlay_window.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/ssl_host_state_delegate.h"
#include "content/public/browser/storage_partition.h"
@@ -441,6 +442,10 @@ TEST_F(WebContentsImplTest, DirectNavigationToViewSourceWebUI) {
load_params.is_renderer_initiated = false;
controller().LoadURLWithParams(load_params);
+ NavigationRequest* request =
+ main_test_rfh()->frame_tree_node()->navigation_request();
+ CHECK(request);
+
int entry_id = cont.GetPendingEntry()->GetUniqueID();
// Did we get the expected message?
EXPECT_TRUE(process()->sink().GetFirstMessageMatching(
@@ -454,6 +459,9 @@ TEST_F(WebContentsImplTest, DirectNavigationToViewSourceWebUI) {
FrameHostMsg_DidStartProvisionalLoad(1, kRewrittenURL,
std::vector<GURL>(),
base::TimeTicks::Now()));
+ main_test_rfh()->SimulateCommitProcessed(
+ request->navigation_handle()->GetNavigationId(),
+ true /* was_successful */);
main_test_rfh()->SendNavigateWithParams(&params,
false /* was_within_same_document */);
@@ -472,24 +480,21 @@ TEST_F(WebContentsImplTest, SimpleNavigation) {
SiteInstance* instance1 = contents()->GetSiteInstance();
EXPECT_EQ(nullptr, contents()->GetPendingMainFrame());
- // Navigate to URL
+ // Navigate until ready to commit.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(url, contents());
+ navigation->ReadyToCommit();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(instance1, orig_rfh->GetSiteInstance());
// Controller's pending entry will have a null site instance until we assign
- // it in DidNavigate.
+ // it in Commit.
EXPECT_EQ(
nullptr,
NavigationEntryImpl::FromNavigationEntry(controller().GetVisibleEntry())->
site_instance());
- // DidNavigate from the page
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ navigation->Commit();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
EXPECT_EQ(instance1, orig_rfh->GetSiteInstance());
@@ -549,10 +554,10 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
// Navigate to new site
const GURL url2("http://www.yahoo.com");
- controller().LoadURL(
- url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ auto new_site_navigation =
+ NavigationSimulator::CreateBrowserInitiated(url2, contents());
+ new_site_navigation->ReadyToCommit();
int entry_id = controller().GetPendingEntry()->GetUniqueID();
- orig_rfh->PrepareForCommit();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(url, contents()->GetLastCommittedURL());
EXPECT_EQ(url2, contents()->GetVisibleURL());
@@ -587,9 +592,10 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
// Going back should switch SiteInstances again. The first SiteInstance is
// stored in the NavigationEntry, so it should be the same as at the start.
// We should use the same RFH as before, swapping it back in.
- controller().GoBack();
+ auto back_navigation =
+ NavigationSimulator::CreateHistoryNavigation(-1, contents());
+ back_navigation->ReadyToCommit();
entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
TestRenderFrameHost* goback_rfh = contents()->GetPendingMainFrame();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
@@ -623,13 +629,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundariesAfterCrash) {
// Navigate to URL. First URL should use first RenderViewHost.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
-
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh->GetRenderViewHost(), contents()->GetRenderViewHost());
@@ -638,21 +638,19 @@ TEST_F(WebContentsImplTest, CrossSiteBoundariesAfterCrash) {
orig_rfh->GetProcess()->SimulateCrash();
EXPECT_FALSE(orig_rfh->IsRenderFrameLive());
- // Navigate to new site. We should not go into PENDING.
+ // Start navigating to a new site. We should not go into PENDING.
const GURL url2("http://www.yahoo.com");
- controller().LoadURL(
- url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
+ auto navigation_to_url2 =
+ NavigationSimulator::CreateBrowserInitiated(url2, contents());
+ navigation_to_url2->ReadyToCommit();
+
TestRenderFrameHost* new_rfh = main_test_rfh();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(nullptr, contents()->GetPendingMainFrame());
EXPECT_NE(orig_rfh, new_rfh);
EXPECT_EQ(orig_rvh_delete_count, 1);
- // DidNavigate from the new page
- contents()->TestDidNavigate(new_rfh, entry_id, true, url2,
- ui::PAGE_TRANSITION_TYPED);
+ navigation_to_url2->Commit();
SiteInstance* instance2 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
@@ -669,37 +667,24 @@ TEST_F(WebContentsImplTest, CrossSiteBoundariesAfterCrash) {
// both contentses to a new site will place both contentses in a single
// SiteInstance.
TEST_F(WebContentsImplTest, NavigateTwoTabsCrossSite) {
- TestRenderFrameHost* orig_rfh = main_test_rfh();
SiteInstance* instance1 = contents()->GetSiteInstance();
// Navigate to URL. First URL should use first RenderViewHost.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
// Open a new contents with the same SiteInstance, navigated to the same site.
std::unique_ptr<TestWebContents> contents2(
TestWebContents::Create(browser_context(), instance1));
- contents2->GetController().LoadURL(url, Referrer(),
- ui::PAGE_TRANSITION_TYPED,
- std::string());
- entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID();
- contents2->GetMainFrame()->PrepareForCommit();
- // Need this page id to be 2 since the site instance is the same (which is the
- // scope of page IDs) and we want to consider this a new page.
- contents2->TestDidNavigate(contents2->GetMainFrame(), entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents2.get(), url);
+ EXPECT_EQ(instance1, contents2->GetSiteInstance());
// Navigate first contents to a new site.
const GURL url2a("http://www.yahoo.com");
controller().LoadURL(url2a, Referrer(), ui::PAGE_TRANSITION_LINK,
std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- orig_rfh->PrepareForCommit();
+ int entry_id = controller().GetPendingEntry()->GetUniqueID();
+ contents()->GetMainFrame()->PrepareForCommit();
TestRenderFrameHost* pending_rfh_a = contents()->GetPendingMainFrame();
if (AreAllSitesIsolatedForTesting())
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
@@ -748,12 +733,7 @@ TEST_F(WebContentsImplTest, NavigateFromSitelessUrl) {
browser_client.set_assign_site_for_url(false);
// Navigate to an URL that will not assign a new SiteInstance.
const GURL native_url("non-site-url://stuffandthings");
- controller().LoadURL(
- native_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, native_url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), native_url);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -766,16 +746,14 @@ TEST_F(WebContentsImplTest, NavigateFromSitelessUrl) {
browser_client.set_assign_site_for_url(true);
// Navigate to new site (should keep same site instance).
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(url, contents());
+ navigation->ReadyToCommit();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(native_url, contents()->GetLastCommittedURL());
EXPECT_EQ(url, contents()->GetVisibleURL());
EXPECT_FALSE(contents()->GetPendingMainFrame());
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ navigation->Commit();
// Keep the number of active frames in orig_rfh's SiteInstance
// non-zero so that orig_rfh doesn't get deleted when it gets
@@ -791,7 +769,7 @@ TEST_F(WebContentsImplTest, NavigateFromSitelessUrl) {
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
+ int entry_id = controller().GetPendingEntry()->GetUniqueID();
orig_rfh->PrepareForCommit();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(url, contents()->GetLastCommittedURL());
@@ -861,12 +839,7 @@ TEST_F(WebContentsImplTest, NavigateFromRestoredSitelessUrl) {
// Navigate to a regular site and verify that the SiteInstance was kept.
browser_client.set_assign_site_for_url(true);
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry = controller().GetPendingEntry();
- orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry->GetUniqueID(), true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
// Cleanup.
@@ -907,13 +880,7 @@ TEST_F(WebContentsImplTest, NavigateFromRestoredRegularUrl) {
// Navigate to another site and verify that a new SiteInstance was created.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry = controller().GetPendingEntry();
- orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(contents()->GetPendingMainFrame(),
- entry->GetUniqueID(), true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
EXPECT_NE(orig_instance, contents()->GetSiteInstance());
// Cleanup.
@@ -923,22 +890,16 @@ TEST_F(WebContentsImplTest, NavigateFromRestoredRegularUrl) {
// Test that we can find an opener RVH even if it's pending.
// http://crbug.com/176252.
TEST_F(WebContentsImplTest, FindOpenerRVHWhenPending) {
- TestRenderFrameHost* orig_rfh = main_test_rfh();
// Navigate to a URL.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
// Start to navigate first tab to a new site, so that it has a pending RVH.
const GURL url2("http://www.yahoo.com");
- controller().LoadURL(
- url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- orig_rfh->PrepareForCommit();
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(url2, contents());
+ navigation->ReadyToCommit();
TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
SiteInstance* instance = pending_rfh->GetSiteInstance();
@@ -961,9 +922,7 @@ TEST_F(WebContentsImplTest, FindOpenerRVHWhenPending) {
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, entry_id, true, url2,
- ui::PAGE_TRANSITION_TYPED);
+ navigation->Commit();
EXPECT_FALSE(
contents()->GetRenderManager()->GetRenderFrameProxyHost(instance));
}
@@ -981,29 +940,20 @@ TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
// Navigate to URL.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
// Open a related contents to a second site.
std::unique_ptr<TestWebContents> contents2(
TestWebContents::Create(browser_context(), instance1));
const GURL url2("http://www.yahoo.com");
- contents2->GetController().LoadURL(url2, Referrer(),
- ui::PAGE_TRANSITION_TYPED,
- std::string());
- entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID();
- contents2->GetMainFrame()->PrepareForCommit();
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(url2, contents2.get());
+ navigation->ReadyToCommit();
// The first RVH in contents2 isn't live yet, so we shortcut the cross site
// pending.
- TestRenderFrameHost* rfh2 = contents2->GetMainFrame();
EXPECT_FALSE(contents2->CrossProcessNavigationPending());
- contents2->TestDidNavigate(rfh2, entry_id, true, url2,
- ui::PAGE_TRANSITION_TYPED);
+ navigation->Commit();
SiteInstance* instance2 = contents2->GetSiteInstance();
EXPECT_NE(instance1, instance2);
EXPECT_FALSE(contents2->CrossProcessNavigationPending());
@@ -1018,13 +968,7 @@ TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
// Navigate to the new site. Doesn't switch SiteInstancees, because we
// compare against the current URL, not the SiteInstance's site.
const GURL url3("http://mail.yahoo.com");
- controller().LoadURL(
- url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url3,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url3);
SiteInstance* instance4 = contents()->GetSiteInstance();
EXPECT_EQ(instance1, instance4);
}
@@ -1037,12 +981,7 @@ TEST_F(WebContentsImplTest, CrossSiteUnloadHandlers) {
// Navigate to URL. First URL should use first RenderViewHost.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -1061,7 +1000,7 @@ TEST_F(WebContentsImplTest, CrossSiteUnloadHandlers) {
// Navigate again, but simulate an onbeforeunload approval.
controller().LoadURL(
url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
+ int entry_id = controller().GetPendingEntry()->GetUniqueID();
EXPECT_TRUE(orig_rfh->is_waiting_for_beforeunload_ack());
now = base::TimeTicks::Now();
orig_rfh->PrepareForCommit();
@@ -1090,12 +1029,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationPreempted) {
// Navigate to URL. First URL should use first RenderFrameHost.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -1213,18 +1147,12 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackOldNavigationIgnored) {
// Start with a web ui page, which gets a new RVH with WebUI bindings.
GURL url1(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost));
- controller().LoadURL(url1, Referrer(), ui::PAGE_TRANSITION_TYPED,
- std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
TestRenderFrameHost* webui_rfh = main_test_rfh();
- webui_rfh->PrepareForCommit();
- contents()->TestDidNavigate(webui_rfh, entry_id, true, url1,
- ui::PAGE_TRANSITION_TYPED);
NavigationEntry* entry1 = controller().GetLastCommittedEntry();
SiteInstance* instance1 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- EXPECT_EQ(webui_rfh, main_test_rfh());
EXPECT_EQ(url1, entry1->GetURL());
EXPECT_EQ(instance1,
NavigationEntryImpl::FromNavigationEntry(entry1)->site_instance());
@@ -1232,24 +1160,12 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackOldNavigationIgnored) {
// Navigate to new site.
const GURL url2("http://www.google.com");
- controller().LoadURL(url2, Referrer(), ui::PAGE_TRANSITION_TYPED,
- std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- EXPECT_TRUE(contents()->CrossProcessNavigationPending());
- TestRenderFrameHost* google_rfh = contents()->GetPendingMainFrame();
-
- // Simulate beforeunload approval.
- EXPECT_TRUE(webui_rfh->is_waiting_for_beforeunload_ack());
- webui_rfh->PrepareForCommit();
-
- // DidNavigate from the pending page.
- contents()->TestDidNavigate(google_rfh, entry_id, true, url2,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url2);
+ TestRenderFrameHost* google_rfh = main_test_rfh();
NavigationEntry* entry2 = controller().GetLastCommittedEntry();
SiteInstance* instance2 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- EXPECT_EQ(google_rfh, main_test_rfh());
EXPECT_NE(instance1, instance2);
EXPECT_FALSE(contents()->GetPendingMainFrame());
EXPECT_EQ(url2, entry2->GetURL());
@@ -1259,13 +1175,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackOldNavigationIgnored) {
// Navigate to third page on same site.
const GURL url3("http://news.google.com");
- controller().LoadURL(url3, Referrer(), ui::PAGE_TRANSITION_TYPED,
- std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(google_rfh, entry_id, true, url3,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url3);
NavigationEntry* entry3 = controller().GetLastCommittedEntry();
SiteInstance* instance3 = contents()->GetSiteInstance();
@@ -1309,12 +1219,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationNotPreemptedByFrame) {
// Navigate to URL. First URL should use the original RenderFrameHost.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -1342,7 +1247,7 @@ namespace {
void SetAsNonUserGesture(FrameHostMsg_DidCommitProvisionalLoad_Params* params) {
params->gesture = NavigationGestureAuto;
}
-}
+} // namespace
// Test that a cross-site navigation is not preempted if the previous
// renderer sends a FrameNavigate message just before being told to stop.
@@ -1391,45 +1296,35 @@ TEST_F(WebContentsImplTest, CrossSiteNotPreemptedDuringBeforeUnload) {
// Test that NavigationEntries have the correct page state after going
// forward and back. Prevents regression for bug 1116137.
TEST_F(WebContentsImplTest, NavigationEntryContentState) {
- TestRenderFrameHost* orig_rfh = main_test_rfh();
// Navigate to URL. There should be no committed entry yet.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(url, contents());
+ navigation->ReadyToCommit();
NavigationEntry* entry = controller().GetLastCommittedEntry();
EXPECT_EQ(nullptr, entry);
- // Committed entry should have page state after DidNavigate.
- orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ // Committed entry should have page state.
+ navigation->Commit();
entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry->GetPageState().IsValid());
// Navigate to same site.
const GURL url2("http://images.google.com");
- controller().LoadURL(
- url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
+ auto navigation2 =
+ NavigationSimulator::CreateBrowserInitiated(url2, contents());
+ navigation2->ReadyToCommit();
entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry->GetPageState().IsValid());
- // Committed entry should have page state after DidNavigate.
- orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url2,
- ui::PAGE_TRANSITION_TYPED);
+ // Committed entry should have page state.
+ navigation2->Commit();
entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry->GetPageState().IsValid());
// Now go back. Committed entry should still have page state.
- controller().GoBack();
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(
- orig_rfh, entry_id, false, url,
- controller().GetPendingEntry()->GetTransitionType());
+ NavigationSimulator::GoBack(contents());
entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry->GetPageState().IsValid());
}
@@ -1442,9 +1337,7 @@ TEST_F(WebContentsImplTest, NavigationEntryContentStateNewWindow) {
// Navigate to about:blank.
const GURL url(url::kAboutBlankURL);
- orig_rfh->SendRendererInitiatedNavigationRequest(url, false);
- contents()->TestDidNavigate(orig_rfh, 0, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
// Should have a page state here.
NavigationEntry* entry = controller().GetLastCommittedEntry();
@@ -1458,14 +1351,9 @@ TEST_F(WebContentsImplTest, NavigationEntryContentStateNewWindow) {
// Navigating to a normal page should not cause a process swap.
const GURL new_url("http://www.google.com");
- controller().LoadURL(new_url, Referrer(),
- ui::PAGE_TRANSITION_TYPED, std::string());
- entry = controller().GetPendingEntry();
- EXPECT_FALSE(contents()->CrossProcessNavigationPending());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), new_url);
+
EXPECT_EQ(orig_rfh, main_test_rfh());
- orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry->GetUniqueID(), true, new_url,
- ui::PAGE_TRANSITION_TYPED);
NavigationEntryImpl* entry_impl2 = NavigationEntryImpl::FromNavigationEntry(
controller().GetLastCommittedEntry());
EXPECT_EQ(site_instance_id, entry_impl2->site_instance()->GetId());
@@ -1481,12 +1369,7 @@ TEST_F(WebContentsImplTest, NavigationExitsFullscreen) {
// Navigate to a site.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
EXPECT_EQ(orig_rfh, main_test_rfh());
// Toggle fullscreen mode on (as if initiated via IPC from renderer).
@@ -1499,13 +1382,7 @@ TEST_F(WebContentsImplTest, NavigationExitsFullscreen) {
// Navigate to a new site.
const GURL url2("http://www.yahoo.com");
- controller().LoadURL(
- url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- TestRenderFrameHost* const pending_rfh = contents()->GetPendingMainFrame();
- contents()->TestDidNavigate(pending_rfh, entry_id, true, url2,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url2);
// Confirm fullscreen has exited.
EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
@@ -1523,23 +1400,12 @@ TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
// Navigate to a site.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
EXPECT_EQ(orig_rfh, main_test_rfh());
// Now, navigate to another page on the same site.
const GURL url2("http://www.google.com/search?q=kittens");
- controller().LoadURL(
- url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- orig_rfh->PrepareForCommit();
- EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- contents()->TestDidNavigate(orig_rfh, entry_id, true, url2,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url2);
EXPECT_EQ(orig_rfh, main_test_rfh());
// Sanity-check: Confirm we're not starting out in fullscreen mode.
@@ -1555,16 +1421,9 @@ TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
// Navigate backward (or forward).
if (i == 0)
- controller().GoBack();
+ NavigationSimulator::GoBack(contents());
else
- controller().GoForward();
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- orig_rfh->PrepareForCommit();
- EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- EXPECT_EQ(orig_rfh, main_test_rfh());
- contents()->TestDidNavigate(orig_rfh, entry_id, false, url,
- ui::PAGE_TRANSITION_FORWARD_BACK);
- orig_rfh->SimulateNavigationStop();
+ NavigationSimulator::GoForward(contents());
// Confirm fullscreen has exited.
EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
@@ -1582,12 +1441,7 @@ TEST_F(WebContentsImplTest, CrashExitsFullscreen) {
// Navigate to a site.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigate(main_test_rfh(), entry_id, true,
- url, ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
// Toggle fullscreen mode on (as if initiated via IPC from renderer).
EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
@@ -1618,7 +1472,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromBrowserWithNewNavigationDontProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial.
@@ -1764,7 +1618,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromBrowserNewNavigationProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial
@@ -1945,7 +1799,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenNavigate) {
// While interstitial showing, navigate to a new URL.
const GURL url2("http://www.yahoo.com");
- NavigationSimulator::NavigateAndCommitFromDocument(url2, main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url2);
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
@@ -1957,7 +1811,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenNavigate) {
TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show interstitial.
@@ -1997,7 +1851,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) {
TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
EXPECT_EQ(1, controller().GetEntryCount());
NavigationEntry* entry = controller().GetLastCommittedEntry();
@@ -2039,7 +1893,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) {
TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenNavigate) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show interstitial.
@@ -2119,7 +1973,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenCloseAndShutdown) {
TEST_F(WebContentsImplTest, CreateInterstitialForClosingTab) {
// Navigate to a page.
GURL url1("http://www.google.com");
- NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger an interstitial.
@@ -2169,7 +2023,7 @@ TEST_F(WebContentsImplTest, CreateInterstitialForClosingTab) {
TEST_F(WebContentsImplTest, TabNavigationDoesntRaceInterstitial) {
// Navigate to a page.
GURL url1("http://www.google.com");
- NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger an interstitial.
@@ -2214,7 +2068,7 @@ TEST_F(WebContentsImplTest, TabNavigationDoesntRaceInterstitial) {
TEST_F(WebContentsImplTest, ShowInterstitialProceedMultipleCommands) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -2250,8 +2104,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedMultipleCommands) {
TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
// Navigate to a page so we have a navigation entry in the controller.
GURL start_url("http://www.google.com");
- NavigationSimulator::NavigateAndCommitFromDocument(start_url,
- main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), start_url);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -2306,8 +2159,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) {
// Navigate to a page so we have a navigation entry in the controller.
GURL start_url("http://www.google.com");
- NavigationSimulator::NavigateAndCommitFromDocument(start_url,
- main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), start_url);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -2528,13 +2380,7 @@ TEST_F(WebContentsImplTest, NoJSMessageOnInterstitials) {
const GURL kGURL(kUrl);
// Start a navigation to a page
- contents()->GetController().LoadURL(
- kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- main_test_rfh()->PrepareForCommit();
- // DidNavigate from the page
- contents()->TestDidNavigate(main_test_rfh(), entry_id, true,
- kGURL, ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kGURL);
// Simulate showing an interstitial while the page is showing.
TestInterstitialPage::InterstitialState state =
@@ -2561,7 +2407,7 @@ TEST_F(WebContentsImplTest, NoJSMessageOnInterstitials) {
TEST_F(WebContentsImplTest, CopyStateFromAndPruneSourceInterstitial) {
// Navigate to a page.
GURL url1("http://www.google.com");
- NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial
@@ -3555,7 +3401,56 @@ class PictureInPictureDelegate : public WebContentsDelegate {
DISALLOW_COPY_AND_ASSIGN(PictureInPictureDelegate);
};
+class TestOverlayWindow : public OverlayWindow {
+ public:
+ TestOverlayWindow() = default;
+ ~TestOverlayWindow() override{};
+
+ static std::unique_ptr<OverlayWindow> Create(
+ PictureInPictureWindowController* controller) {
+ return std::unique_ptr<OverlayWindow>(new TestOverlayWindow());
+ }
+
+ bool IsActive() const override { return false; }
+ void Close() override {}
+ void Show() override {}
+ void Hide() override {}
+ bool IsVisible() const override { return false; }
+ bool IsAlwaysOnTop() const override { return false; }
+ ui::Layer* GetLayer() override { return nullptr; }
+ gfx::Rect GetBounds() const override { return gfx::Rect(); }
+ void UpdateVideoSize(const gfx::Size& natural_size) override {}
+ void SetPlaybackState(PlaybackState playback_state) override {}
+ ui::Layer* GetWindowBackgroundLayer() override { return nullptr; }
+ ui::Layer* GetVideoLayer() override { return nullptr; }
+ gfx::Rect GetVideoBounds() override { return gfx::Rect(); }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestOverlayWindow);
+};
+
+class PictureInPictureTestBrowserClient : public TestContentBrowserClient {
+ public:
+ PictureInPictureTestBrowserClient()
+ : original_browser_client_(SetBrowserClientForTesting(this)) {}
+
+ ~PictureInPictureTestBrowserClient() override {
+ SetBrowserClientForTesting(original_browser_client_);
+ }
+
+ std::unique_ptr<OverlayWindow> CreateWindowForPictureInPicture(
+ PictureInPictureWindowController* controller) override {
+ return TestOverlayWindow::Create(controller);
+ }
+
+ private:
+ ContentBrowserClient* original_browser_client_;
+};
+
TEST_F(WebContentsImplTest, EnterPictureInPicture) {
+ PictureInPictureTestBrowserClient browser_client;
+ SetBrowserClientForTesting(&browser_client);
+
const int kPlayerVideoOnlyId = 30; /* arbitrary and used for tests */
PictureInPictureDelegate delegate;
@@ -3583,7 +3478,7 @@ TEST_F(WebContentsImplTest, EnterPictureInPicture) {
gfx::Size(42, 42) /* natural_size */, 1 /* request_id */));
EXPECT_TRUE(observer->GetPictureInPictureVideoMediaPlayerId().has_value());
EXPECT_EQ(kPlayerVideoOnlyId,
- observer->GetPictureInPictureVideoMediaPlayerId()->second);
+ observer->GetPictureInPictureVideoMediaPlayerId()->delegate_id);
// Picture-in-Picture media player id should not be reset when the media is
// destroyed (e.g. video stops playing). This allows the Picture-in-Picture
@@ -3672,19 +3567,20 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager {
} // namespace
TEST_F(WebContentsImplTest, ResetJavaScriptDialogOnUserNavigate) {
+ const GURL kUrl("http://www.google.com");
+ const GURL kUrl2("http://www.google.com/sub");
TestJavaScriptDialogManager dialog_manager;
contents()->SetJavaScriptDialogManagerForTesting(&dialog_manager);
// A user-initiated navigation.
- contents()->TestDidNavigate(main_test_rfh(), 0, true,
- GURL("about:whatever"),
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl);
EXPECT_EQ(1u, dialog_manager.reset_count());
// An automatic navigation.
- main_test_rfh()->SendNavigateWithModificationCallback(
- 0, true, GURL(url::kAboutBlankURL), base::Bind(SetAsNonUserGesture));
-
+ auto navigation =
+ NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
+ navigation->SetHasUserGesture(false);
+ navigation->Commit();
EXPECT_EQ(1u, dialog_manager.reset_count());
contents()->SetJavaScriptDialogManagerForTesting(nullptr);
diff --git a/chromium/content/browser/web_contents/web_contents_view.h b/chromium/content/browser/web_contents/web_contents_view.h
index cf8c74f4c74..41e44d5d658 100644
--- a/chromium/content/browser/web_contents/web_contents_view.h
+++ b/chromium/content/browser/web_contents/web_contents_view.h
@@ -110,9 +110,13 @@ class WebContentsView {
// fully created.
virtual void RenderViewCreated(RenderViewHost* host) = 0;
- // Invoked when the WebContents is notified that the RenderView has been
- // swapped in.
- virtual void RenderViewSwappedIn(RenderViewHost* host) = 0;
+ // Invoked when the WebContents is notified that the RenderView is ready.
+ virtual void RenderViewReady() = 0;
+
+ // Invoked when the WebContents is notified that the RenderViewHost has been
+ // changed.
+ virtual void RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) = 0;
// Invoked to enable/disable overscroll gesture navigation.
virtual void SetOverscrollControllerEnabled(bool enabled) = 0;
diff --git a/chromium/content/browser/web_contents/web_contents_view_android.cc b/chromium/content/browser/web_contents/web_contents_view_android.cc
index 28c90658587..8990bc7bf6c 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_android.cc
@@ -57,22 +57,6 @@ bool ShouldRequestUnbufferedDispatch() {
!content::GetContentClient()->UsingSynchronousCompositing();
return should_request_unbuffered_dispatch;
}
-
-RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid(
- WebContents* web_contents) {
- RenderWidgetHostView* rwhv = NULL;
- if (web_contents) {
- rwhv = web_contents->GetRenderWidgetHostView();
- if (web_contents->ShowingInterstitialPage()) {
- rwhv = web_contents->GetInterstitialPage()
- ->GetMainFrame()
- ->GetRenderViewHost()
- ->GetWidget()
- ->GetView();
- }
- }
- return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
-}
}
// static
@@ -131,19 +115,22 @@ void WebContentsViewAndroid::SetSelectPopup(
void WebContentsViewAndroid::SetOverscrollRefreshHandler(
std::unique_ptr<ui::OverscrollRefreshHandler> overscroll_refresh_handler) {
overscroll_refresh_handler_ = std::move(overscroll_refresh_handler);
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
- if (rwhv)
- rwhv->OnOverscrollRefreshHandlerAvailable();
+ auto* rwhv = web_contents_->GetRenderWidgetHostView();
+ if (rwhv) {
+ static_cast<RenderWidgetHostViewAndroid*>(rwhv)
+ ->OnOverscrollRefreshHandlerAvailable();
+ }
if (web_contents_->ShowingInterstitialPage()) {
- rwhv = static_cast<RenderWidgetHostViewAndroid*>(
- web_contents_->GetInterstitialPage()
- ->GetMainFrame()
- ->GetRenderViewHost()
- ->GetWidget()
- ->GetView());
- if (rwhv)
- rwhv->OnOverscrollRefreshHandlerAvailable();
+ rwhv = web_contents_->GetInterstitialPage()
+ ->GetMainFrame()
+ ->GetRenderViewHost()
+ ->GetWidget()
+ ->GetView();
+ if (rwhv) {
+ static_cast<RenderWidgetHostViewAndroid*>(rwhv)
+ ->OnOverscrollRefreshHandlerAvailable();
+ }
}
}
@@ -167,8 +154,16 @@ gfx::NativeView WebContentsViewAndroid::GetContentNativeView() const {
RenderWidgetHostViewAndroid*
WebContentsViewAndroid::GetRenderWidgetHostViewAndroid() {
- return static_cast<RenderWidgetHostViewAndroid*>(
- web_contents_->GetRenderWidgetHostView());
+ RenderWidgetHostView* rwhv = nullptr;
+ rwhv = web_contents_->GetRenderWidgetHostView();
+ if (web_contents_->ShowingInterstitialPage()) {
+ rwhv = web_contents_->GetInterstitialPage()
+ ->GetMainFrame()
+ ->GetRenderViewHost()
+ ->GetWidget()
+ ->GetView();
+ }
+ return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
}
gfx::NativeWindow WebContentsViewAndroid::GetTopLevelNativeWindow() const {
@@ -191,11 +186,12 @@ void WebContentsViewAndroid::SizeContents(const gfx::Size& size) {
}
void WebContentsViewAndroid::Focus() {
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
if (web_contents_->ShowingInterstitialPage()) {
web_contents_->GetInterstitialPage()->Focus();
- } else if (rwhv) {
- rwhv->Focus();
+ } else {
+ auto* rwhv = web_contents_->GetRenderWidgetHostView();
+ if (rwhv)
+ static_cast<RenderWidgetHostViewAndroid*>(rwhv)->Focus();
}
}
@@ -273,7 +269,42 @@ RenderWidgetHostViewBase* WebContentsViewAndroid::CreateViewForPopupWidget(
void WebContentsViewAndroid::RenderViewCreated(RenderViewHost* host) {
}
-void WebContentsViewAndroid::RenderViewSwappedIn(RenderViewHost* host) {
+void WebContentsViewAndroid::RenderViewReady() {
+ if (device_orientation_ == 0)
+ return;
+ auto* rwhva = GetRenderWidgetHostViewAndroid();
+ if (rwhva)
+ rwhva->UpdateScreenInfo(GetNativeView());
+
+ web_contents_->OnScreenOrientationChange();
+}
+
+void WebContentsViewAndroid::RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) {
+ if (old_host) {
+ auto* rwhv = old_host->GetWidget()->GetView();
+ if (rwhv && rwhv->GetNativeView()) {
+ static_cast<RenderWidgetHostViewAndroid*>(rwhv)->UpdateNativeViewTree(
+ nullptr);
+ }
+ }
+
+ auto* rwhv = new_host->GetWidget()->GetView();
+ if (rwhv && rwhv->GetNativeView()) {
+ static_cast<RenderWidgetHostViewAndroid*>(rwhv)->UpdateNativeViewTree(
+ GetNativeView());
+ SetFocus(view_.HasFocus());
+ }
+}
+
+void WebContentsViewAndroid::SetFocus(bool focused) {
+ auto* rwhva = GetRenderWidgetHostViewAndroid();
+ if (!rwhva)
+ return;
+ if (focused)
+ rwhva->GotFocus();
+ else
+ rwhva->LostFocus();
}
void WebContentsViewAndroid::SetOverscrollControllerEnabled(bool enabled) {
@@ -281,10 +312,11 @@ void WebContentsViewAndroid::SetOverscrollControllerEnabled(bool enabled) {
void WebContentsViewAndroid::ShowContextMenu(
RenderFrameHost* render_frame_host, const ContextMenuParams& params) {
- RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
+ auto* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
+ web_contents_->GetRenderWidgetHostView());
// See if context menu is handled by SelectionController as a selection menu.
// If not, use the delegate to show it.
- if (view && view->ShowSelectionMenu(params))
+ if (rwhv && rwhv->ShowSelectionMenu(params))
return;
if (delegate_)
@@ -550,10 +582,11 @@ bool WebContentsViewAndroid::ScrollTo(float x, float y) {
}
void WebContentsViewAndroid::OnSizeChanged() {
- auto* rwhv = ::content::GetRenderWidgetHostViewAndroid(web_contents_);
+ auto* rwhv = GetRenderWidgetHostViewAndroid();
if (rwhv) {
web_contents_->SendScreenRects();
- rwhv->SynchronizeVisualProperties();
+ rwhv->SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+ base::nullopt);
}
}
diff --git a/chromium/content/browser/web_contents/web_contents_view_android.h b/chromium/content/browser/web_contents/web_contents_view_android.h
index 3b6ab05eeac..088fedea3fa 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.h
+++ b/chromium/content/browser/web_contents/web_contents_view_android.h
@@ -80,7 +80,9 @@ class WebContentsViewAndroid : public WebContentsView,
RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(RenderViewHost* host) override;
- void RenderViewSwappedIn(RenderViewHost* host) override;
+ void RenderViewReady() override;
+ void RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) override;
void SetOverscrollControllerEnabled(bool enabled) override;
// Backend implementation of RenderViewHostDelegateView.
@@ -122,10 +124,10 @@ class WebContentsViewAndroid : public WebContentsView,
void OnSizeChanged() override;
void OnPhysicalBackingSizeChanged() override;
+ void SetFocus(bool focused);
void set_device_orientation(int orientation) {
device_orientation_ = orientation;
}
- int device_orientation() { return device_orientation_; }
private:
void OnDragEntered(const std::vector<DropData::Metadata>& metadata,
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 984fa41d064..713b17948ef 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -465,9 +465,9 @@ void WebContentsViewAura::InstallCreateHookForTests(
WebContentsViewAura::WebContentsViewAura(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate)
- : is_mus_browser_plugin_guest_(
- web_contents->GetBrowserPluginGuest() != nullptr &&
- base::FeatureList::IsEnabled(features::kMash)),
+ : is_mus_browser_plugin_guest_(web_contents->GetBrowserPluginGuest() !=
+ nullptr &&
+ !features::IsAshInBrowserProcess()),
web_contents_(web_contents),
delegate_(delegate),
current_drag_op_(blink::kWebDragOperationNone),
@@ -843,8 +843,10 @@ void WebContentsViewAura::SetPageTitle(const base::string16& title) {
void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
}
-void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) {
-}
+void WebContentsViewAura::RenderViewReady() {}
+
+void WebContentsViewAura::RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) {}
void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
RenderWidgetHostViewAura* view =
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 82807c7f77f..058f3e00d6f 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.h
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.h
@@ -119,7 +119,9 @@ class CONTENT_EXPORT WebContentsViewAura
RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(RenderViewHost* host) override;
- void RenderViewSwappedIn(RenderViewHost* host) override;
+ void RenderViewReady() override;
+ void RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) override;
void SetOverscrollControllerEnabled(bool enabled) override;
// Overridden from RenderViewHostDelegateView:
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 dbc35b6c764..60ec51cdf3a 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
@@ -448,7 +448,8 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
// Disabled because the test always fails the first time it runs on the Win Aura
// bots, and usually but not always passes second-try (See crbug.com/179532).
-#if defined(OS_WIN)
+// Flaky on CrOS as well: https://crbug.com/856079
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
#define MAYBE_QuickOverscrollDirectionChange \
DISABLED_QuickOverscrollDirectionChange
#else
diff --git a/chromium/content/browser/web_contents/web_contents_view_child_frame.cc b/chromium/content/browser/web_contents/web_contents_view_child_frame.cc
index e95c31d677f..688540cea25 100644
--- a/chromium/content/browser/web_contents/web_contents_view_child_frame.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_child_frame.cc
@@ -99,7 +99,11 @@ void WebContentsViewChildFrame::SetPageTitle(const base::string16& title) {
void WebContentsViewChildFrame::RenderViewCreated(RenderViewHost* host) {}
-void WebContentsViewChildFrame::RenderViewSwappedIn(RenderViewHost* host) {}
+void WebContentsViewChildFrame::RenderViewReady() {}
+
+void WebContentsViewChildFrame::RenderViewHostChanged(
+ RenderViewHost* old_host,
+ RenderViewHost* new_host) {}
void WebContentsViewChildFrame::SetOverscrollControllerEnabled(bool enabled) {
// This is managed by the outer view.
diff --git a/chromium/content/browser/web_contents/web_contents_view_child_frame.h b/chromium/content/browser/web_contents/web_contents_view_child_frame.h
index 17275be9302..e5485f5609c 100644
--- a/chromium/content/browser/web_contents/web_contents_view_child_frame.h
+++ b/chromium/content/browser/web_contents/web_contents_view_child_frame.h
@@ -45,7 +45,9 @@ class WebContentsViewChildFrame : public WebContentsView,
RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(RenderViewHost* host) override;
- void RenderViewSwappedIn(RenderViewHost* host) override;
+ void RenderViewReady() override;
+ void RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) override;
void SetOverscrollControllerEnabled(bool enabled) override;
#if defined(OS_MACOSX)
void SetAllowOtherViews(bool allow) override;
diff --git a/chromium/content/browser/web_contents/web_contents_view_guest.cc b/chromium/content/browser/web_contents/web_contents_view_guest.cc
index 699570cc139..44c68ed25b6 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.cc
@@ -72,14 +72,14 @@ void WebContentsViewGuest::OnGuestAttached(WebContentsView* parent_view) {
// view hierarchy. We add this view as embedder's child here.
// This would go in WebContentsViewGuest::CreateView, but that is too early to
// access embedder_web_contents(). Therefore, we do it here.
- if (!base::FeatureList::IsEnabled(features::kMash))
+ if (features::IsAshInBrowserProcess())
parent_view->GetNativeView()->AddChild(platform_view_->GetNativeView());
#endif // defined(USE_AURA)
}
void WebContentsViewGuest::OnGuestDetached(WebContentsView* old_parent_view) {
#if defined(USE_AURA)
- if (!base::FeatureList::IsEnabled(features::kMash)) {
+ if (features::IsAshInBrowserProcess()) {
old_parent_view->GetNativeView()->RemoveChild(
platform_view_->GetNativeView());
}
@@ -163,8 +163,13 @@ void WebContentsViewGuest::RenderViewCreated(RenderViewHost* host) {
platform_view_->RenderViewCreated(host);
}
-void WebContentsViewGuest::RenderViewSwappedIn(RenderViewHost* host) {
- platform_view_->RenderViewSwappedIn(host);
+void WebContentsViewGuest::RenderViewReady() {
+ platform_view_->RenderViewReady();
+}
+
+void WebContentsViewGuest::RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) {
+ platform_view_->RenderViewHostChanged(old_host, new_host);
}
void WebContentsViewGuest::SetOverscrollControllerEnabled(bool enabled) {
diff --git a/chromium/content/browser/web_contents/web_contents_view_guest.h b/chromium/content/browser/web_contents/web_contents_view_guest.h
index 4a06fe5f688..9e3511a9dab 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.h
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.h
@@ -63,7 +63,9 @@ class WebContentsViewGuest : public WebContentsView,
RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(RenderViewHost* host) override;
- void RenderViewSwappedIn(RenderViewHost* host) override;
+ void RenderViewReady() override;
+ void RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) override;
void SetOverscrollControllerEnabled(bool enabled) override;
#if defined(OS_MACOSX)
void SetAllowOtherViews(bool allow) 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 4640550b848..7f80c1b1d82 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.h
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.h
@@ -7,6 +7,7 @@
#import <Cocoa/Cocoa.h>
+#include <list>
#include <memory>
#include <string>
#include <vector>
@@ -18,7 +19,8 @@
#include "content/browser/web_contents/web_contents_view.h"
#include "content/common/content_export.h"
#include "content/common/drag_event_source_info.h"
-#include "ui/base/cocoa/base_view.h"
+#import "ui/base/cocoa/accessibility_hostable.h"
+#import "ui/base/cocoa/base_view.h"
#include "ui/gfx/geometry/size.h"
@class WebDragDest;
@@ -40,7 +42,7 @@ class Layer;
}
CONTENT_EXPORT
-@interface WebContentsViewCocoa : BaseView {
+@interface WebContentsViewCocoa : BaseView<AccessibilityHostable> {
@private
// Instances of this class are owned by both webContentsView_ and AppKit. It
// is possible for an instance to outlive its webContentsView_. The
@@ -48,6 +50,7 @@ CONTENT_EXPORT
content::WebContentsViewMac* webContentsView_;
base::scoped_nsobject<WebDragSource> dragSource_;
base::scoped_nsobject<WebDragDest> dragDest_;
+ base::scoped_nsobject<id> accessibilityParent_;
BOOL mouseDownCanMoveWindow_;
}
@@ -57,6 +60,7 @@ CONTENT_EXPORT
// NSDraggingSource. It is supposedly deprecated, but the non-deprecated API
// -[NSWindow dragImage:...] still relies on it.
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal;
+
@end
namespace content {
@@ -98,7 +102,9 @@ class WebContentsViewMac : public WebContentsView,
RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(RenderViewHost* host) override;
- void RenderViewSwappedIn(RenderViewHost* host) override;
+ void RenderViewReady() override;
+ void RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) override;
void SetOverscrollControllerEnabled(bool enabled) override;
bool IsEventTracking() const override;
void CloseTabAfterEventTracking() override;
@@ -162,6 +168,13 @@ class WebContentsViewMac : public WebContentsView,
// Whether to allow other views.
bool allow_other_views_;
+ // This contains all RenderWidgetHostViewMacs that have been added as child
+ // NSViews to this NSView. Note that this list may contain RWHVMacs besides
+ // just |web_contents_->GetRenderWidgetHostView()|. The only time that the
+ // RWHVMac's NSView is removed from the WCVMac's NSView is when it is
+ // destroyed.
+ std::list<base::WeakPtr<RenderWidgetHostViewBase>> child_views_;
+
ui::Layer* parent_ui_layer_ = nullptr;
std::unique_ptr<PopupMenuHelper> popup_menu_helper_;
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 00b2d2a729d..94848b56836 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -198,9 +198,6 @@ void WebContentsViewMac::Focus() {
gfx::NativeView native_view = GetNativeViewForFocus();
NSWindow* window = [native_view window];
[window makeFirstResponder:native_view];
- if (![window isVisible])
- return;
- [window makeKeyAndOrderFront:nil];
}
void WebContentsViewMac::SetInitialFocus() {
@@ -373,8 +370,10 @@ RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForWidget(
view->SetDelegate(rw_delegate.get());
}
view->SetAllowPauseForResizeOrRepaint(!allow_other_views_);
- if (parent_ui_layer_)
- view->SetParentUiLayer(parent_ui_layer_);
+
+ // Add the RenderWidgetHostView to the ui::Layer heirarchy.
+ child_views_.push_back(view->GetWeakPtr());
+ SetParentUiLayer(parent_ui_layer_);
// Fancy layout comes later; for now just make it our size and resize it
// with us. In case there are other siblings of the content area, we want
@@ -423,8 +422,10 @@ void WebContentsViewMac::RenderViewCreated(RenderViewHost* host) {
host->EnablePreferredSizeMode();
}
-void WebContentsViewMac::RenderViewSwappedIn(RenderViewHost* host) {
-}
+void WebContentsViewMac::RenderViewReady() {}
+
+void WebContentsViewMac::RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) {}
void WebContentsViewMac::SetOverscrollControllerEnabled(bool enabled) {
}
@@ -450,10 +451,13 @@ void WebContentsViewMac::CloseTab() {
void WebContentsViewMac::SetParentUiLayer(ui::Layer* parent_ui_layer) {
parent_ui_layer_ = parent_ui_layer;
- RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
- web_contents_->GetRenderWidgetHostView());
- if (view)
- view->SetParentUiLayer(parent_ui_layer);
+ // Remove any child NSViews that have been destroyed.
+ for (auto iter = child_views_.begin(); iter != child_views_.end();) {
+ if (*iter)
+ (*iter++)->SetParentUiLayer(parent_ui_layer);
+ else
+ iter = child_views_.erase(iter);
+ }
}
} // namespace content
@@ -739,4 +743,18 @@ void WebContentsViewMac::SetParentUiLayer(ui::Layer* parent_ui_layer) {
[self updateWebContentsVisibility];
}
+// AccessibilityHostable protocol implementation.
+- (void)setAccessibilityParentElement:(id)accessibilityParent {
+ accessibilityParent_.reset([accessibilityParent retain]);
+}
+
+// NSAccessibility informal protocol implementation.
+- (id)accessibilityAttributeValue:(NSString*)attribute {
+ if (accessibilityParent_ &&
+ [attribute isEqualToString:NSAccessibilityParentAttribute]) {
+ return accessibilityParent_;
+ }
+ return [super accessibilityAttributeValue:attribute];
+}
+
@end
diff --git a/chromium/content/browser/web_contents/web_contents_view_mac_unittest.mm b/chromium/content/browser/web_contents/web_contents_view_mac_unittest.mm
index d18ac92c06e..8ce3dad6c86 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac_unittest.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac_unittest.mm
@@ -9,6 +9,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
#include "testing/platform_test.h"
#include "ui/base/test/cocoa_helper.h"
#import "ui/base/test/cocoa_helper.h"
@@ -23,6 +24,7 @@ class WebContentsViewCocoaTest : public ui::CocoaTest {
} // namespace
TEST_F(WebContentsViewCocoaTest, NonWebDragSourceTest) {
+ // The designated initializer is private but init should be fine in this case.
base::scoped_nsobject<WebContentsViewCocoa> view(
[[WebContentsViewCocoa alloc] init]);
@@ -36,6 +38,28 @@ TEST_F(WebContentsViewCocoaTest, NonWebDragSourceTest) {
[view draggingSourceOperationMaskForLocal:NO]);
}
+TEST_F(WebContentsViewCocoaTest, AccessibilityParentTest) {
+ // The designated initializer is private but init should be fine in this case.
+ base::scoped_nsobject<WebContentsViewCocoa> view(
+ [[WebContentsViewCocoa alloc] init]);
+
+ // NSBox so it participates in the a11y hierarchy.
+ base::scoped_nsobject<NSView> parent_view([[NSBox alloc] init]);
+ base::scoped_nsobject<NSView> accessibility_parent([[NSView alloc] init]);
+
+ [parent_view addSubview:view];
+ EXPECT_NSEQ([view accessibilityAttributeValue:NSAccessibilityParentAttribute],
+ parent_view);
+
+ [view setAccessibilityParentElement:accessibility_parent];
+ EXPECT_NSEQ([view accessibilityAttributeValue:NSAccessibilityParentAttribute],
+ accessibility_parent);
+
+ [view setAccessibilityParentElement:nil];
+ EXPECT_NSEQ([view accessibilityAttributeValue:NSAccessibilityParentAttribute],
+ parent_view);
+}
+
namespace {
class WebContentsViewMacTest : public RenderViewHostTestHarness {
diff --git a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc
index 083d6c6fa95..90dd7610d3e 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc
@@ -72,14 +72,15 @@ SignedExchangeCertFetcher::CreateAndStart(
bool force_fetch,
SignedExchangeVersion version,
CertificateCallback callback,
- SignedExchangeDevToolsProxy* devtools_proxy) {
+ SignedExchangeDevToolsProxy* devtools_proxy,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeCertFetcher::CreateAndStart");
std::unique_ptr<SignedExchangeCertFetcher> cert_fetcher(
new SignedExchangeCertFetcher(
std::move(shared_url_loader_factory), std::move(throttles), cert_url,
std::move(request_initiator), force_fetch, version,
- std::move(callback), devtools_proxy));
+ std::move(callback), devtools_proxy, throttling_profile_id));
cert_fetcher->Start();
return cert_fetcher;
}
@@ -92,7 +93,8 @@ SignedExchangeCertFetcher::SignedExchangeCertFetcher(
bool force_fetch,
SignedExchangeVersion version,
CertificateCallback callback,
- SignedExchangeDevToolsProxy* devtools_proxy)
+ SignedExchangeDevToolsProxy* devtools_proxy,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id)
: shared_url_loader_factory_(std::move(shared_url_loader_factory)),
throttles_(std::move(throttles)),
resource_request_(std::make_unique<network::ResourceRequest>()),
@@ -117,6 +119,7 @@ SignedExchangeCertFetcher::SignedExchangeCertFetcher(
cert_request_id_ = base::UnguessableToken::Create();
resource_request_->enable_load_timing = true;
}
+ resource_request_->throttling_profile_id = throttling_profile_id;
}
SignedExchangeCertFetcher::~SignedExchangeCertFetcher() = default;
@@ -148,8 +151,8 @@ void SignedExchangeCertFetcher::Abort() {
}
void SignedExchangeCertFetcher::OnHandleReady(MojoResult result) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertFetcher::OnHandleReady");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeCertFetcher::OnHandleReady");
const void* buffer = nullptr;
uint32_t num_bytes = 0;
MojoResult rv =
@@ -157,8 +160,8 @@ void SignedExchangeCertFetcher::OnHandleReady(MojoResult result) {
if (rv == MOJO_RESULT_OK) {
if (body_string_.size() + num_bytes > g_max_cert_size_for_signed_exchange) {
body_->EndReadData(num_bytes);
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_, "SignedExchangeCertFetcher::OnHandleReady",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_,
"The response body size of certificate message exceeds the limit.");
Abort();
return;
@@ -170,13 +173,11 @@ void SignedExchangeCertFetcher::OnHandleReady(MojoResult result) {
} else {
DCHECK_EQ(MOJO_RESULT_SHOULD_WAIT, rv);
}
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertFetcher::OnHandleReady");
}
void SignedExchangeCertFetcher::OnDataComplete() {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertFetcher::OnDataComplete");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeCertFetcher::OnDataComplete");
DCHECK(callback_);
url_loader_ = nullptr;
body_.reset();
@@ -188,41 +189,53 @@ void SignedExchangeCertFetcher::OnDataComplete() {
devtools_proxy_);
body_string_.clear();
if (!cert_chain) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_, "SignedExchangeCertFetcher::OnDataComplete",
- "Failed to get certificate chain from message.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_, "Failed to get certificate chain from message.");
std::move(callback_).Run(nullptr);
return;
}
std::move(callback_).Run(std::move(cert_chain));
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertFetcher::OnDataComplete");
}
// network::mojom::URLLoaderClient
void SignedExchangeCertFetcher::OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
+ const network::ResourceResponseHead& head) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeCertFetcher::OnReceiveResponse");
if (devtools_proxy_) {
DCHECK(cert_request_id_);
devtools_proxy_->CertificateResponseReceived(*cert_request_id_,
resource_request_->url, head);
}
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertFetcher::OnReceiveResponse");
- if (head.headers->response_code() != net::HTTP_OK) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_, "SignedExchangeCertFetcher::OnReceiveResponse",
- base::StringPrintf("Invalid reponse code: %d",
- head.headers->response_code()));
+
+ // |headers| is null when loading data URL.
+ if (head.headers && head.headers->response_code() != net::HTTP_OK) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_, base::StringPrintf("Invalid reponse code: %d",
+ head.headers->response_code()));
Abort();
return;
}
+
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cert-chain-format
+ // "The resource at a signature's cert-url MUST have the
+ // application/cert-chain+cbor content type" [spec text]
+ if (head.mime_type != "application/cert-chain+cbor") {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_,
+ base::StringPrintf(
+ "Content type of cert-url must be application/cert-chain+cbor. "
+ "Actual content type: %s",
+ head.mime_type.c_str()));
+ Abort();
+ return;
+ }
+
if (head.content_length > 0) {
if (base::checked_cast<size_t>(head.content_length) >
g_max_cert_size_for_signed_exchange) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_, "SignedExchangeCertFetcher::OnReceiveResponse",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_,
base::StringPrintf("Invalid content length: %" PRIu64,
head.content_length));
Abort();
@@ -230,8 +243,6 @@ void SignedExchangeCertFetcher::OnReceiveResponse(
}
body_string_.reserve(head.content_length);
}
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertFetcher::OnReceiveResponse");
}
void SignedExchangeCertFetcher::OnReceiveRedirect(
@@ -243,12 +254,6 @@ void SignedExchangeCertFetcher::OnReceiveRedirect(
Abort();
}
-void SignedExchangeCertFetcher::OnDataDownloaded(int64_t data_length,
- int64_t encoded_length) {
- // Cert fetching is not a downloading job.
- NOTREACHED();
-}
-
void SignedExchangeCertFetcher::OnUploadProgress(
int64_t current_position,
int64_t total_size,
diff --git a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h
index 23de0610fb8..679ed5f7eba 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h
@@ -54,7 +54,8 @@ class CONTENT_EXPORT SignedExchangeCertFetcher
bool force_fetch,
SignedExchangeVersion version,
CertificateCallback callback,
- SignedExchangeDevToolsProxy* devtools_proxy);
+ SignedExchangeDevToolsProxy* devtools_proxy,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id);
~SignedExchangeCertFetcher() override;
@@ -76,19 +77,17 @@ class CONTENT_EXPORT SignedExchangeCertFetcher
bool force_fetch,
SignedExchangeVersion version,
CertificateCallback callback,
- SignedExchangeDevToolsProxy* devtools_proxy);
+ SignedExchangeDevToolsProxy* devtools_proxy,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id);
void Start();
void Abort();
void OnHandleReady(MojoResult result);
void OnDataComplete();
// network::mojom::URLLoaderClient
- void OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override;
+ void OnReceiveResponse(const network::ResourceResponseHead& head) override;
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) override;
- void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override;
diff --git a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc
index 20234806225..7cff4e9bf38 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc
@@ -4,6 +4,7 @@
#include "content/browser/web_package/signed_exchange_cert_fetcher_factory.h"
+#include "base/unguessable_token.h"
#include "content/public/common/url_loader_throttle.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -17,10 +18,12 @@ class SignedExchangeCertFetcherFactoryImpl
SignedExchangeCertFetcherFactoryImpl(
url::Origin request_initiator,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- URLLoaderThrottlesGetter url_loader_throttles_getter)
+ URLLoaderThrottlesGetter url_loader_throttles_getter,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id)
: request_initiator_(std::move(request_initiator)),
url_loader_factory_(std::move(url_loader_factory)),
- url_loader_throttles_getter_(std::move(url_loader_throttles_getter)) {}
+ url_loader_throttles_getter_(std::move(url_loader_throttles_getter)),
+ throttling_profile_id_(throttling_profile_id) {}
std::unique_ptr<SignedExchangeCertFetcher> CreateFetcherAndStart(
const GURL& cert_url,
@@ -33,6 +36,7 @@ class SignedExchangeCertFetcherFactoryImpl
url::Origin request_initiator_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
URLLoaderThrottlesGetter url_loader_throttles_getter_;
+ const base::Optional<base::UnguessableToken> throttling_profile_id_;
};
std::unique_ptr<SignedExchangeCertFetcher>
@@ -49,7 +53,7 @@ SignedExchangeCertFetcherFactoryImpl::CreateFetcherAndStart(
return SignedExchangeCertFetcher::CreateAndStart(
std::move(url_loader_factory_), std::move(throttles), cert_url,
std::move(request_initiator_), force_fetch, version, std::move(callback),
- devtools_proxy);
+ devtools_proxy, throttling_profile_id_);
}
// static
@@ -57,10 +61,11 @@ std::unique_ptr<SignedExchangeCertFetcherFactory>
SignedExchangeCertFetcherFactory::Create(
url::Origin request_initiator,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- URLLoaderThrottlesGetter url_loader_throttles_getter) {
+ URLLoaderThrottlesGetter url_loader_throttles_getter,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id) {
return std::make_unique<SignedExchangeCertFetcherFactoryImpl>(
std::move(request_initiator), std::move(url_loader_factory),
- std::move(url_loader_throttles_getter));
+ std::move(url_loader_throttles_getter), throttling_profile_id);
}
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.h b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.h
index dc01c1c3bd2..941334570c5 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.h
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.h
@@ -9,6 +9,8 @@
#include <vector>
#include "base/callback_forward.h"
+#include "base/optional.h"
+#include "base/unguessable_token.h"
#include "content/browser/web_package/signed_exchange_cert_fetcher.h"
#include "content/common/content_export.h"
#include "url/origin.h"
@@ -41,7 +43,8 @@ class CONTENT_EXPORT SignedExchangeCertFetcherFactory {
static std::unique_ptr<SignedExchangeCertFetcherFactory> Create(
url::Origin request_initiator,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- URLLoaderThrottlesGetter url_loader_throttles_getter);
+ URLLoaderThrottlesGetter url_loader_throttles_getter,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id);
};
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
index 19e3ed513c7..9e5ea4406c0 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
@@ -8,6 +8,8 @@
#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "base/test/scoped_task_environment.h"
+#include "components/cbor/cbor_values.h"
+#include "components/cbor/cbor_writer.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/url_loader_throttle.h"
@@ -37,9 +39,11 @@ class DeferringURLLoaderThrottle final : public URLLoaderThrottle {
*defer = true;
}
- void WillRedirectRequest(const net::RedirectInfo& redirect_info,
- const network::ResourceResponseHead& response_head,
- bool* defer) override {
+ void WillRedirectRequest(
+ const net::RedirectInfo& redirect_info,
+ const network::ResourceResponseHead& response_head,
+ bool* defer,
+ std::vector<std::string>* to_be_removed_headers) override {
will_redirect_request_called_ = true;
*defer = true;
}
@@ -75,8 +79,9 @@ class MockURLLoader final : public network::mojom::URLLoader {
: binding_(this, std::move(url_loader_request)) {}
~MockURLLoader() override = default;
- MOCK_METHOD1(FollowRedirect,
- void(const base::Optional<net::HttpRequestHeaders>&));
+ MOCK_METHOD2(FollowRedirect,
+ void(const base::Optional<std::vector<std::string>>&,
+ const base::Optional<net::HttpRequestHeaders>&));
MOCK_METHOD0(ProceedWithResponse, void());
MOCK_METHOD2(SetPriority,
void(net::RequestPriority priority,
@@ -142,7 +147,7 @@ class SignedExchangeCertFetcherTest : public testing::Test {
SignedExchangeCertFetcherTest()
: url_(GURL("https://www.example.com/cert")),
request_initiator_(
- url::Origin::Create(GURL("https://htxg.example.com/test.htxg"))),
+ url::Origin::Create(GURL("https://sxg.example.com/test.sxg"))),
resource_dispatcher_host_(CreateDownloadHandlerIntercept(),
base::ThreadTaskRunnerHandle::Get(),
true /* enable_resource_scheduler */) {}
@@ -154,30 +159,24 @@ class SignedExchangeCertFetcherTest : public testing::Test {
}
static std::string CreateCertMessage(const base::StringPiece& cert_data) {
- std::string message;
- uint32_t cert_size = cert_data.length();
- uint32_t cert_list_size = cert_size + 3 /* size of "cert data size" */ +
- 2 /* size of "extensions size" */;
- uint32_t message_size = cert_list_size +
- 1 /* size of "request context size" */ +
- 3 /* size of "certificate list size" */;
- // request context size
- message += static_cast<char>(0x00);
- // certificate list size
- message += static_cast<char>(cert_list_size >> 16);
- message += static_cast<char>((cert_list_size & 0xFF00) >> 8);
- message += static_cast<char>(cert_list_size & 0xFF);
- // certificate list size
- message += static_cast<char>(cert_size >> 16);
- message += static_cast<char>((cert_size & 0xFF00) >> 8);
- message += static_cast<char>(cert_size & 0xFF);
- // cert data
- message += std::string(cert_data);
- // extensions size
- message += static_cast<char>(0x00);
- message += static_cast<char>(0x00);
- CHECK_EQ(message_size, message.size());
- return message;
+ cbor::CBORValue::MapValue cbor_map;
+ cbor_map[cbor::CBORValue("sct")] =
+ cbor::CBORValue("SCT", cbor::CBORValue::Type::BYTE_STRING);
+ cbor_map[cbor::CBORValue("cert")] =
+ cbor::CBORValue(cert_data, cbor::CBORValue::Type::BYTE_STRING);
+ cbor_map[cbor::CBORValue("ocsp")] =
+ cbor::CBORValue("OCSP", cbor::CBORValue::Type::BYTE_STRING);
+
+ cbor::CBORValue::ArrayValue cbor_array;
+ cbor_array.push_back(cbor::CBORValue(u8"\U0001F4DC\u26D3"));
+ cbor_array.push_back(cbor::CBORValue(std::move(cbor_map)));
+
+ base::Optional<std::vector<uint8_t>> serialized =
+ cbor::CBORWriter::Write(cbor::CBORValue(std::move(cbor_array)));
+ if (!serialized)
+ return std::string();
+ return std::string(reinterpret_cast<char*>(serialized->data()),
+ serialized->size());
}
static base::StringPiece CreateCertMessageFromCert(
@@ -202,6 +201,7 @@ class SignedExchangeCertFetcherTest : public testing::Test {
void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
std::unique_ptr<SignedExchangeCertFetcher> CreateFetcherAndStart(
+ const GURL& url,
bool force_fetch) {
SignedExchangeCertFetcher::CertificateCallback callback = base::BindOnce(
&ForwardCertificateCallback, base::Unretained(&callback_called_),
@@ -210,18 +210,20 @@ class SignedExchangeCertFetcherTest : public testing::Test {
return SignedExchangeCertFetcher::CreateAndStart(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&mock_loader_factory_),
- std::move(throttles_), url_, request_initiator_, force_fetch,
- SignedExchangeVersion::kB0, std::move(callback),
- nullptr /* devtools_proxy */);
+ std::move(throttles_), url, request_initiator_, force_fetch,
+ SignedExchangeVersion::kB1, std::move(callback),
+ nullptr /* devtools_proxy */,
+ base::nullopt /* throttling_profile_id */);
}
void CallOnReceiveResponse() {
network::ResourceResponseHead resource_response;
resource_response.headers =
base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
-
- mock_loader_factory_.client_ptr()->OnReceiveResponse(
- resource_response, nullptr /* downloaded_file */);
+ resource_response.headers->AddHeader(
+ "Content-Type: application/cert-chain+cbor");
+ resource_response.mime_type = "application/cert-chain+cbor";
+ mock_loader_factory_.client_ptr()->OnReceiveResponse(resource_response);
}
DeferringURLLoaderThrottle* InitializeDeferringURLLoaderThrottle() {
@@ -252,7 +254,7 @@ class SignedExchangeCertFetcherTest : public testing::Test {
TEST_F(SignedExchangeCertFetcherTest, Simple) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
ASSERT_TRUE(mock_loader_factory_.client_ptr());
ASSERT_TRUE(mock_loader_factory_.url_request());
@@ -279,7 +281,7 @@ TEST_F(SignedExchangeCertFetcherTest, Simple) {
TEST_F(SignedExchangeCertFetcherTest, MultipleChunked) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
const std::string message =
@@ -305,7 +307,7 @@ TEST_F(SignedExchangeCertFetcherTest, MultipleChunked) {
TEST_F(SignedExchangeCertFetcherTest, ForceFetchAndFail) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(true /* force_fetch */);
+ CreateFetcherAndStart(url_, true /* force_fetch */);
CallOnReceiveResponse();
ASSERT_TRUE(mock_loader_factory_.url_request());
@@ -333,7 +335,7 @@ TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_Exceeds) {
SignedExchangeCertFetcher::SetMaxCertSizeForTest(message.size() - 1);
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
mojo::DataPipe data_pipe(message.size());
CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
@@ -356,7 +358,7 @@ TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_SameSize) {
SignedExchangeCertFetcher::SetMaxCertSizeForTest(message.size());
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
mojo::DataPipe data_pipe(message.size());
CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
@@ -379,7 +381,7 @@ TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_MultipleChunked) {
SignedExchangeCertFetcher::SetMaxCertSizeForTest(message.size() - 1);
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
mojo::DataPipe data_pipe(message.size() / 2 + 1);
ASSERT_TRUE(mojo::BlockingCopyFromString(
@@ -406,13 +408,12 @@ TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_ContentLengthCheck) {
SignedExchangeCertFetcher::SetMaxCertSizeForTest(message.size() - 1);
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
network::ResourceResponseHead resource_response;
resource_response.headers =
base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
resource_response.content_length = message.size();
- mock_loader_factory_.client_ptr()->OnReceiveResponse(
- resource_response, nullptr /* downloaded_file */);
+ mock_loader_factory_.client_ptr()->OnReceiveResponse(resource_response);
mojo::DataPipe data_pipe(message.size());
CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
data_pipe.producer_handle.reset();
@@ -428,7 +429,7 @@ TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_ContentLengthCheck) {
TEST_F(SignedExchangeCertFetcherTest, Abort_Redirect) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
network::ResourceResponseHead response_head;
net::RedirectInfo redirect_info;
mock_loader_factory_.client_ptr()->OnReceiveRedirect(redirect_info,
@@ -441,12 +442,27 @@ TEST_F(SignedExchangeCertFetcherTest, Abort_Redirect) {
TEST_F(SignedExchangeCertFetcherTest, Abort_404) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
network::ResourceResponseHead resource_response;
resource_response.headers =
base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 404 Not Found");
- mock_loader_factory_.client_ptr()->OnReceiveResponse(
- resource_response, nullptr /* downloaded_file */);
+ mock_loader_factory_.client_ptr()->OnReceiveResponse(resource_response);
+ RunUntilIdle();
+
+ EXPECT_TRUE(callback_called_);
+ EXPECT_FALSE(cert_result_);
+}
+
+TEST_F(SignedExchangeCertFetcherTest, WrongMimeType) {
+ std::unique_ptr<SignedExchangeCertFetcher> fetcher =
+ CreateFetcherAndStart(url_, false /* force_fetch */);
+ network::ResourceResponseHead resource_response;
+ resource_response.headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
+ resource_response.headers->AddHeader(
+ "Content-Type: application/octet-stream");
+ resource_response.mime_type = "application/octet-stream";
+ mock_loader_factory_.client_ptr()->OnReceiveResponse(resource_response);
RunUntilIdle();
EXPECT_TRUE(callback_called_);
@@ -455,7 +471,7 @@ TEST_F(SignedExchangeCertFetcherTest, Abort_404) {
TEST_F(SignedExchangeCertFetcherTest, Invalid_CertData) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
const std::string message = CreateCertMessage("Invalid Cert Data");
mojo::DataPipe data_pipe(message.size());
@@ -473,7 +489,7 @@ TEST_F(SignedExchangeCertFetcherTest, Invalid_CertData) {
TEST_F(SignedExchangeCertFetcherTest, Invalid_CertMessage) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
const std::string message = "Invalid cert message";
@@ -495,7 +511,7 @@ TEST_F(SignedExchangeCertFetcherTest, Invalid_CertMessage) {
TEST_F(SignedExchangeCertFetcherTest, Throttle_Simple) {
DeferringURLLoaderThrottle* throttle = InitializeDeferringURLLoaderThrottle();
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
RunUntilIdle();
EXPECT_TRUE(throttle->will_start_request_called());
@@ -532,7 +548,7 @@ TEST_F(SignedExchangeCertFetcherTest, Throttle_Simple) {
TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnRequest) {
DeferringURLLoaderThrottle* throttle = InitializeDeferringURLLoaderThrottle();
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
RunUntilIdle();
throttle->delegate()->CancelWithError(net::ERR_INVALID_SIGNED_EXCHANGE);
@@ -546,7 +562,7 @@ TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnRequest) {
TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnRedirect) {
DeferringURLLoaderThrottle* throttle = InitializeDeferringURLLoaderThrottle();
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
RunUntilIdle();
throttle->delegate()->Resume();
@@ -572,7 +588,7 @@ TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnRedirect) {
TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnResponse) {
DeferringURLLoaderThrottle* throttle = InitializeDeferringURLLoaderThrottle();
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
RunUntilIdle();
throttle->delegate()->Resume();
@@ -603,7 +619,7 @@ TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnResponse) {
TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_BeforeReceiveResponse) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
RunUntilIdle();
fetcher.reset();
RunUntilIdle();
@@ -614,7 +630,7 @@ TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_BeforeReceiveResponse) {
TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_BeforeResponseBody) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
RunUntilIdle();
fetcher.reset();
@@ -626,7 +642,7 @@ TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_BeforeResponseBody) {
TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_WhileReceivingBody) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
const std::string message =
@@ -649,7 +665,7 @@ TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_WhileReceivingBody) {
TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_AfterReceivingBody) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
const std::string message =
@@ -671,7 +687,7 @@ TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_AfterReceivingBody) {
TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_BeforeReceiveResponse) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
RunUntilIdle();
CloseClientPipe();
RunUntilIdle();
@@ -682,7 +698,7 @@ TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_BeforeReceiveResponse) {
TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_BeforeResponseBody) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
RunUntilIdle();
CloseClientPipe();
@@ -694,7 +710,7 @@ TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_BeforeResponseBody) {
TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_WhileReceivingBody) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
const std::string message =
@@ -715,7 +731,7 @@ TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_WhileReceivingBody) {
TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_AfterReceivingBody) {
std::unique_ptr<SignedExchangeCertFetcher> fetcher =
- CreateFetcherAndStart(false /* force_fetch */);
+ CreateFetcherAndStart(url_, false /* force_fetch */);
CallOnReceiveResponse();
scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
const std::string message =
@@ -736,4 +752,39 @@ TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_AfterReceivingBody) {
cert_result_->cert()->CalculateChainFingerprint256());
}
+TEST_F(SignedExchangeCertFetcherTest, DataURL) {
+ const GURL data_url = GURL("data:application/cert-chain+cbor,foobar");
+ std::unique_ptr<SignedExchangeCertFetcher> fetcher =
+ CreateFetcherAndStart(data_url, false /* force_fetch */);
+ EXPECT_EQ(data_url, mock_loader_factory_.url_request()->url);
+
+ network::ResourceResponseHead resource_response;
+ resource_response.mime_type = "application/cert-chain+cbor";
+ mock_loader_factory_.client_ptr()->OnReceiveResponse(resource_response);
+
+ mock_loader_factory_.client_ptr()->OnStartLoadingResponseBody(
+ CreateTestDataFilledDataPipe());
+ mock_loader_factory_.client_ptr()->OnComplete(
+ network::URLLoaderCompletionStatus(net::OK));
+ RunUntilIdle();
+ EXPECT_TRUE(callback_called_);
+ ASSERT_TRUE(cert_result_);
+ EXPECT_EQ(GetTestDataCertFingerprint256(),
+ cert_result_->cert()->CalculateChainFingerprint256());
+}
+
+TEST_F(SignedExchangeCertFetcherTest, DataURLWithWrongMimeType) {
+ const GURL data_url = GURL("data:application/octet-stream,foobar");
+ std::unique_ptr<SignedExchangeCertFetcher> fetcher =
+ CreateFetcherAndStart(data_url, false /* force_fetch */);
+ EXPECT_EQ(data_url, mock_loader_factory_.url_request()->url);
+
+ network::ResourceResponseHead resource_response;
+ resource_response.mime_type = "application/octet-stream";
+ mock_loader_factory_.client_ptr()->OnReceiveResponse(resource_response);
+ RunUntilIdle();
+
+ EXPECT_TRUE(callback_called_);
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc b/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
index d94125eae13..1fd297d9512 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
@@ -4,7 +4,6 @@
#include "content/browser/web_package/signed_exchange_certificate_chain.h"
-#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
@@ -12,87 +11,32 @@
#include "components/cbor/cbor_reader.h"
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_utils.h"
-#include "content/public/common/content_switches.h"
#include "net/cert/x509_certificate.h"
namespace content {
namespace {
-bool ConsumeByte(base::span<const uint8_t>* data, uint8_t* out) {
- if (data->empty())
- return false;
- *out = (*data)[0];
- *data = data->subspan(1);
- return true;
-}
-
-bool Consume2Bytes(base::span<const uint8_t>* data, uint16_t* out) {
- if (data->size() < 2)
- return false;
- *out = ((*data)[0] << 8) | (*data)[1];
- *data = data->subspan(2);
- return true;
-}
-
-bool Consume3Bytes(base::span<const uint8_t>* data, uint32_t* out) {
- if (data->size() < 3)
- return false;
- *out = ((*data)[0] << 16) | ((*data)[1] << 8) | (*data)[2];
- *data = data->subspan(3);
- return true;
-}
-
-std::unique_ptr<SignedExchangeCertificateChain> ParseB0(
- base::span<const uint8_t> message,
- SignedExchangeDevToolsProxy* devtools_proxy) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertificateChain::ParseB0");
- base::Optional<std::vector<base::StringPiece>> der_certs =
- SignedExchangeCertificateChain::GetCertChainFromMessage(message);
- if (!der_certs) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB0",
- "Failed to parse the response as a TLS 1.3 Certificate message.");
- return nullptr;
- }
-
- scoped_refptr<net::X509Certificate> cert =
- net::X509Certificate::CreateFromDERCertChain(*der_certs);
- if (!cert) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB0",
- "X509Certificate::CreateFromDERCertChain failed.");
- return nullptr;
- }
-
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertificateChain::ParseB1");
- // The V0 certificate format doesn't support OCSP nor SCT.
- return base::WrapUnique(
- new SignedExchangeCertificateChain(cert, "" /* ocsp */, "" /* sct */));
-}
-
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cert-chain-format
std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
base::span<const uint8_t> message,
SignedExchangeDevToolsProxy* devtools_proxy) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertificateChain::ParseB1");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeCertificateChain::ParseB1");
cbor::CBORReader::DecoderError error;
base::Optional<cbor::CBORValue> value =
cbor::CBORReader::Read(message, &error);
if (!value.has_value()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf("Failed to decode CBORValue. CBOR error: %s",
cbor::CBORReader::ErrorCodeToString(error)));
return nullptr;
}
if (!value->is_array()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Expected top-level CBORValue to be an array. Actual type: %d",
static_cast<int>(value->type())));
@@ -102,8 +46,8 @@ std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
const cbor::CBORValue::ArrayValue& top_level_array = value->GetArray();
// Expect at least 2 elements (magic string and main certificate).
if (top_level_array.size() < 2) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Expected top-level array to have at least 2 elements."
"Actual element count: %" PRIuS,
@@ -112,8 +56,8 @@ std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
}
if (!top_level_array[0].is_string() ||
top_level_array[0].GetString() != kCertChainCborMagic) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
"First element of cert chain CBOR does not match the magic string.");
return nullptr;
}
@@ -125,8 +69,8 @@ std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
for (size_t i = 1; i < top_level_array.size(); i++) {
if (!top_level_array[i].is_map()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Expected certificate map, got non-map type at index %zu."
" Actual type: %d",
@@ -140,8 +84,8 @@ std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
// properties of this certificate. [spec text]
auto cert_iter = cert_map.find(cbor::CBORValue(kCertKey));
if (cert_iter == cert_map.end() || !cert_iter->second.is_bytestring()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"cert is not found or not a bytestring, at index %zu.", i));
return nullptr;
@@ -154,23 +98,22 @@ std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
// DER-encoded OCSP response for that certificate (using the ASN.1 type
// OCSPResponse defined in [RFC2560]). ... [spec text]
if (ocsp_iter == cert_map.end() || !ocsp_iter->second.is_bytestring()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
"ocsp is not a bytestring, or not found in the first cert map.");
return nullptr;
}
ocsp = ocsp_iter->second.GetBytestringAsString().as_string();
if (ocsp.empty()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
- "ocsp must not be empty.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "ocsp must not be empty.");
return nullptr;
}
} else if (ocsp_iter != cert_map.end()) {
// Step 2. ... Subsequent certificates MUST NOT have an ocsp value. [spec
// text]
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"ocsp value found in a subsequent cert map, at index %zu.", i));
return nullptr;
@@ -187,16 +130,14 @@ std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
auto sct_iter = cert_map.find(cbor::CBORValue(kSctKey));
if (sct_iter != cert_map.end()) {
if (!sct_iter->second.is_bytestring()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
- "sct is not a bytestring.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "sct is not a bytestring.");
return nullptr;
}
sct = sct_iter->second.GetBytestringAsString().as_string();
if (sct.empty()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
- "sct must not be empty.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "sct must not be empty.");
return nullptr;
}
}
@@ -205,14 +146,11 @@ std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
scoped_refptr<net::X509Certificate> cert =
net::X509Certificate::CreateFromDERCertChain(der_certs);
if (!cert) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
- "X509Certificate::CreateFromDERCertChain failed.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "X509Certificate::CreateFromDERCertChain failed.");
return nullptr;
}
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertificateChain::ParseB1");
return base::WrapUnique(new SignedExchangeCertificateChain(cert, ocsp, sct));
}
@@ -224,71 +162,8 @@ SignedExchangeCertificateChain::Parse(
SignedExchangeVersion version,
base::span<const uint8_t> cert_response_body,
SignedExchangeDevToolsProxy* devtools_proxy) {
- switch (version) {
- case SignedExchangeVersion::kB0:
- return ParseB0(cert_response_body, devtools_proxy);
- case SignedExchangeVersion::kB1:
- return ParseB1(cert_response_body, devtools_proxy);
- }
- NOTREACHED();
- return nullptr;
-}
-
-// static
-base::Optional<std::vector<base::StringPiece>>
-SignedExchangeCertificateChain::GetCertChainFromMessage(
- base::span<const uint8_t> message) {
- uint8_t cert_request_context_size = 0;
- if (!ConsumeByte(&message, &cert_request_context_size)) {
- DVLOG(1) << "Can't read certificate request request context size.";
- return base::nullopt;
- }
- if (cert_request_context_size != 0) {
- DVLOG(1) << "Invalid certificate request context size: "
- << static_cast<int>(cert_request_context_size);
- return base::nullopt;
- }
- uint32_t cert_list_size = 0;
- if (!Consume3Bytes(&message, &cert_list_size)) {
- DVLOG(1) << "Can't read certificate list size.";
- return base::nullopt;
- }
-
- if (cert_list_size != message.size()) {
- DVLOG(1) << "Certificate list size error: cert_list_size=" << cert_list_size
- << " remaining=" << message.size();
- return base::nullopt;
- }
-
- std::vector<base::StringPiece> certs;
- while (!message.empty()) {
- uint32_t cert_data_size = 0;
- if (!Consume3Bytes(&message, &cert_data_size)) {
- DVLOG(1) << "Can't read certificate data size.";
- return base::nullopt;
- }
- if (message.size() < cert_data_size) {
- DVLOG(1) << "Certificate data size error: cert_data_size="
- << cert_data_size << " remaining=" << message.size();
- return base::nullopt;
- }
- certs.emplace_back(base::StringPiece(
- reinterpret_cast<const char*>(message.data()), cert_data_size));
- message = message.subspan(cert_data_size);
-
- uint16_t extensions_size = 0;
- if (!Consume2Bytes(&message, &extensions_size)) {
- DVLOG(1) << "Can't read extensions size.";
- return base::nullopt;
- }
- if (message.size() < extensions_size) {
- DVLOG(1) << "Extensions size error: extensions_size=" << extensions_size
- << " remaining=" << message.size();
- return base::nullopt;
- }
- message = message.subspan(extensions_size);
- }
- return certs;
+ DCHECK_EQ(version, SignedExchangeVersion::kB1);
+ return ParseB1(cert_response_body, devtools_proxy);
}
SignedExchangeCertificateChain::SignedExchangeCertificateChain(
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain.h b/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
index 7b6ece476c3..b20f7349a38 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
@@ -37,12 +37,6 @@ class CONTENT_EXPORT SignedExchangeCertificateChain {
SignedExchangeCertificateChain(scoped_refptr<net::X509Certificate> cert,
const std::string& ocsp,
const std::string& sct);
-
- // Parses a TLS 1.3 Certificate message containing X.509v3 certificates and
- // returns a vector of cert_data. Returns nullopt when failed to parse.
- static base::Optional<std::vector<base::StringPiece>> GetCertChainFromMessage(
- base::span<const uint8_t> message);
-
~SignedExchangeCertificateChain();
const scoped_refptr<net::X509Certificate>& cert() const { return cert_; }
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc b/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc
index 56d34a6ad96..8d718db5f0a 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc
@@ -9,8 +9,6 @@
namespace content {
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- SignedExchangeCertificateChain::Parse(SignedExchangeVersion::kB0,
- base::make_span(data, size), nullptr);
SignedExchangeCertificateChain::Parse(SignedExchangeVersion::kB1,
base::make_span(data, size), nullptr);
return 0;
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc b/chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc
index 932f1cbf474..6389105c3a0 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc
@@ -21,261 +21,12 @@ namespace content {
namespace {
-base::Optional<std::vector<base::StringPiece>> GetCertChain(
- const uint8_t* input,
- size_t input_size) {
- return SignedExchangeCertificateChain::GetCertChainFromMessage(
- base::make_span(input, input_size));
-}
-
cbor::CBORValue CBORByteString(base::StringPiece str) {
return cbor::CBORValue(str, cbor::CBORValue::Type::BYTE_STRING);
}
} // namespace
-TEST(SignedExchangeCertificateParseB0Test, OneCert) {
- const uint8_t input[] = {
- // clang-format off
- 0x00, // request context size
- 0x00, 0x00, 0x07, // certificate list size
-
- 0x00, 0x00, 0x02, // cert data size
- 0x11, 0x22, // cert data
- 0x00, 0x00, // extensions size
- // clang-format on
- };
- base::Optional<std::vector<base::StringPiece>> certs =
- GetCertChain(input, arraysize(input));
- ASSERT_TRUE(certs);
- ASSERT_EQ(1u, certs->size());
- const uint8_t kExpected[] = {
- // clang-format off
- 0x11, 0x22, // cert data
- // clang-format on
- };
- EXPECT_THAT((*certs)[0],
- testing::ElementsAreArray(kExpected, arraysize(kExpected)));
-}
-
-TEST(SignedExchangeCertificateParseB0Test, OneCertWithExtension) {
- const uint8_t input[] = {
- // clang-format off
- 0x00, // request context size
- 0x00, 0x00, 0x0A, // certificate list size
-
- 0x00, 0x00, 0x02, // cert data size
- 0x11, 0x22, // cert data
- 0x00, 0x03, // extensions size
- 0xE1, 0xE2, 0xE3, // extensions data
- // clang-format on
- };
- base::Optional<std::vector<base::StringPiece>> certs =
- GetCertChain(input, arraysize(input));
- ASSERT_TRUE(certs);
- ASSERT_EQ(1u, certs->size());
- const uint8_t kExpected[] = {
- // clang-format off
- 0x11, 0x22, // cert data
- // clang-format on
- };
- EXPECT_THAT((*certs)[0],
- testing::ElementsAreArray(kExpected, arraysize(kExpected)));
-}
-
-TEST(SignedExchangeCertificateParseB0Test, TwoCerts) {
- const uint8_t input[] = {
- // clang-format off
- 0x00, // request context size
- 0x00, 0x01, 0x13, // certificate list size
-
- 0x00, 0x01, 0x04, // cert data size
-
- // cert data
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
-
- 0x00, 0x00, // extensions size
-
- 0x00, 0x00, 0x05, // cert data size
- 0x33, 0x44, 0x55, 0x66, 0x77, // cert data
- 0x00, 0x00, // extensions size
-
- // clang-format on
- };
-
- const uint8_t kExpected1[] = {
- // clang-format off
- // cert data
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
- // clang-format on
- };
- const uint8_t kExpected2[] = {
- // clang-format off
- 0x33, 0x44, 0x55, 0x66, 0x77, // cert data
- // clang-format on
- };
-
- base::Optional<std::vector<base::StringPiece>> certs =
- GetCertChain(input, sizeof(input));
- ASSERT_TRUE(certs);
- ASSERT_EQ(2u, certs->size());
- EXPECT_THAT((*certs)[0],
- testing::ElementsAreArray(kExpected1, arraysize(kExpected1)));
- EXPECT_THAT((*certs)[1],
- testing::ElementsAreArray(kExpected2, arraysize(kExpected2)));
-}
-
-TEST(SignedExchangeCertificateParseB0Test, Empty) {
- EXPECT_FALSE(GetCertChain(nullptr, 0));
-}
-
-TEST(SignedExchangeCertificateParseB0Test, InvalidRequestContextSize) {
- const uint8_t input[] = {
- // clang-format off
- 0x01, // request context size: must be zero
- 0x20, // request context
- // clang-format on
- };
- EXPECT_FALSE(GetCertChain(input, arraysize(input)));
-}
-
-TEST(SignedExchangeCertificateParseB0Test, CanNotReadCertListSize1) {
- const uint8_t input[] = {
- // clang-format off
- 0x00, // request context size
- 0x01, // certificate list size: must be 3 bytes
- // clang-format on
- };
- EXPECT_FALSE(GetCertChain(input, arraysize(input)));
-}
-
-TEST(SignedExchangeCertificateParseB0Test, CanNotReadCertListSize2) {
- const uint8_t input[] = {
- // clang-format off
- 0x00, // request context size
- 0x00, 0x01, // certificate list size: must be 3 bytes
- // clang-format on
- };
- EXPECT_FALSE(GetCertChain(input, arraysize(input)));
-}
-
-TEST(SignedExchangeCertificateParseB0Test, CertListSizeError) {
- const uint8_t input[] = {
- // clang-format off
- 0x00, // request context size
- 0x00, 0x01, 0x01, // certificate list size: 257 (This must be 7)
-
- 0x00, 0x00, 0x02, // cert data size
- 0x11, 0x22, // cert data
- 0x00, 0x00, // extensions size
- // clang-format on
- };
- EXPECT_FALSE(GetCertChain(input, arraysize(input)));
-}
-
-TEST(SignedExchangeCertificateParseB0Test, CanNotReadCertDataSize) {
- const uint8_t input[] = {
- // clang-format off
- 0x00, // request context size
- 0x00, 0x00, 0x02, // certificate list size
-
- 0x00, 0x01, // cert data size: must be 3 bytes
- // clang-format on
- };
- EXPECT_FALSE(GetCertChain(input, arraysize(input)));
-}
-
-TEST(SignedExchangeCertificateParseB0Test, CertDataSizeError) {
- const uint8_t input[] = {
- // clang-format off
- 0x00, // request context size
- 0x00, 0x00, 0x04, // certificate list size
-
- 0x00, 0x00, 0x02, // cert data size
- 0x11, // cert data: Need 2 bytes
- // clang-format on
- };
- EXPECT_FALSE(GetCertChain(input, arraysize(input)));
-}
-
-TEST(SignedExchangeCertificateParseB0Test, CanNotReadExtensionsSize) {
- const uint8_t input[] = {
- // clang-format off
- 0x00, // request context size
- 0x00, 0x00, 0x06, // certificate list size
-
- 0x00, 0x00, 0x02, // cert data size
- 0x11, 0x22, // cert data
- 0x00, // extensions size : must be 2 bytes
- // clang-format on
- };
- EXPECT_FALSE(GetCertChain(input, arraysize(input)));
-}
-
-TEST(SignedExchangeCertificateParseB0Test, ExtensionsSizeError) {
- const uint8_t input[] = {
- // clang-format off
- 0x00, // request context size
- 0x00, 0x00, 0x07, // certificate list size
-
- 0x00, 0x00, 0x02, // cert data size
- 0x11, 0x22, // cert data
- 0x00, 0x01, // extensions size
- // clang-format on
- };
- EXPECT_FALSE(GetCertChain(input, arraysize(input)));
-}
-
TEST(SignedExchangeCertificateParseB1Test, Empty) {
auto parsed = SignedExchangeCertificateChain::Parse(
SignedExchangeVersion::kB1, base::span<const uint8_t>(), nullptr);
@@ -408,7 +159,7 @@ TEST(SignedExchangeCertificateParseB1Test, TwoCerts) {
EXPECT_EQ(parsed->sct(), base::make_optional<std::string>("SCT"));
}
-TEST(SignedExchangeCertificateParseB1Test, HavingOCSPInSecnodCert) {
+TEST(SignedExchangeCertificateParseB1Test, HavingOCSPInSecondCert) {
net::CertificateList certs;
ASSERT_TRUE(net::LoadCertificateFiles(
{"subjectAltName_sanity_check.pem", "root_ca_cert.pem"}, &certs));
@@ -444,8 +195,8 @@ TEST(SignedExchangeCertificateParseB1Test, HavingOCSPInSecnodCert) {
TEST(SignedExchangeCertificateParseB1Test, ParseGoldenFile) {
base::FilePath path;
base::PathService::Get(content::DIR_TEST_DATA, &path);
- path = path.AppendASCII("htxg").AppendASCII(
- "wildcard_example.org.public.pem.cbor");
+ path =
+ path.AppendASCII("sxg").AppendASCII("test.example.org.public.pem.cbor");
std::string contents;
ASSERT_TRUE(base::ReadFileToString(path, &contents));
diff --git a/chromium/content/browser/web_package/signed_exchange_consts.h b/chromium/content/browser/web_package/signed_exchange_consts.h
index 9dedf00f449..6e8bd5210ae 100644
--- a/chromium/content/browser/web_package/signed_exchange_consts.h
+++ b/chromium/content/browser/web_package/signed_exchange_consts.h
@@ -8,25 +8,24 @@
namespace content {
constexpr char kAcceptHeaderSignedExchangeSuffix[] =
- ",application/signed-exchange;v=b0";
+ ",application/signed-exchange;v=b1";
-enum class SignedExchangeVersion { kB0, kB1 };
+enum class SignedExchangeVersion { kB1 };
// Field names defined in the application/signed-exchange content type:
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#application-signed-exchange
-constexpr char kCertSha256Key[] = "certSha256";
-constexpr char kCertUrl[] = "certUrl";
+constexpr char kCertSha256Key[] = "cert-sha256";
+constexpr char kCertUrl[] = "cert-url";
constexpr char kDateKey[] = "date";
constexpr char kExpiresKey[] = "expires";
constexpr char kHeadersKey[] = "headers";
constexpr char kIntegrity[] = "integrity";
constexpr char kMethodKey[] = ":method";
-constexpr char kSignature[] = "signature";
constexpr char kSig[] = "sig";
constexpr char kStatusKey[] = ":status";
constexpr char kUrlKey[] = ":url";
-constexpr char kValidityUrlKey[] = "validityUrl";
+constexpr char kValidityUrlKey[] = "validity-url";
constexpr char kCertChainCborMagic[] = u8"\U0001F4DC\u26D3"; // "📜⛓"
constexpr char kCertKey[] = "cert";
constexpr char kOcspKey[] = "ocsp";
diff --git a/chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc b/chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc
index 3a04504e15d..44f40ccf461 100644
--- a/chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc
+++ b/chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc
@@ -7,7 +7,8 @@
#include "base/trace_event/trace_event.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/frame_host/frame_tree_node.h"
-#include "content/browser/web_package/signed_exchange_header.h"
+#include "content/browser/web_package/signed_exchange_envelope.h"
+#include "content/browser/web_package/signed_exchange_error.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -73,16 +74,17 @@ void OnSignedExchangeReceivedOnUI(
const GURL& outer_request_url,
scoped_refptr<network::ResourceResponse> outer_response,
base::Optional<const base::UnguessableToken> devtools_navigation_token,
- base::Optional<SignedExchangeHeader> header,
+ base::Optional<SignedExchangeEnvelope> envelope,
+ scoped_refptr<net::X509Certificate> certificate,
base::Optional<net::SSLInfo> ssl_info,
- std::vector<std::string> error_messages) {
+ std::vector<SignedExchangeError> errors) {
FrameTreeNode* frame_tree_node =
FrameTreeNode::GloballyFindByID(frame_tree_node_id_getter.Run());
if (!frame_tree_node)
return;
RenderFrameDevToolsAgentHost::OnSignedExchangeReceived(
frame_tree_node, devtools_navigation_token, outer_request_url,
- outer_response->head, header, ssl_info, error_messages);
+ outer_response->head, envelope, certificate, ssl_info, errors);
}
} // namespace
@@ -105,10 +107,11 @@ SignedExchangeDevToolsProxy::~SignedExchangeDevToolsProxy() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
-void SignedExchangeDevToolsProxy::ReportErrorMessage(
- const std::string& message) {
+void SignedExchangeDevToolsProxy::ReportError(
+ const std::string& message,
+ base::Optional<SignedExchangeError::FieldIndexPair> error_field) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- error_messages_.push_back(message);
+ errors_.push_back(SignedExchangeError(message, std::move(error_field)));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&AddErrorMessageToConsoleOnUI, frame_tree_node_id_getter_,
@@ -161,7 +164,8 @@ void SignedExchangeDevToolsProxy::CertificateRequestCompleted(
}
void SignedExchangeDevToolsProxy::OnSignedExchangeReceived(
- const base::Optional<SignedExchangeHeader>& header,
+ const base::Optional<SignedExchangeEnvelope>& envelope,
+ const scoped_refptr<net::X509Certificate>& certificate,
const net::SSLInfo* ssl_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!devtools_enabled_)
@@ -178,8 +182,8 @@ void SignedExchangeDevToolsProxy::OnSignedExchangeReceived(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&OnSignedExchangeReceivedOnUI, frame_tree_node_id_getter_,
outer_request_url_, resource_response->DeepCopy(),
- devtools_navigation_token_, header,
- std::move(ssl_info_opt), std::move(error_messages_)));
+ devtools_navigation_token_, envelope, certificate,
+ std::move(ssl_info_opt), std::move(errors_)));
}
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_devtools_proxy.h b/chromium/content/browser/web_package/signed_exchange_devtools_proxy.h
index e73b1119ec5..33ffee7a164 100644
--- a/chromium/content/browser/web_package/signed_exchange_devtools_proxy.h
+++ b/chromium/content/browser/web_package/signed_exchange_devtools_proxy.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/optional.h"
#include "base/unguessable_token.h"
+#include "content/browser/web_package/signed_exchange_error.h"
#include "content/common/content_export.h"
#include "services/network/public/cpp/resource_response.h"
@@ -23,6 +24,7 @@ class UnguessableToken;
namespace net {
class SSLInfo;
+class X509Certificate;
} // namespace net
namespace network {
@@ -32,7 +34,7 @@ struct URLLoaderCompletionStatus;
} // namespace network
namespace content {
-class SignedExchangeHeader;
+class SignedExchangeEnvelope;
// SignedExchangeDevToolsProxy lives on the IO thread and sends messages to
// DevTools via the UI thread to show signed exchange related information.
@@ -56,7 +58,10 @@ class CONTENT_EXPORT SignedExchangeDevToolsProxy {
bool report_raw_headers);
~SignedExchangeDevToolsProxy();
- void ReportErrorMessage(const std::string& message);
+ void ReportError(
+ const std::string& message,
+ base::Optional<SignedExchangeError::FieldIndexPair> error_field);
+
void CertificateRequestSent(const base::UnguessableToken& request_id,
const network::ResourceRequest& request);
void CertificateResponseReceived(const base::UnguessableToken& request_id,
@@ -67,7 +72,8 @@ class CONTENT_EXPORT SignedExchangeDevToolsProxy {
const network::URLLoaderCompletionStatus& status);
void OnSignedExchangeReceived(
- const base::Optional<SignedExchangeHeader>& header,
+ const base::Optional<SignedExchangeEnvelope>& envelope,
+ const scoped_refptr<net::X509Certificate>& certificate,
const net::SSLInfo* ssl_info);
private:
@@ -76,7 +82,7 @@ class CONTENT_EXPORT SignedExchangeDevToolsProxy {
const base::RepeatingCallback<int(void)> frame_tree_node_id_getter_;
const base::Optional<const base::UnguessableToken> devtools_navigation_token_;
const bool devtools_enabled_;
- std::vector<std::string> error_messages_;
+ std::vector<SignedExchangeError> errors_;
DISALLOW_COPY_AND_ASSIGN(SignedExchangeDevToolsProxy);
};
diff --git a/chromium/content/browser/web_package/signed_exchange_header.cc b/chromium/content/browser/web_package/signed_exchange_envelope.cc
index e0bfe678b2a..b42ccc07872 100644
--- a/chromium/content/browser/web_package/signed_exchange_header.cc
+++ b/chromium/content/browser/web_package/signed_exchange_envelope.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/web_package/signed_exchange_header.h"
+#include "content/browser/web_package/signed_exchange_envelope.h"
#include <utility>
@@ -16,6 +16,7 @@
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_utils.h"
#include "net/http/http_util.h"
+#include "url/origin.h"
namespace content {
@@ -68,12 +69,12 @@ bool IsMethodCacheable(base::StringPiece method) {
}
bool ParseRequestMap(const cbor::CBORValue& value,
- SignedExchangeHeader* out,
+ SignedExchangeEnvelope* out,
SignedExchangeDevToolsProxy* devtools_proxy) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseRequestMap");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseRequestMap");
if (!value.is_map()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Expected request map, got non-map type. Actual type: %d",
static_cast<int>(value.type())));
@@ -85,20 +86,24 @@ bool ParseRequestMap(const cbor::CBORValue& value,
auto url_iter = request_map.find(
cbor::CBORValue(kUrlKey, cbor::CBORValue::Type::BYTE_STRING));
if (url_iter == request_map.end() || !url_iter->second.is_bytestring()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap",
- ":url is not found or not a bytestring.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, ":url is not found or not a bytestring.");
return false;
}
out->set_request_url(GURL(url_iter->second.GetBytestringAsString()));
if (!out->request_url().is_valid()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap", ":url is not a valid URL.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(devtools_proxy,
+ ":url is not a valid URL.");
return false;
}
if (out->request_url().has_ref()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap", ":url can't have a fragment.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, ":url can't have a fragment.");
+ return false;
+ }
+ if (!out->request_url().SchemeIs("https")) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, ":url scheme must be 'https'.");
return false;
}
@@ -106,9 +111,8 @@ bool ParseRequestMap(const cbor::CBORValue& value,
cbor::CBORValue(kMethodKey, cbor::CBORValue::Type::BYTE_STRING));
if (method_iter == request_map.end() ||
!method_iter->second.is_bytestring()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap",
- ":method is not found or not a bytestring.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, ":method is not found or not a bytestring.");
return false;
}
base::StringPiece method_str = method_iter->second.GetBytestringAsString();
@@ -117,8 +121,8 @@ bool ParseRequestMap(const cbor::CBORValue& value,
// [spec text]
if (!net::HttpUtil::IsMethodSafe(method_str.as_string()) ||
!IsMethodCacheable(method_str)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Request method is not safe or not cacheable. method: %s",
method_str.as_string().c_str()));
@@ -128,9 +132,8 @@ bool ParseRequestMap(const cbor::CBORValue& value,
for (const auto& it : request_map) {
if (!it.first.is_bytestring() || !it.second.is_bytestring()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap",
- "Non-bytestring value in the request map.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Non-bytestring value in the request map.");
return false;
}
base::StringPiece name_str = it.first.GetBytestringAsString();
@@ -140,8 +143,8 @@ bool ParseRequestMap(const cbor::CBORValue& value,
// TODO(kouhei): Add spec ref here once
// https://github.com/WICG/webpackage/issues/161 is resolved.
if (name_str != base::ToLowerASCII(name_str)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Request header name should be lower-cased. header name: %s",
name_str.as_string().c_str()));
@@ -151,26 +154,24 @@ bool ParseRequestMap(const cbor::CBORValue& value,
// 4. If exchange’s headers contain a stateful header field, as defined in
// Section 4.1, return “invalid”. [spec text]
if (IsStatefulRequestHeader(name_str)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Exchange contains stateful request header. header name: %s",
name_str.as_string().c_str()));
return false;
}
}
-
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseRequestMap");
return true;
}
bool ParseResponseMap(const cbor::CBORValue& value,
- SignedExchangeHeader* out,
+ SignedExchangeEnvelope* out,
SignedExchangeDevToolsProxy* devtools_proxy) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseResponseMap");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseResponseMap");
if (!value.is_map()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseResponseMap",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Expected request map, got non-map type. Actual type: %d",
static_cast<int>(value.type())));
@@ -182,35 +183,32 @@ bool ParseResponseMap(const cbor::CBORValue& value,
cbor::CBORValue(kStatusKey, cbor::CBORValue::Type::BYTE_STRING));
if (status_iter == response_map.end() ||
!status_iter->second.is_bytestring()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap",
- ":status is not found or not a bytestring.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, ":status is not found or not a bytestring.");
return false;
}
base::StringPiece response_code_str =
status_iter->second.GetBytestringAsString();
int response_code;
if (!base::StringToInt(response_code_str, &response_code)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap",
- "Failed to parse status code to integer.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Failed to parse status code to integer.");
return false;
}
out->set_response_code(static_cast<net::HttpStatusCode>(response_code));
for (const auto& it : response_map) {
if (!it.first.is_bytestring() || !it.second.is_bytestring()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap",
- "Non-bytestring value in the response map.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Non-bytestring value in the response map.");
return false;
}
base::StringPiece name_str = it.first.GetBytestringAsString();
if (name_str == kStatusKey)
continue;
if (!net::HttpUtil::IsValidHeaderName(name_str)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseResponseMap",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf("Invalid header name. header_name: %s",
name_str.as_string().c_str()));
return false;
@@ -219,8 +217,8 @@ bool ParseResponseMap(const cbor::CBORValue& value,
// TODO(kouhei): Add spec ref here once
// https://github.com/WICG/webpackage/issues/161 is resolved.
if (name_str != base::ToLowerASCII(name_str)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseResponseMap",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Response header name should be lower-cased. header_name: %s",
name_str.as_string().c_str()));
@@ -230,8 +228,8 @@ bool ParseResponseMap(const cbor::CBORValue& value,
// 4. If exchange’s headers contain a stateful header field, as defined in
// Section 4.1, return “invalid”. [spec text]
if (IsStatefulResponseHeader(name_str)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseResponseMap",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Exchange contains stateful response header. header_name: %s",
name_str.as_string().c_str()));
@@ -240,53 +238,43 @@ bool ParseResponseMap(const cbor::CBORValue& value,
base::StringPiece value_str = it.second.GetBytestringAsString();
if (!net::HttpUtil::IsValidHeaderValue(value_str)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseRequestMap", "Invalid header value.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(devtools_proxy,
+ "Invalid header value.");
return false;
}
if (!out->AddResponseHeader(name_str, value_str)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "ParseResponseMap",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf("Duplicate header value. header_name: %s",
name_str.as_string().c_str()));
return false;
}
}
-
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseResponseMap");
return true;
}
} // namespace
-constexpr size_t SignedExchangeHeader::kEncodedLengthInBytes;
-
-// static
-size_t SignedExchangeHeader::ParseEncodedLength(
- base::span<const uint8_t> input) {
- DCHECK_EQ(input.size(), SignedExchangeHeader::kEncodedLengthInBytes);
- return static_cast<size_t>(input[0]) << 16 |
- static_cast<size_t>(input[1]) << 8 | static_cast<size_t>(input[2]);
-}
-
// static
-base::Optional<SignedExchangeHeader> SignedExchangeHeader::Parse(
- base::span<const uint8_t> input,
+base::Optional<SignedExchangeEnvelope> SignedExchangeEnvelope::Parse(
+ base::StringPiece signature_header_field,
+ base::span<const uint8_t> cbor_header,
SignedExchangeDevToolsProxy* devtools_proxy) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHeader::Parse");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeEnvelope::Parse");
cbor::CBORReader::DecoderError error;
- base::Optional<cbor::CBORValue> value = cbor::CBORReader::Read(input, &error);
+ base::Optional<cbor::CBORValue> value =
+ cbor::CBORReader::Read(cbor_header, &error);
if (!value.has_value()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeader::Parse",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf("Failed to decode CBORValue. CBOR error: %s",
cbor::CBORReader::ErrorCodeToString(error)));
return base::nullopt;
}
if (!value->is_array()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeader::Parse",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Expected top-level CBORValue to be an array. Actual type : %d",
static_cast<int>(value->type())));
@@ -296,64 +284,65 @@ base::Optional<SignedExchangeHeader> SignedExchangeHeader::Parse(
const cbor::CBORValue::ArrayValue& top_level_array = value->GetArray();
constexpr size_t kTopLevelArraySize = 2;
if (top_level_array.size() != kTopLevelArraySize) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeader::Parse",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf("Expected top-level array to have 2 elements. "
"Actual element count: %" PRIuS,
top_level_array.size()));
return base::nullopt;
}
- SignedExchangeHeader ret;
+ SignedExchangeEnvelope ret;
if (!ParseRequestMap(top_level_array[0], &ret, devtools_proxy)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeader::Parse",
- "Failed to parse request map.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Failed to parse request map.");
return base::nullopt;
}
if (!ParseResponseMap(top_level_array[1], &ret, devtools_proxy)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeader::Parse",
- "Failed to parse response map.");
- return base::nullopt;
- }
-
- auto signature_iter = ret.response_headers_.find(kSignature);
- if (signature_iter == ret.response_headers_.end()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeader::Parse",
- "No signature header found.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Failed to parse response map.");
return base::nullopt;
}
- base::Optional<std::vector<SignedExchangeHeaderParser::Signature>>
- signatures = SignedExchangeHeaderParser::ParseSignature(
- signature_iter->second, devtools_proxy);
+ base::Optional<std::vector<SignedExchangeSignatureHeaderField::Signature>>
+ signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ signature_header_field, devtools_proxy);
if (!signatures || signatures->empty()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeader::Parse",
- "Failed to parse signature.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Failed to parse signature header field.");
return base::nullopt;
}
+ // TODO(https://crbug.com/850475): Support multiple signatures.
ret.signature_ = (*signatures)[0];
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHeader::Parse");
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cross-origin-trust
+ // If the signature’s “validity-url” parameter is not same-origin with
+ // exchange’s effective request URI (Section 5.5 of [RFC7230]), return
+ // “invalid” [spec text]
+ const GURL request_url = ret.request_url();
+ const GURL validity_url = ret.signature().validity_url;
+ if (!url::IsSameOriginWith(request_url, validity_url)) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Validity URL must be same-origin with request URL.");
+ return base::nullopt;
+ }
+
return std::move(ret);
}
-SignedExchangeHeader::SignedExchangeHeader() = default;
-SignedExchangeHeader::SignedExchangeHeader(const SignedExchangeHeader&) =
+SignedExchangeEnvelope::SignedExchangeEnvelope() = default;
+SignedExchangeEnvelope::SignedExchangeEnvelope(const SignedExchangeEnvelope&) =
default;
-SignedExchangeHeader::SignedExchangeHeader(SignedExchangeHeader&&) = default;
-SignedExchangeHeader::~SignedExchangeHeader() = default;
-SignedExchangeHeader& SignedExchangeHeader::operator=(SignedExchangeHeader&&) =
+SignedExchangeEnvelope::SignedExchangeEnvelope(SignedExchangeEnvelope&&) =
default;
+SignedExchangeEnvelope::~SignedExchangeEnvelope() = default;
+SignedExchangeEnvelope& SignedExchangeEnvelope::operator=(
+ SignedExchangeEnvelope&&) = default;
-bool SignedExchangeHeader::AddResponseHeader(base::StringPiece name,
- base::StringPiece value) {
+bool SignedExchangeEnvelope::AddResponseHeader(base::StringPiece name,
+ base::StringPiece value) {
std::string name_str = name.as_string();
DCHECK_EQ(name_str, base::ToLowerASCII(name))
<< "Response header names should be always lower-cased.";
@@ -365,7 +354,7 @@ bool SignedExchangeHeader::AddResponseHeader(base::StringPiece name,
}
scoped_refptr<net::HttpResponseHeaders>
-SignedExchangeHeader::BuildHttpResponseHeaders() const {
+SignedExchangeEnvelope::BuildHttpResponseHeaders() const {
std::string header_str("HTTP/1.1 ");
header_str.append(base::NumberToString(response_code()));
header_str.append(" ");
diff --git a/chromium/content/browser/web_package/signed_exchange_header.h b/chromium/content/browser/web_package/signed_exchange_envelope.h
index e544f17994e..7d865308062 100644
--- a/chromium/content/browser/web_package/signed_exchange_header.h
+++ b/chromium/content/browser/web_package/signed_exchange_envelope.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_WEB_PACKAGE_SIGNED_EXCHANGE_HEADER_H_
-#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_HEADER_H_
+#ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_ENVELOPE_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_ENVELOPE_H_
#include <map>
#include <string>
@@ -13,7 +13,7 @@
#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
-#include "content/browser/web_package/signed_exchange_header_parser.h"
+#include "content/browser/web_package/signed_exchange_signature_header_field.h"
#include "content/common/content_export.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
@@ -23,32 +23,27 @@ namespace content {
class SignedExchangeDevToolsProxy;
-// SignedExchangeHeader contains all information captured in signed exchange
-// envelope but the payload.
+// SignedExchangeEnvelope contains all information captured in
+// the "application/signed-exchange" format but the payload.
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html
-class CONTENT_EXPORT SignedExchangeHeader {
+class CONTENT_EXPORT SignedExchangeEnvelope {
public:
- static constexpr size_t kEncodedLengthInBytes = 3;
- // Parse encoded length of the variable-length field in the signed exchange.
- // Note: |input| must be pointing to a valid memory address that has at least
- // |kEncodedLengthInBytes|.
- static size_t ParseEncodedLength(base::span<const uint8_t> input);
-
using HeaderMap = std::map<std::string, std::string>;
// Parse headers from the application/signed-exchange;v=b0 format.
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#application-signed-exchange
//
- // This also performs the step 3 and 4 of "Cross-origin trust" validation.
+ // This also performs the step 1, 3 and 4 of "Cross-origin trust" validation.
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#cross-origin-trust
- static base::Optional<SignedExchangeHeader> Parse(
- base::span<const uint8_t> input,
+ static base::Optional<SignedExchangeEnvelope> Parse(
+ base::StringPiece signature_header_field,
+ base::span<const uint8_t> cbor_header,
SignedExchangeDevToolsProxy* devtools_proxy);
- SignedExchangeHeader();
- SignedExchangeHeader(const SignedExchangeHeader&);
- SignedExchangeHeader(SignedExchangeHeader&&);
- SignedExchangeHeader& operator=(SignedExchangeHeader&&);
- ~SignedExchangeHeader();
+ SignedExchangeEnvelope();
+ SignedExchangeEnvelope(const SignedExchangeEnvelope&);
+ SignedExchangeEnvelope(SignedExchangeEnvelope&&);
+ SignedExchangeEnvelope& operator=(SignedExchangeEnvelope&&);
+ ~SignedExchangeEnvelope();
// AddResponseHeader returns false on duplicated keys. |name| must be
// lower-cased.
@@ -68,11 +63,11 @@ class CONTENT_EXPORT SignedExchangeHeader {
const HeaderMap& response_headers() const { return response_headers_; }
- const SignedExchangeHeaderParser::Signature& signature() const {
+ const SignedExchangeSignatureHeaderField::Signature& signature() const {
return signature_;
}
void SetSignatureForTesting(
- const SignedExchangeHeaderParser::Signature& sig) {
+ const SignedExchangeSignatureHeaderField::Signature& sig) {
signature_ = sig;
}
@@ -82,9 +77,9 @@ class CONTENT_EXPORT SignedExchangeHeader {
net::HttpStatusCode response_code_;
HeaderMap response_headers_;
- SignedExchangeHeaderParser::Signature signature_;
+ SignedExchangeSignatureHeaderField::Signature signature_;
};
} // namespace content
-#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_HEADER_H_
+#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_ENVELOPE_H_
diff --git a/chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc b/chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc
new file mode 100644
index 00000000000..021d7fef021
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc
@@ -0,0 +1,230 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_package/signed_exchange_envelope.h"
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "components/cbor/cbor_values.h"
+#include "components/cbor/cbor_writer.h"
+#include "content/browser/web_package/signed_exchange_consts.h"
+#include "content/browser/web_package/signed_exchange_prologue.h"
+#include "content/public/common/content_paths.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+const char kSignatureString[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https://test.example.org/resource.validity.1511128380\";"
+ " cert-url=\"https://example.com/oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+
+cbor::CBORValue CBORByteString(const char* str) {
+ return cbor::CBORValue(str, cbor::CBORValue::Type::BYTE_STRING);
+}
+
+base::Optional<SignedExchangeEnvelope> GenerateHeaderAndParse(
+ base::StringPiece signature,
+ const std::map<const char*, const char*>& request_map,
+ const std::map<const char*, const char*>& response_map) {
+ cbor::CBORValue::MapValue request_cbor_map;
+ cbor::CBORValue::MapValue response_cbor_map;
+ for (auto& pair : request_map)
+ request_cbor_map[CBORByteString(pair.first)] = CBORByteString(pair.second);
+ for (auto& pair : response_map)
+ response_cbor_map[CBORByteString(pair.first)] = CBORByteString(pair.second);
+
+ cbor::CBORValue::ArrayValue array;
+ array.push_back(cbor::CBORValue(std::move(request_cbor_map)));
+ array.push_back(cbor::CBORValue(std::move(response_cbor_map)));
+
+ auto serialized = cbor::CBORWriter::Write(cbor::CBORValue(std::move(array)));
+ return SignedExchangeEnvelope::Parse(
+ signature, base::make_span(serialized->data(), serialized->size()),
+ nullptr /* devtools_proxy */);
+}
+
+} // namespace
+
+TEST(SignedExchangeEnvelopeTest, ParseGoldenFile) {
+ base::FilePath test_sxg_path;
+ base::PathService::Get(content::DIR_TEST_DATA, &test_sxg_path);
+ test_sxg_path =
+ test_sxg_path.AppendASCII("sxg").AppendASCII("test.example.org_test.sxg");
+
+ std::string contents;
+ ASSERT_TRUE(base::ReadFileToString(test_sxg_path, &contents));
+ auto* contents_bytes = reinterpret_cast<const uint8_t*>(contents.data());
+
+ ASSERT_GT(contents.size(), SignedExchangePrologue::kEncodedPrologueInBytes);
+ base::Optional<SignedExchangePrologue> prologue =
+ SignedExchangePrologue::Parse(
+ base::make_span(contents_bytes,
+ SignedExchangePrologue::kEncodedPrologueInBytes),
+ nullptr /* devtools_proxy */);
+ ASSERT_TRUE(prologue.has_value());
+ ASSERT_GT(contents.size(), SignedExchangePrologue::kEncodedPrologueInBytes +
+ prologue->ComputeFollowingSectionsLength());
+
+ base::StringPiece signature_header_field(
+ contents.data() + SignedExchangePrologue::kEncodedPrologueInBytes,
+ prologue->signature_header_field_length());
+ const auto cbor_bytes = base::make_span<const uint8_t>(
+ contents_bytes + SignedExchangePrologue::kEncodedPrologueInBytes +
+ prologue->signature_header_field_length(),
+ prologue->cbor_header_length());
+ const base::Optional<SignedExchangeEnvelope> envelope =
+ SignedExchangeEnvelope::Parse(signature_header_field, cbor_bytes,
+ nullptr /* devtools_proxy */);
+ ASSERT_TRUE(envelope.has_value());
+ EXPECT_EQ(envelope->request_url(), GURL("https://test.example.org/test/"));
+ EXPECT_EQ(envelope->request_method(), "GET");
+ EXPECT_EQ(envelope->response_code(), static_cast<net::HttpStatusCode>(200u));
+ EXPECT_EQ(envelope->response_headers().size(), 3u);
+ EXPECT_EQ(envelope->response_headers().find("content-encoding")->second,
+ "mi-sha256-draft2");
+}
+
+TEST(SignedExchangeEnvelopeTest, ValidHeader) {
+ auto header = GenerateHeaderAndParse(
+ kSignatureString,
+ {
+ {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "GET"},
+ },
+ {{kStatusKey, "200"}, {"content-type", "text/html"}});
+ ASSERT_TRUE(header.has_value());
+ EXPECT_EQ(header->request_url(), GURL("https://test.example.org/test/"));
+ EXPECT_EQ(header->request_method(), "GET");
+ EXPECT_EQ(header->response_code(), static_cast<net::HttpStatusCode>(200u));
+ EXPECT_EQ(header->response_headers().size(), 1u);
+}
+
+TEST(SignedExchangeEnvelopeTest, UnsafeMethod) {
+ auto header = GenerateHeaderAndParse(
+ kSignatureString,
+ {
+ {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "POST"},
+ },
+ {
+ {kStatusKey, "200"},
+ });
+ ASSERT_FALSE(header.has_value());
+}
+
+TEST(SignedExchangeEnvelopeTest, InvalidURL) {
+ auto header = GenerateHeaderAndParse(
+ kSignatureString,
+ {
+ {kUrlKey, "https:://test.example.org/test/"}, {kMethodKey, "GET"},
+ },
+ {
+ {kStatusKey, "200"},
+ });
+ ASSERT_FALSE(header.has_value());
+}
+
+TEST(SignedExchangeEnvelopeTest, URLWithFragment) {
+ auto header = GenerateHeaderAndParse(
+ kSignatureString,
+ {
+ {kUrlKey, "https://test.example.org/test/#foo"}, {kMethodKey, "GET"},
+ },
+ {
+ {kStatusKey, "200"},
+ });
+ ASSERT_FALSE(header.has_value());
+}
+
+TEST(SignedExchangeEnvelopeTest, RelativeURL) {
+ auto header =
+ GenerateHeaderAndParse(kSignatureString,
+ {
+ {kUrlKey, "test/"}, {kMethodKey, "GET"},
+ },
+ {
+ {kStatusKey, "200"},
+ });
+ ASSERT_FALSE(header.has_value());
+}
+
+TEST(SignedExchangeEnvelopeTest, HttpURLShouldFail) {
+ auto header = GenerateHeaderAndParse(
+ kSignatureString,
+ {
+ {kUrlKey, "http://test.example.org/test/"}, {kMethodKey, "GET"},
+ },
+ {
+ {kStatusKey, "200"},
+ });
+ ASSERT_FALSE(header.has_value());
+}
+
+TEST(SignedExchangeEnvelopeTest, StatefulRequestHeader) {
+ auto header =
+ GenerateHeaderAndParse(kSignatureString,
+ {
+ {kUrlKey, "https://test.example.org/test/"},
+ {kMethodKey, "GET"},
+ {"authorization", "Basic Zm9vOmJhcg=="},
+ },
+ {
+ {kStatusKey, "200"},
+ });
+ ASSERT_FALSE(header.has_value());
+}
+
+TEST(SignedExchangeEnvelopeTest, StatefulResponseHeader) {
+ auto header = GenerateHeaderAndParse(
+ kSignatureString,
+ {
+ {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "GET"},
+ },
+ {
+ {kStatusKey, "200"}, {"set-cookie", "foo=bar"},
+ });
+ ASSERT_FALSE(header.has_value());
+}
+
+TEST(SignedExchangeEnvelopeTest, UppercaseRequestMap) {
+ auto header =
+ GenerateHeaderAndParse(kSignatureString,
+ {{kUrlKey, "https://test.example.org/test/"},
+ {kMethodKey, "GET"},
+ {"Accept-Language", "en-us"}},
+ {
+ {kStatusKey, "200"},
+ });
+ ASSERT_FALSE(header.has_value());
+}
+
+TEST(SignedExchangeEnvelopeTest, UppercaseResponseMap) {
+ auto header = GenerateHeaderAndParse(
+ kSignatureString,
+ {
+ {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "GET"},
+ },
+ {{kStatusKey, "200"}, {"Content-Length", "123"}});
+ ASSERT_FALSE(header.has_value());
+}
+
+TEST(SignedExchangeEnvelopeTest, InvalidValidityURLHeader) {
+ auto header = GenerateHeaderAndParse(
+ kSignatureString,
+ {
+ {kUrlKey, "https://test2.example.org/test/"}, {kMethodKey, "GET"},
+ },
+ {{kStatusKey, "200"}, {"content-type", "text/html"}});
+ ASSERT_FALSE(header.has_value());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_error.cc b/chromium/content/browser/web_package/signed_exchange_error.cc
new file mode 100644
index 00000000000..c9c914856b7
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_error.cc
@@ -0,0 +1,48 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_package/signed_exchange_error.h"
+
+namespace content {
+
+// static
+base::Optional<SignedExchangeError::Field>
+SignedExchangeError::GetFieldFromSignatureVerifierResult(
+ SignedExchangeSignatureVerifier::Result verify_result) {
+ switch (verify_result) {
+ case SignedExchangeSignatureVerifier::Result::kSuccess:
+ return base::nullopt;
+ case SignedExchangeSignatureVerifier::Result::kErrNoCertificate:
+ return base::nullopt;
+ case SignedExchangeSignatureVerifier::Result::kErrNoCertificateSHA256:
+ return Field::kSignatureCertSha256;
+ case SignedExchangeSignatureVerifier::Result::kErrCertificateSHA256Mismatch:
+ return Field::kSignatureCertSha256;
+ case SignedExchangeSignatureVerifier::Result::kErrInvalidSignatureFormat:
+ return base::nullopt;
+ case SignedExchangeSignatureVerifier::Result::
+ kErrSignatureVerificationFailed:
+ return Field::kSignatureSig;
+ case SignedExchangeSignatureVerifier::Result::kErrInvalidSignatureIntegrity:
+ return Field::kSignatureIintegrity;
+ case SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp:
+ return Field::kSignatureTimestamps;
+ case SignedExchangeSignatureVerifier::Result::kErrUnsupportedCertType:
+ return Field::kSignatureCertUrl;
+ }
+
+ NOTREACHED();
+ return base::nullopt;
+}
+
+SignedExchangeError::SignedExchangeError(const std::string& message,
+ base::Optional<FieldIndexPair> field)
+ : message(message), field(field) {}
+
+SignedExchangeError::SignedExchangeError(const SignedExchangeError& other) =
+ default;
+SignedExchangeError::SignedExchangeError(SignedExchangeError&& other) = default;
+SignedExchangeError::~SignedExchangeError() = default;
+
+} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_error.h b/chromium/content/browser/web_package/signed_exchange_error.h
new file mode 100644
index 00000000000..50856c66d4b
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_error.h
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_ERROR_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_ERROR_H_
+
+#include <string>
+#include <utility>
+
+#include "base/optional.h"
+#include "content/browser/web_package/signed_exchange_signature_verifier.h"
+
+namespace content {
+
+struct SignedExchangeError {
+ public:
+ enum class Field {
+ kSignatureSig,
+ kSignatureIintegrity,
+ kSignatureCertUrl,
+ kSignatureCertSha256,
+ kSignatureValidityUrl,
+ kSignatureTimestamps,
+ };
+
+ // |signature_index| will be used when we will support multiple signatures in
+ // a signed exchange header to indicate which signature is causing the error.
+ using FieldIndexPair = std::pair<int /* signature_index */, Field>;
+
+ static base::Optional<Field> GetFieldFromSignatureVerifierResult(
+ SignedExchangeSignatureVerifier::Result verify_result);
+
+ SignedExchangeError(const std::string& message,
+ base::Optional<FieldIndexPair> field);
+
+ // Copy constructor.
+ SignedExchangeError(const SignedExchangeError& other);
+ // Move constructor.
+ SignedExchangeError(SignedExchangeError&& other);
+
+ ~SignedExchangeError();
+
+ std::string message;
+ base::Optional<FieldIndexPair> field;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_ERROR_H_
diff --git a/chromium/content/browser/web_package/signed_exchange_handler.cc b/chromium/content/browser/web_package/signed_exchange_handler.cc
index 52e127a28e9..b068987cc1f 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_handler.cc
@@ -11,20 +11,28 @@
#include "content/browser/web_package/signed_exchange_cert_fetcher_factory.h"
#include "content/browser/web_package/signed_exchange_certificate_chain.h"
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
-#include "content/browser/web_package/signed_exchange_header.h"
+#include "content/browser/web_package/signed_exchange_envelope.h"
+#include "content/browser/web_package/signed_exchange_prologue.h"
#include "content/browser/web_package/signed_exchange_signature_verifier.h"
#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/url_loader_throttle.h"
#include "mojo/public/cpp/system/string_data_pipe_producer.h"
#include "net/base/io_buffer.h"
+#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/cert/asn1_util.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
+#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/ct_verifier.h"
#include "net/cert/x509_certificate.h"
+#include "net/cert/x509_util.h"
#include "net/filter/source_stream.h"
+#include "net/http/transport_security_state.h"
#include "net/ssl/ssl_config.h"
#include "net/ssl/ssl_config_service.h"
#include "net/ssl/ssl_info.h"
@@ -39,11 +47,7 @@ namespace content {
namespace {
-// 256KB (Maximum header size) * 2, since signed exchange header contains
-// request and response headers.
-constexpr size_t kMaxHeadersCBORLength = 512 * 1024;
-
-constexpr char kMiHeader[] = "MI";
+constexpr char kMiHeader[] = "MI-Draft2";
net::CertVerifier* g_cert_verifier_for_testing = nullptr;
@@ -74,11 +78,13 @@ SignedExchangeHandler::SignedExchangeHandler(
std::unique_ptr<net::SourceStream> body,
ExchangeHeadersCallback headers_callback,
std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory,
+ int load_flags,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy)
: headers_callback_(std::move(headers_callback)),
source_(std::move(body)),
cert_fetcher_factory_(std::move(cert_fetcher_factory)),
+ load_flags_(load_flags),
request_context_getter_(std::move(request_context_getter)),
net_log_(net::NetLogWithSource::Make(
request_context_getter_->GetURLRequestContext()->net_log(),
@@ -86,39 +92,37 @@ SignedExchangeHandler::SignedExchangeHandler(
devtools_proxy_(std::move(devtools_proxy)),
weak_factory_(this) {
DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::SignedExchangeHandler");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeHandler::SignedExchangeHandler");
- if (!SignedExchangeHeaderParser::GetVersionParamFromContentType(content_type,
- &version_) ||
- (version_ != SignedExchangeVersion::kB0 &&
- version_ != SignedExchangeVersion::kB1)) {
+ if (!SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
+ content_type, &version_) ||
+ version_ != SignedExchangeVersion::kB1) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&SignedExchangeHandler::RunErrorCallback,
weak_factory_.GetWeakPtr(),
net::ERR_INVALID_SIGNED_EXCHANGE));
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_.get(), "SignedExchangeHandler::SignedExchangeHandler",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(),
base::StringPrintf("Unsupported version of the content type. Currentry "
"content type must be "
- "\"application/signed-exchange;v={b0,b1}\". But the "
+ "\"application/signed-exchange;v=b1\". But the "
"response content type was \"%s\"",
content_type.c_str()));
return;
}
- // Triggering the read (asynchronously) for the encoded header length.
- SetupBuffers(SignedExchangeHeader::kEncodedLengthInBytes);
+ // Triggering the read (asynchronously) for the prologue bytes.
+ SetupBuffers(SignedExchangePrologue::kEncodedPrologueInBytes);
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&SignedExchangeHandler::DoHeaderLoop,
weak_factory_.GetWeakPtr()));
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::SignedExchangeHandler");
}
SignedExchangeHandler::~SignedExchangeHandler() = default;
-SignedExchangeHandler::SignedExchangeHandler() : weak_factory_(this) {}
+SignedExchangeHandler::SignedExchangeHandler()
+ : load_flags_(net::LOAD_NORMAL), weak_factory_(this) {}
void SignedExchangeHandler::SetupBuffers(size_t size) {
header_buf_ = base::MakeRefCounted<net::IOBuffer>(size);
@@ -127,8 +131,7 @@ void SignedExchangeHandler::SetupBuffers(size_t size) {
}
void SignedExchangeHandler::DoHeaderLoop() {
- DCHECK(state_ == State::kReadingHeadersLength ||
- state_ == State::kReadingHeaders);
+ DCHECK(state_ == State::kReadingPrologue || state_ == State::kReadingHeaders);
int rv = source_->Read(
header_read_buf_.get(), header_read_buf_->BytesRemaining(),
base::BindRepeating(&SignedExchangeHandler::DidReadHeader,
@@ -138,19 +141,21 @@ void SignedExchangeHandler::DoHeaderLoop() {
}
void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::DidReadHeader");
+ DCHECK(state_ == State::kReadingPrologue || state_ == State::kReadingHeaders);
+
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeHandler::DidReadHeader");
if (result < 0) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_.get(), "SignedExchangeHandler::DidReadHeader",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(),
base::StringPrintf("Error reading body stream. result: %d", result));
RunErrorCallback(static_cast<net::Error>(result));
return;
}
if (result == 0) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_.get(), "SignedExchangeHandler::DidReadHeader",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(),
"Stream ended while reading signed exchange header.");
RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
@@ -159,28 +164,29 @@ void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
header_read_buf_->DidConsume(result);
if (header_read_buf_->BytesRemaining() == 0) {
switch (state_) {
- case State::kReadingHeadersLength:
- if (!ParseHeadersLength())
+ case State::kReadingPrologue:
+ if (!ParsePrologue()) {
RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ return;
+ }
break;
case State::kReadingHeaders:
- if (!ParseHeadersAndFetchCertificate())
+ if (!ParseHeadersAndFetchCertificate()) {
RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ return;
+ }
break;
default:
NOTREACHED();
}
}
- if (state_ != State::kReadingHeadersLength &&
- state_ != State::kReadingHeaders) {
- TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::DidReadHeader", "state",
- static_cast<int>(state_));
+ // We have finished reading headers, so return without queueing the next read.
+ if (state_ == State::kFetchingCertificate)
return;
- }
// Trigger the next read.
+ DCHECK(state_ == State::kReadingPrologue || state_ == State::kReadingHeaders);
if (completed_syncly) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&SignedExchangeHandler::DoHeaderLoop,
@@ -188,76 +194,75 @@ void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
} else {
DoHeaderLoop();
}
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::DidReadHeader");
}
-bool SignedExchangeHandler::ParseHeadersLength() {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::ParseEncodedLength");
- DCHECK_EQ(state_, State::kReadingHeadersLength);
+bool SignedExchangeHandler::ParsePrologue() {
+ DCHECK_EQ(state_, State::kReadingPrologue);
- headers_length_ = SignedExchangeHeader::ParseEncodedLength(
+ prologue_ = SignedExchangePrologue::Parse(
base::make_span(reinterpret_cast<uint8_t*>(header_buf_->data()),
- SignedExchangeHeader::kEncodedLengthInBytes));
- if (headers_length_ == 0 || headers_length_ > kMaxHeadersCBORLength) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_.get(), "SignedExchangeHandler::ParseEncodedLength",
- base::StringPrintf("Invalid CBOR header length: %zu", headers_length_));
+ SignedExchangePrologue::kEncodedPrologueInBytes),
+ devtools_proxy_.get());
+ if (!prologue_)
return false;
- }
- // Set up a new buffer for CBOR-encoded buffer reading.
- SetupBuffers(headers_length_);
+ // Set up a new buffer for Signature + CBOR-encoded header reading.
+ SetupBuffers(prologue_->ComputeFollowingSectionsLength());
state_ = State::kReadingHeaders;
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::ParseEncodedLength");
return true;
}
bool SignedExchangeHandler::ParseHeadersAndFetchCertificate() {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::ParseHeadersAndFetchCertificate");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeHandler::ParseHeadersAndFetchCertificate");
DCHECK_EQ(state_, State::kReadingHeaders);
- header_ = SignedExchangeHeader::Parse(
- base::make_span(reinterpret_cast<uint8_t*>(header_buf_->data()),
- headers_length_),
- devtools_proxy_.get());
+ base::StringPiece data(header_buf_->data(), header_read_buf_->size());
+ base::StringPiece signature_header_field =
+ data.substr(0, prologue_->signature_header_field_length());
+ base::span<const uint8_t> cbor_header = base::as_bytes(
+ base::make_span(data.substr(prologue_->signature_header_field_length(),
+ prologue_->cbor_header_length())));
+ envelope_ = SignedExchangeEnvelope::Parse(signature_header_field, cbor_header,
+ devtools_proxy_.get());
header_read_buf_ = nullptr;
header_buf_ = nullptr;
- if (!header_) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_.get(),
- "SignedExchangeHandler::ParseHeadersAndFetchCertificate",
- "Failed to parse SignedExchange header.");
+ if (!envelope_) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(), "Failed to parse SignedExchange header.");
return false;
}
- const GURL cert_url = header_->signature().cert_url;
+ const GURL cert_url = envelope_->signature().cert_url;
// TODO(https://crbug.com/819467): When we will support ed25519Key, |cert_url|
// may be empty.
DCHECK(cert_url.is_valid());
DCHECK(version_.has_value());
DCHECK(cert_fetcher_factory_);
+
+ const bool force_fetch = load_flags_ & net::LOAD_BYPASS_CACHE;
+
cert_fetcher_ = std::move(cert_fetcher_factory_)
->CreateFetcherAndStart(
- cert_url, false, *version_,
+ cert_url, force_fetch, *version_,
base::BindOnce(&SignedExchangeHandler::OnCertReceived,
base::Unretained(this)),
devtools_proxy_.get());
state_ = State::kFetchingCertificate;
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::ParseHeadersAndFetchCertificate");
return true;
}
void SignedExchangeHandler::RunErrorCallback(net::Error error) {
DCHECK_NE(state_, State::kHeadersCallbackCalled);
- if (devtools_proxy_)
- devtools_proxy_->OnSignedExchangeReceived(header_, nullptr);
+ if (devtools_proxy_) {
+ devtools_proxy_->OnSignedExchangeReceived(
+ envelope_,
+ unverified_cert_chain_ ? unverified_cert_chain_->cert()
+ : scoped_refptr<net::X509Certificate>(),
+ nullptr);
+ }
std::move(headers_callback_)
.Run(error, GURL(), std::string(), network::ResourceResponseHead(),
nullptr);
@@ -266,39 +271,48 @@ void SignedExchangeHandler::RunErrorCallback(net::Error error) {
void SignedExchangeHandler::OnCertReceived(
std::unique_ptr<SignedExchangeCertificateChain> cert_chain) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::OnCertReceived");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeHandler::OnCertReceived");
DCHECK_EQ(state_, State::kFetchingCertificate);
if (!cert_chain) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_.get(), "SignedExchangeHandler::OnCertReceived",
- "Failed to fetch the certificate.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(), "Failed to fetch the certificate.",
+ std::make_pair(0 /* signature_index */,
+ SignedExchangeError::Field::kSignatureCertUrl));
RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
- if (SignedExchangeSignatureVerifier::Verify(*header_, cert_chain->cert(),
- GetVerificationTime(),
- devtools_proxy_.get()) !=
- SignedExchangeSignatureVerifier::Result::kSuccess) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_.get(), "SignedExchangeHandler::OnCertReceived",
- "Failed to verify the signed exchange header.");
+ unverified_cert_chain_ = std::move(cert_chain);
+
+ const SignedExchangeSignatureVerifier::Result verify_result =
+ SignedExchangeSignatureVerifier::Verify(
+ *envelope_, unverified_cert_chain_->cert(), GetVerificationTime(),
+ devtools_proxy_.get());
+ if (verify_result != SignedExchangeSignatureVerifier::Result::kSuccess) {
+ base::Optional<SignedExchangeError::Field> error_field =
+ SignedExchangeError::GetFieldFromSignatureVerifierResult(verify_result);
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(), "Failed to verify the signed exchange header.",
+ error_field ? base::make_optional(
+ std::make_pair(0 /* signature_index */, *error_field))
+ : base::nullopt);
RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
+
+ // TODO(https://crbug.com/849935): The code below reaching into
+ // URLRequestContext will not work with Network service.
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
net::URLRequestContext* request_context =
request_context_getter_->GetURLRequestContext();
if (!request_context) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_.get(), "SignedExchangeHandler::OnCertReceived",
- "No request context available.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(), "No request context available.");
RunErrorCallback(net::ERR_CONTEXT_SHUT_DOWN);
return;
}
- unverified_cert_chain_ = std::move(cert_chain);
-
net::SSLConfig config;
request_context->ssl_config_service()->GetSSLConfig(&config);
@@ -307,7 +321,7 @@ void SignedExchangeHandler::OnCertReceived(
: request_context->cert_verifier();
int result = cert_verifier->Verify(
net::CertVerifier::RequestParams(
- unverified_cert_chain_->cert(), header_->request_url().host(),
+ unverified_cert_chain_->cert(), envelope_->request_url().host(),
config.GetCertVerifyFlags(), unverified_cert_chain_->ocsp(),
net::CertificateList()),
net::SSLConfigService::GetCRLSet().get(), &cert_verify_result_,
@@ -318,9 +332,19 @@ void SignedExchangeHandler::OnCertReceived(
// explicit state machines (eg: DoLoop() in //net).
if (result != net::ERR_IO_PENDING)
OnCertVerifyComplete(result);
+}
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::OnCertReceived");
+bool SignedExchangeHandler::CheckCertExtension(
+ const net::X509Certificate* verified_cert) {
+ if (base::FeatureList::IsEnabled(
+ features::kAllowSignedHTTPExchangeCertsWithoutExtension))
+ return true;
+
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cross-origin-trust
+ // Step 6.2. Validate that main-certificate has the CanSignHttpExchanges
+ // extension (Section 4.2). [spec text]
+ return net::asn1::HasCanSignHttpExchangesDraftExtension(
+ net::x509_util::CryptoBufferAsStringPiece(verified_cert->cert_buffer()));
}
bool SignedExchangeHandler::CheckOCSPStatus(
@@ -333,10 +357,6 @@ bool SignedExchangeHandler::CheckOCSPStatus(
// OCSP verification is done in CertVerifier::Verify(), so we just check the
// result here.
- // The b0 implementation checkpoint has no OCSP check.
- if (version_ == SignedExchangeVersion::kB0)
- return true;
-
if (ocsp_result.response_status != net::OCSPVerifyResult::PROVIDED ||
ocsp_result.revocation_status != net::OCSPRevocationStatus::GOOD)
return false;
@@ -344,32 +364,150 @@ bool SignedExchangeHandler::CheckOCSPStatus(
return true;
}
+// TODO(https://crbug.com/815025, https://crbug.com/849935): This is temporary
+// code until we have Network Service friendly CT verification.
+int SignedExchangeHandler::VerifyCT(net::ct::CTVerifyResult* ct_verify_result) {
+ // This function will not work with Network Service.
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+
+ net::URLRequestContext* request_context =
+ request_context_getter_->GetURLRequestContext();
+ if (!request_context)
+ return net::ERR_CONTEXT_SHUT_DOWN;
+
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cross-origin-trust
+ // Step 6.4 Validate that valid SCTs from trusted logs are available from any
+ // of:
+ // - The SignedCertificateTimestampList in main-certificate’s sct property
+ // (Section 3.3),
+ const std::string& sct_list_from_cert_cbor = unverified_cert_chain_->sct();
+ // - An OCSP extension in the OCSP response in main-certificate’s ocsp
+ // property, or
+ const std::string& stapled_ocsp_response = unverified_cert_chain_->ocsp();
+ // - An X.509 extension in the certificate in main-certificate’s cert
+ // property,
+ net::X509Certificate* verified_cert = cert_verify_result_.verified_cert.get();
+ // as described by Section 3.3 of [RFC6962]. [spec text]
+ request_context->cert_transparency_verifier()->Verify(
+ envelope_->request_url().host(), verified_cert, stapled_ocsp_response,
+ sct_list_from_cert_cbor, &ct_verify_result->scts, net_log_);
+
+ net::ct::SCTList verified_scts = net::ct::SCTsMatchingStatus(
+ ct_verify_result->scts, net::ct::SCT_STATUS_OK);
+
+ ct_verify_result->policy_compliance =
+ request_context->ct_policy_enforcer()->CheckCompliance(
+ verified_cert, verified_scts, net_log_);
+
+ // TODO(https://crbug.com/803774): We should determine whether EV & SXG
+ // should be a thing (due to the online/offline signing difference)
+ if (cert_verify_result_.cert_status & net::CERT_STATUS_IS_EV &&
+ ct_verify_result->policy_compliance !=
+ net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS &&
+ ct_verify_result->policy_compliance !=
+ net::ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) {
+ cert_verify_result_.cert_status |= net::CERT_STATUS_CT_COMPLIANCE_FAILED;
+ cert_verify_result_.cert_status &= ~net::CERT_STATUS_IS_EV;
+ }
+
+ net::TransportSecurityState::CTRequirementsStatus ct_requirement_status =
+ request_context->transport_security_state()->CheckCTRequirements(
+ net::HostPortPair::FromURL(envelope_->request_url()),
+ cert_verify_result_.is_issued_by_known_root,
+ cert_verify_result_.public_key_hashes, verified_cert,
+ unverified_cert_chain_->cert().get(), ct_verify_result->scts,
+ net::TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
+ ct_verify_result->policy_compliance);
+
+ switch (ct_requirement_status) {
+ case net::TransportSecurityState::CT_REQUIREMENTS_NOT_MET:
+ return net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
+ case net::TransportSecurityState::CT_REQUIREMENTS_MET:
+ ct_verify_result->policy_compliance_required = true;
+ break;
+ case net::TransportSecurityState::CT_NOT_REQUIRED:
+ // CT is not required if the certificate does not chain to a publicly
+ // trusted root certificate.
+ if (!cert_verify_result_.is_issued_by_known_root) {
+ ct_verify_result->policy_compliance_required = false;
+ break;
+ }
+ // For old certificates (issued before 2018-05-01), CheckCTRequirements()
+ // may return CT_NOT_REQUIRED, so we check the compliance status here.
+ // TODO(https://crbug.com/851778): Remove this condition once we require
+ // signing certificates to have CanSignHttpExchanges extension, because
+ // such certificates should be naturally after 2018-05-01.
+ if (ct_verify_result->policy_compliance ==
+ net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS ||
+ ct_verify_result->policy_compliance ==
+ net::ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) {
+ ct_verify_result->policy_compliance_required = true;
+ break;
+ }
+ // Require CT compliance, by overriding CT_NOT_REQUIRED and treat it as
+ // ERR_CERTIFICATE_TRANSPARENCY_REQUIRED.
+ return net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
+ }
+ return net::OK;
+}
+
void SignedExchangeHandler::OnCertVerifyComplete(int result) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::OnCertVerifyComplete");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeHandler::OnCertVerifyComplete");
if (result != net::OK) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_.get(), "SignedExchangeHandler::OnCertVerifyComplete",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(),
base::StringPrintf("Certificate verification error: %s",
- net::ErrorToShortString(result).c_str()));
+ net::ErrorToShortString(result).c_str()),
+ std::make_pair(0 /* signature_index */,
+ SignedExchangeError::Field::kSignatureCertUrl));
+ RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ return;
+ }
+
+ if (!CheckCertExtension(cert_verify_result_.verified_cert.get())) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(),
+ "Certificate must have CanSignHttpExchangesDraft extension. To ignore "
+ "this error for testing, enable "
+ "chrome://flags/#allow-sxg-certs-without-extension.",
+ std::make_pair(0 /* signature_index */,
+ SignedExchangeError::Field::kSignatureCertUrl));
RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
if (!CheckOCSPStatus(cert_verify_result_.ocsp_result)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_.get(), "SignedExchangeHandler::OnCertVerifyComplete",
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(),
base::StringPrintf(
"OCSP check failed. response status: %d, revocation status: %d",
cert_verify_result_.ocsp_result.response_status,
- cert_verify_result_.ocsp_result.revocation_status));
- RunErrorCallback(static_cast<net::Error>(net::ERR_FAILED));
+ cert_verify_result_.ocsp_result.revocation_status),
+ std::make_pair(0 /* signature_index */,
+ SignedExchangeError::Field::kSignatureCertUrl));
+ RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ return;
+ }
+
+ net::ct::CTVerifyResult ct_verify_result;
+ int ct_result = VerifyCT(&ct_verify_result);
+ if (ct_result != net::OK) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(),
+ base::StringPrintf(
+ "CT verification failed. result: %s, policy compliance: %d",
+ net::ErrorToShortString(ct_result).c_str(),
+ ct_verify_result.policy_compliance),
+ std::make_pair(0 /* signature_index */,
+ SignedExchangeError::Field::kSignatureCertUrl));
+ RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
network::ResourceResponseHead response_head;
- response_head.headers = header_->BuildHttpResponseHeaders();
+ response_head.headers = envelope_->BuildHttpResponseHeaders();
response_head.headers->GetMimeTypeAndCharset(&response_head.mime_type,
&response_head.charset);
@@ -385,9 +523,8 @@ void SignedExchangeHandler::OnCertVerifyComplete(int result) {
std::string mi_header_value;
if (!response_head.headers->EnumerateHeader(nullptr, kMiHeader,
&mi_header_value)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy_.get(), "SignedExchangeHandler::OnCertVerifyComplete",
- "Signed exchange has no MI: header");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy_.get(), "Signed exchange has no MI-Draft2: header");
RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
@@ -405,18 +542,18 @@ void SignedExchangeHandler::OnCertVerifyComplete(int result) {
ssl_info.is_fatal_cert_error =
net::IsCertStatusError(ssl_info.cert_status) &&
!net::IsCertStatusMinorError(ssl_info.cert_status);
+ ssl_info.UpdateCertificateTransparencyInfo(ct_verify_result);
- if (devtools_proxy_)
- devtools_proxy_->OnSignedExchangeReceived(header_, &ssl_info);
+ if (devtools_proxy_) {
+ devtools_proxy_->OnSignedExchangeReceived(
+ envelope_, unverified_cert_chain_->cert(), &ssl_info);
+ }
response_head.ssl_info = std::move(ssl_info);
- // TODO(https://crbug.com/815025): Verify the Certificate Transparency status.
std::move(headers_callback_)
- .Run(net::OK, header_->request_url(), header_->request_method(),
+ .Run(net::OK, envelope_->request_url(), envelope_->request_method(),
response_head, std::move(mi_stream));
state_ = State::kHeadersCallbackCalled;
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::OnCertVerifyComplete");
}
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_handler.h b/chromium/content/browser/web_package/signed_exchange_handler.h
index d1df8d39d5b..b2ded77ac04 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler.h
+++ b/chromium/content/browser/web_package/signed_exchange_handler.h
@@ -11,7 +11,8 @@
#include "base/optional.h"
#include "base/time/time.h"
#include "content/browser/web_package/signed_exchange_consts.h"
-#include "content/browser/web_package/signed_exchange_header.h"
+#include "content/browser/web_package/signed_exchange_envelope.h"
+#include "content/browser/web_package/signed_exchange_prologue.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/completion_callback.h"
@@ -71,6 +72,7 @@ class CONTENT_EXPORT SignedExchangeHandler {
std::unique_ptr<net::SourceStream> body,
ExchangeHeadersCallback headers_callback,
std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory,
+ int load_flags,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy);
~SignedExchangeHandler();
@@ -80,7 +82,7 @@ class CONTENT_EXPORT SignedExchangeHandler {
private:
enum class State {
- kReadingHeadersLength,
+ kReadingPrologue,
kReadingHeaders,
kFetchingCertificate,
kHeadersCallbackCalled,
@@ -89,30 +91,32 @@ class CONTENT_EXPORT SignedExchangeHandler {
void SetupBuffers(size_t size);
void DoHeaderLoop();
void DidReadHeader(bool completed_syncly, int result);
- bool ParseHeadersLength();
+ bool ParsePrologue();
bool ParseHeadersAndFetchCertificate();
void RunErrorCallback(net::Error);
void OnCertReceived(
std::unique_ptr<SignedExchangeCertificateChain> cert_chain);
void OnCertVerifyComplete(int result);
+ bool CheckCertExtension(const net::X509Certificate* verified_cert);
bool CheckOCSPStatus(const net::OCSPVerifyResult& ocsp_result);
+ int VerifyCT(net::ct::CTVerifyResult* ct_verify_result);
ExchangeHeadersCallback headers_callback_;
base::Optional<SignedExchangeVersion> version_;
std::unique_ptr<net::SourceStream> source_;
- State state_ = State::kReadingHeadersLength;
- // Buffer used for header reading.
+ State state_ = State::kReadingPrologue;
+ // Buffer used for prologue and envelope reading.
scoped_refptr<net::IOBuffer> header_buf_;
// Wrapper around |header_buf_| to progressively read fixed-size data.
scoped_refptr<net::DrainableIOBuffer> header_read_buf_;
- size_t headers_length_ = 0;
-
- base::Optional<SignedExchangeHeader> header_;
+ base::Optional<SignedExchangePrologue> prologue_;
+ base::Optional<SignedExchangeEnvelope> envelope_;
std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory_;
std::unique_ptr<SignedExchangeCertFetcher> cert_fetcher_;
+ const int load_flags_;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
diff --git a/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc b/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
index 46b4a38736b..54a648fc03b 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
@@ -4,6 +4,8 @@
#include "content/browser/web_package/signed_exchange_handler.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_path.h"
@@ -16,9 +18,13 @@
#include "content/public/common/content_features.h"
#include "content/public/common/content_paths.h"
#include "net/base/io_buffer.h"
+#include "net/base/load_flags.h"
#include "net/base/test_completion_callback.h"
+#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/ct_verifier.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/filter/mock_source_stream.h"
+#include "net/http/transport_security_state.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "net/url_request/url_request_test_util.h"
@@ -26,6 +32,7 @@
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
+using testing::ElementsAre;
using testing::Property;
using testing::Return;
using testing::SetArgPointee;
@@ -38,10 +45,15 @@ namespace {
const uint64_t kSignatureHeaderDate = 1520834000;
const int kOutputBufferSize = 4096;
+// "wildcard_example.org.public.pem.cbor" has these dummy data in "ocsp" and
+// "sct" fields.
+constexpr base::StringPiece kDummyOCSPDer = "OCSP";
+constexpr base::StringPiece kDummySCTList = "SCT";
+
std::string GetTestFileContents(base::StringPiece name) {
base::FilePath path;
base::PathService::Get(content::DIR_TEST_DATA, &path);
- path = path.AppendASCII("htxg").AppendASCII(name);
+ path = path.AppendASCII("sxg").AppendASCII(name);
std::string contents;
CHECK(base::ReadFileToString(path, &contents));
@@ -50,10 +62,13 @@ std::string GetTestFileContents(base::StringPiece name) {
scoped_refptr<net::X509Certificate> LoadCertificate(
const std::string& cert_file) {
+ base::FilePath dir_path;
+ base::PathService::Get(content::DIR_TEST_DATA, &dir_path);
+ dir_path = dir_path.AppendASCII("sxg");
+
base::ScopedAllowBlockingForTesting allow_io;
return net::CreateCertificateChainFromFile(
- net::GetTestCertsDirectory(), cert_file,
- net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
+ dir_path, cert_file, net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
}
class MockSignedExchangeCertFetcherFactory
@@ -88,15 +103,51 @@ class MockSignedExchangeCertFetcherFactory
class GMockCertVerifier : public net::CertVerifier {
public:
- MOCK_METHOD6(Verify,
+ // net::CompletionOnceCallback is move-only, which GMock does not support.
+ int Verify(const net::CertVerifier::RequestParams& params,
+ net::CRLSet* crl_set,
+ net::CertVerifyResult* verify_result,
+ net::CompletionOnceCallback callback,
+ std::unique_ptr<net::CertVerifier::Request>* out_req,
+ const net::NetLogWithSource& net_log) override {
+ return VerifyImpl(params, crl_set, verify_result, out_req, net_log);
+ }
+
+ MOCK_METHOD5(VerifyImpl,
int(const net::CertVerifier::RequestParams& params,
net::CRLSet* crl_set,
net::CertVerifyResult* verify_result,
- const net::CompletionCallback& callback,
std::unique_ptr<net::CertVerifier::Request>* out_req,
const net::NetLogWithSource& net_log));
};
+class MockCTVerifier : public net::CTVerifier {
+ public:
+ MOCK_METHOD6(Verify,
+ void(base::StringPiece hostname,
+ net::X509Certificate* cert,
+ base::StringPiece stapled_ocsp_response,
+ base::StringPiece sct_list_from_tls_extension,
+ net::SignedCertificateTimestampAndStatusList* output_scts,
+ const net::NetLogWithSource& net_log));
+ MOCK_METHOD1(SetObserver, void(CTVerifier::Observer*));
+ MOCK_CONST_METHOD0(GetObserver, CTVerifier::Observer*());
+};
+
+class MockCTPolicyEnforcer : public net::CTPolicyEnforcer {
+ public:
+ MOCK_METHOD3(
+ CheckCompliance,
+ net::ct::CTPolicyCompliance(net::X509Certificate* cert,
+ const net::ct::SCTList& verified_scts,
+ const net::NetLogWithSource& net_log));
+};
+
+// Matcher to compare two net::X509Certificates
+MATCHER_P(CertEqualsIncludingChain, cert, "") {
+ return arg->EqualsIncludingChain(cert.get());
+}
+
} // namespace
class SignedExchangeHandlerTest
@@ -104,10 +155,10 @@ class SignedExchangeHandlerTest
public:
SignedExchangeHandlerTest()
: request_initiator_(
- url::Origin::Create(GURL("https://htxg.example.com/test.htxg"))) {}
+ url::Origin::Create(GURL("https://sxg.example.com/test.sxg"))) {}
virtual std::string ContentType() {
- return "application/signed-exchange;v=b0";
+ return "application/signed-exchange;v=b1";
}
void SetUp() override {
@@ -116,20 +167,19 @@ class SignedExchangeHandlerTest
base::TimeDelta::FromSeconds(kSignatureHeaderDate));
feature_list_.InitAndEnableFeature(features::kSignedHTTPExchange);
- std::unique_ptr<net::MockSourceStream> source(new net::MockSourceStream());
- source->set_read_one_byte_at_a_time(true);
- source_ = source.get();
- auto cert_fetcher_factory =
+ source_stream_ = std::make_unique<net::MockSourceStream>();
+ source_stream_->set_read_one_byte_at_a_time(true);
+ source_ = source_stream_.get();
+ cert_fetcher_factory_ =
std::make_unique<MockSignedExchangeCertFetcherFactory>();
- mock_cert_fetcher_factory_ = cert_fetcher_factory.get();
- request_context_getter_ = new net::TestURLRequestContextGetter(
- scoped_task_environment_.GetMainThreadTaskRunner());
- handler_ = std::make_unique<SignedExchangeHandler>(
- ContentType(), std::move(source),
- base::BindOnce(&SignedExchangeHandlerTest::OnHeaderFound,
- base::Unretained(this)),
- std::move(cert_fetcher_factory), request_context_getter_,
- nullptr /* devtools_proxy */);
+ mock_cert_fetcher_factory_ = cert_fetcher_factory_.get();
+ mock_ct_policy_enforcer_ = std::make_unique<MockCTPolicyEnforcer>();
+
+ // Lets mock CT policy enforcer return CT_POLICY_COMPLIES_VIA_SCTS by
+ // default. This may be overridden by test cases.
+ EXPECT_CALL(*mock_ct_policy_enforcer_, CheckCompliance(_, _, _))
+ .WillRepeatedly(
+ Return(net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
}
void TearDown() override {
@@ -182,6 +232,30 @@ class SignedExchangeHandlerTest
return resource_response_;
}
+ // Creates a TestURLRequestContext that uses |mock_ct_policy_enforcer_|.
+ std::unique_ptr<net::TestURLRequestContext> CreateTestURLRequestContext() {
+ auto test_url_request_context =
+ std::make_unique<net::TestURLRequestContext>(
+ true /* delay_initialization */);
+ test_url_request_context->set_ct_policy_enforcer(
+ mock_ct_policy_enforcer_.get());
+ test_url_request_context->Init();
+ return test_url_request_context;
+ }
+
+ void CreateSignedExchangeHandler(
+ std::unique_ptr<net::TestURLRequestContext> context) {
+ request_context_getter_ = new net::TestURLRequestContextGetter(
+ scoped_task_environment_.GetMainThreadTaskRunner(), std::move(context));
+
+ handler_ = std::make_unique<SignedExchangeHandler>(
+ ContentType(), std::move(source_stream_),
+ base::BindOnce(&SignedExchangeHandlerTest::OnHeaderFound,
+ base::Unretained(this)),
+ std::move(cert_fetcher_factory_), net::LOAD_NORMAL,
+ request_context_getter_, nullptr /* devtools_proxy */);
+ }
+
void WaitForHeader() {
while (!read_header()) {
while (source_->awaiting_completion())
@@ -193,6 +267,7 @@ class SignedExchangeHandlerTest
protected:
MockSignedExchangeCertFetcherFactory* mock_cert_fetcher_factory_;
std::unique_ptr<net::CertVerifier> cert_verifier_;
+ std::unique_ptr<MockCTPolicyEnforcer> mock_ct_policy_enforcer_;
net::MockSourceStream* source_;
std::unique_ptr<SignedExchangeHandler> handler_;
@@ -212,6 +287,8 @@ class SignedExchangeHandlerTest
base::test::ScopedTaskEnvironment scoped_task_environment_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
const url::Origin request_initiator_;
+ std::unique_ptr<net::MockSourceStream> source_stream_;
+ std::unique_ptr<MockSignedExchangeCertFetcherFactory> cert_fetcher_factory_;
bool read_header_ = false;
net::Error error_;
@@ -219,15 +296,10 @@ class SignedExchangeHandlerTest
std::unique_ptr<net::SourceStream> payload_stream_;
};
-class SignedExchangeHandlerB1Test : public SignedExchangeHandlerTest {
- std::string ContentType() override {
- return "application/signed-exchange;v=b1";
- }
-};
-
TEST_P(SignedExchangeHandlerTest, Empty) {
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
@@ -237,24 +309,27 @@ TEST_P(SignedExchangeHandlerTest, Empty) {
TEST_P(SignedExchangeHandlerTest, Simple) {
mock_cert_fetcher_factory_->ExpectFetch(
GURL("https://cert.example.org/cert.msg"),
- GetTestFileContents("wildcard_example.org.public.pem.msg"));
+ GetTestFileContents("test.example.org.public.pem.cbor"));
- // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
- // "*.example.org".
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("wildcard.pem");
+ LoadCertificate("prime256v1-sha256.public.pem");
net::CertVerifyResult dummy_result;
dummy_result.verified_cert = original_cert;
dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
- mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
dummy_result, net::OK);
SetCertVerifier(std::move(mock_cert_verifier));
- std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
@@ -280,16 +355,27 @@ TEST_P(SignedExchangeHandlerTest, Simple) {
TEST_P(SignedExchangeHandlerTest, MimeType) {
mock_cert_fetcher_factory_->ExpectFetch(
GURL("https://cert.example.org/cert.msg"),
- GetTestFileContents("wildcard_example.org.public.pem.msg"));
+ GetTestFileContents("test.example.org.public.pem.cbor"));
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("prime256v1-sha256.public.pem");
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+ dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
- mock_cert_verifier->set_default_result(net::OK);
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
+ dummy_result, net::OK);
SetCertVerifier(std::move(mock_cert_verifier));
- std::string contents = GetTestFileContents("test.example.org_hello.txt.htxg");
+ std::string contents = GetTestFileContents("test.example.org_hello.txt.sxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
@@ -307,10 +393,12 @@ TEST_P(SignedExchangeHandlerTest, MimeType) {
EXPECT_EQ(rv, static_cast<int>(expected_payload.size()));
}
-TEST_P(SignedExchangeHandlerTest, ParseError) {
- const uint8_t data[] = {0x00, 0x00, 0x01, 0x00};
+TEST_P(SignedExchangeHandlerTest, HeaderParseError) {
+ const uint8_t data[] = {'s', 'x', 'g', '1', '-', 'b', '1', '\0',
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00};
source_->AddReadResult(reinterpret_cast<const char*>(data), sizeof(data),
net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
@@ -318,35 +406,42 @@ TEST_P(SignedExchangeHandlerTest, ParseError) {
}
TEST_P(SignedExchangeHandlerTest, TruncatedInHeader) {
- std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
contents.resize(30);
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
}
-TEST_P(SignedExchangeHandlerTest, CertSha256Mismatch) {
- // The certificate is for "127.0.0.1". And the SHA 256 hash of the certificate
- // is different from the certSha256 of the signature in the htxg file. So the
- // certification verification must fail.
+TEST_P(SignedExchangeHandlerTest, CertWithoutExtensionShouldBeRejected) {
mock_cert_fetcher_factory_->ExpectFetch(
GURL("https://cert.example.org/cert.msg"),
- GetTestFileContents("127.0.0.1.public.pem.msg"));
+ GetTestFileContents("test.example.org-noext.public.pem.cbor"));
- // Set the default result of MockCertVerifier to OK, to check that the
- // verification of SignedExchange must fail even if the certificate is valid.
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("prime256v1-sha256-noext.public.pem");
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+ dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
- mock_cert_verifier->set_default_result(net::OK);
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
+ dummy_result, net::OK);
SetCertVerifier(std::move(mock_cert_verifier));
- std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ std::string contents = GetTestFileContents("test.example.org_noext_test.sxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
@@ -355,31 +450,65 @@ TEST_P(SignedExchangeHandlerTest, CertSha256Mismatch) {
ReadStream(source_, nullptr);
}
-TEST_P(SignedExchangeHandlerTest, VerifyCertFailure) {
+TEST_P(SignedExchangeHandlerTest, CertWithoutExtensionAllowedByFeatureFlag) {
+ base::test::ScopedFeatureList scoped_feature_list_;
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAllowSignedHTTPExchangeCertsWithoutExtension);
+
mock_cert_fetcher_factory_->ExpectFetch(
GURL("https://cert.example.org/cert.msg"),
- GetTestFileContents("wildcard_example.org.public.pem.msg"));
+ GetTestFileContents("test.example.org-noext.public.pem.cbor"));
- // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
- // "*.example.org".
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("wildcard.pem");
+ LoadCertificate("prime256v1-sha256-noext.public.pem");
net::CertVerifyResult dummy_result;
dummy_result.verified_cert = original_cert;
dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
- mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
dummy_result, net::OK);
SetCertVerifier(std::move(mock_cert_verifier));
- // The certificate is for "*.example.com". But the request URL of the htxg
- // file is "https://test.example.com/test/". So the certification verification
- // must fail.
- std::string contents =
- GetTestFileContents("test.example.com_invalid_test.htxg");
+ std::string contents = GetTestFileContents("test.example.org_noext_test.sxg");
+ source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+ source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(net::OK, error());
+ std::string payload;
+ int rv = ReadPayloadStream(&payload);
+ std::string expected_payload = GetTestFileContents("test.html");
+
+ EXPECT_EQ(expected_payload, payload);
+ EXPECT_EQ(static_cast<int>(expected_payload.size()), rv);
+}
+
+TEST_P(SignedExchangeHandlerTest, CertSha256Mismatch) {
+ // The certificate is for "127.0.0.1". And the SHA 256 hash of the certificate
+ // is different from the cert-sha256 of the signature in the sxg file. So the
+ // certification verification must fail.
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("127.0.0.1.public.pem.cbor"));
+
+ // Set the default result of MockCertVerifier to OK, to check that the
+ // verification of SignedExchange must fail even if the certificate is valid.
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->set_default_result(net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
+
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
@@ -388,151 +517,143 @@ TEST_P(SignedExchangeHandlerTest, VerifyCertFailure) {
ReadStream(source_, nullptr);
}
-TEST_P(SignedExchangeHandlerB1Test, Simple) {
+TEST_P(SignedExchangeHandlerTest, VerifyCertFailure) {
mock_cert_fetcher_factory_->ExpectFetch(
GURL("https://cert.example.org/cert.msg"),
- GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+ GetTestFileContents("test.example.org.public.pem.cbor"));
- // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
- // "*.example.org".
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("wildcard.pem");
+ LoadCertificate("prime256v1-sha256.public.pem");
net::CertVerifyResult dummy_result;
dummy_result.verified_cert = original_cert;
dummy_result.cert_status = net::OK;
- dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
- dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
- mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
dummy_result, net::OK);
SetCertVerifier(std::move(mock_cert_verifier));
- std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ // The certificate is for "test.example.org". But the request URL of the sxg
+ // file is "https://test.example.com/test/". So the certification verification
+ // must fail.
+ std::string contents =
+ GetTestFileContents("test.example.com_invalid_test.sxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
- EXPECT_EQ(net::OK, error());
- EXPECT_EQ(200, resource_response().headers->response_code());
- EXPECT_EQ("text/html", resource_response().mime_type);
- EXPECT_EQ("utf-8", resource_response().charset);
- EXPECT_FALSE(resource_response().load_timing.request_start_time.is_null());
- EXPECT_FALSE(resource_response().load_timing.request_start.is_null());
- EXPECT_FALSE(resource_response().load_timing.send_start.is_null());
- EXPECT_FALSE(resource_response().load_timing.send_end.is_null());
- EXPECT_FALSE(resource_response().load_timing.receive_headers_end.is_null());
-
- std::string payload;
- int rv = ReadPayloadStream(&payload);
-
- std::string expected_payload = GetTestFileContents("test.html");
-
- EXPECT_EQ(payload, expected_payload);
- EXPECT_EQ(rv, static_cast<int>(expected_payload.size()));
+ EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ // Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
+ ReadStream(source_, nullptr);
}
-TEST_P(SignedExchangeHandlerB1Test, OCSPNotChecked) {
+TEST_P(SignedExchangeHandlerTest, OCSPNotChecked) {
mock_cert_fetcher_factory_->ExpectFetch(
GURL("https://cert.example.org/cert.msg"),
- GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+ GetTestFileContents("test.example.org.public.pem.cbor"));
- // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
- // "*.example.org".
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("wildcard.pem");
+ LoadCertificate("prime256v1-sha256.public.pem");
net::CertVerifyResult dummy_result;
dummy_result.verified_cert = original_cert;
dummy_result.cert_status = net::OK;
dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::NOT_CHECKED;
auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
- mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
dummy_result, net::OK);
SetCertVerifier(std::move(mock_cert_verifier));
- std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
- EXPECT_EQ(net::ERR_FAILED, error());
+ EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
-TEST_P(SignedExchangeHandlerB1Test, OCSPNotProvided) {
+TEST_P(SignedExchangeHandlerTest, OCSPNotProvided) {
mock_cert_fetcher_factory_->ExpectFetch(
GURL("https://cert.example.org/cert.msg"),
- GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+ GetTestFileContents("test.example.org.public.pem.cbor"));
- // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
- // "*.example.org".
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("wildcard.pem");
+ LoadCertificate("prime256v1-sha256.public.pem");
net::CertVerifyResult dummy_result;
dummy_result.verified_cert = original_cert;
dummy_result.cert_status = net::OK;
dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::MISSING;
auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
- mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
dummy_result, net::OK);
SetCertVerifier(std::move(mock_cert_verifier));
- std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
- EXPECT_EQ(net::ERR_FAILED, error());
+ EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
-TEST_P(SignedExchangeHandlerB1Test, OCSPInvalid) {
+TEST_P(SignedExchangeHandlerTest, OCSPInvalid) {
mock_cert_fetcher_factory_->ExpectFetch(
GURL("https://cert.example.org/cert.msg"),
- GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+ GetTestFileContents("test.example.org.public.pem.cbor"));
- // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
- // "*.example.org".
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("wildcard.pem");
+ LoadCertificate("prime256v1-sha256.public.pem");
net::CertVerifyResult dummy_result;
dummy_result.verified_cert = original_cert;
dummy_result.cert_status = net::OK;
dummy_result.ocsp_result.response_status =
net::OCSPVerifyResult::INVALID_DATE;
auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
- mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
dummy_result, net::OK);
SetCertVerifier(std::move(mock_cert_verifier));
- std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
- EXPECT_EQ(net::ERR_FAILED, error());
+ EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
-TEST_P(SignedExchangeHandlerB1Test, OCSPRevoked) {
+TEST_P(SignedExchangeHandlerTest, OCSPRevoked) {
mock_cert_fetcher_factory_->ExpectFetch(
GURL("https://cert.example.org/cert.msg"),
- GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+ GetTestFileContents("test.example.org.public.pem.cbor"));
- // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
- // "*.example.org".
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("wildcard.pem");
+ LoadCertificate("prime256v1-sha256.public.pem");
net::CertVerifyResult dummy_result;
dummy_result.verified_cert = original_cert;
dummy_result.cert_status = net::OK;
@@ -540,66 +661,262 @@ TEST_P(SignedExchangeHandlerB1Test, OCSPRevoked) {
dummy_result.ocsp_result.revocation_status =
net::OCSPRevocationStatus::REVOKED;
auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
- mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
dummy_result, net::OK);
SetCertVerifier(std::move(mock_cert_verifier));
- std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
WaitForHeader();
ASSERT_TRUE(read_header());
- EXPECT_EQ(net::ERR_FAILED, error());
+ EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
// Test that fetching a signed exchange properly extracts and
// attempts to verify both the certificate and the OCSP response.
-TEST_P(SignedExchangeHandlerB1Test, CertVerifierParams) {
+TEST_P(SignedExchangeHandlerTest, CertVerifierParams) {
mock_cert_fetcher_factory_->ExpectFetch(
GURL("https://cert.example.org/cert.msg"),
- GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+ GetTestFileContents("test.example.org.public.pem.cbor"));
scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("wildcard.pem");
+ LoadCertificate("prime256v1-sha256.public.pem");
net::CertVerifyResult fake_result;
fake_result.verified_cert = original_cert;
fake_result.cert_status = net::OK;
fake_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
fake_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
- // "wildcard_example.org.public.pem.cbor" has this dummy data instead of a
- // real OCSP response.
- constexpr base::StringPiece kExpectedOCSPDer = "OCSP";
-
std::unique_ptr<GMockCertVerifier> gmock_cert_verifier =
std::make_unique<GMockCertVerifier>();
EXPECT_CALL(
*gmock_cert_verifier,
- Verify(
+ VerifyImpl(
AllOf(Property(&net::CertVerifier::RequestParams::ocsp_response,
- kExpectedOCSPDer),
- Property(
- &net::CertVerifier::RequestParams::certificate,
- Truly([&original_cert](
- const scoped_refptr<net::X509Certificate>& cert) {
- return original_cert->EqualsIncludingChain(cert.get());
- })),
+ kDummyOCSPDer),
+ Property(&net::CertVerifier::RequestParams::certificate,
+ CertEqualsIncludingChain(original_cert)),
Property(&net::CertVerifier::RequestParams::hostname,
"test.example.org")),
- _ /* crl_set */, _ /* verify_result */, _ /* callback */,
- _ /* out_req */, _ /* net_log */
+ _ /* crl_set */, _ /* verify_result */, _ /* out_req */,
+ _ /* net_log */
))
.WillOnce(DoAll(SetArgPointee<2>(fake_result), Return(net::OK)));
SetCertVerifier(std::move(gmock_cert_verifier));
- std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(net::OK, error());
+ std::string payload;
+ int rv = ReadPayloadStream(&payload);
+ std::string expected_payload = GetTestFileContents("test.html");
+
+ EXPECT_EQ(expected_payload, payload);
+ EXPECT_EQ(static_cast<int>(expected_payload.size()), rv);
+}
+
+TEST_P(SignedExchangeHandlerTest, NotEnoughSCTsFromPubliclyTrustedCert) {
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("test.example.org.public.pem.cbor"));
+
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("prime256v1-sha256.public.pem");
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+ dummy_result.is_issued_by_known_root = true;
+ dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
+ dummy_result, net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
+
+ // Lets the mock CT policy enforcer return CT_POLICY_NOT_ENOUGH_SCTS.
+ EXPECT_CALL(*mock_ct_policy_enforcer_, CheckCompliance(_, _, _))
+ .WillOnce(Return(net::ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
+
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
+ source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+ source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ // Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
+ ReadStream(source_, nullptr);
+}
+
+TEST_P(SignedExchangeHandlerTest, CTRequirementsMetForPubliclyTrustedCert) {
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("test.example.org.public.pem.cbor"));
+
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("prime256v1-sha256.public.pem");
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+ dummy_result.is_issued_by_known_root = true;
+ dummy_result.cert_status = net::CERT_STATUS_IS_EV;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
+ dummy_result, net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
+
+ // The mock CT policy enforcer will return CT_POLICY_COMPLIES_VIA_SCTS, as
+ // configured in SetUp().
+
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
+ source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+ source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(net::OK, error());
+ // EV status should be preserved.
+ EXPECT_TRUE(resource_response().ssl_info->cert_status &
+ net::CERT_STATUS_IS_EV);
+ EXPECT_FALSE(resource_response().ssl_info->cert_status &
+ net::CERT_STATUS_CT_COMPLIANCE_FAILED);
+ EXPECT_TRUE(resource_response().ssl_info->ct_policy_compliance_required);
+ EXPECT_EQ(net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
+ resource_response().ssl_info->ct_policy_compliance);
+
+ std::string payload;
+ int rv = ReadPayloadStream(&payload);
+ std::string expected_payload = GetTestFileContents("test.html");
+ EXPECT_EQ(expected_payload, payload);
+ EXPECT_EQ(static_cast<int>(expected_payload.size()), rv);
+}
+
+TEST_P(SignedExchangeHandlerTest, CTNotRequiredForLocalAnchors) {
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("test.example.org.public.pem.cbor"));
+
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("prime256v1-sha256.public.pem");
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+
+ // Local anchor.
+ dummy_result.is_issued_by_known_root = false;
+
+ dummy_result.cert_status = net::CERT_STATUS_IS_EV;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
+ dummy_result, net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
+ // Lets the mock CT policy enforcer return CT_POLICY_NOT_ENOUGH_SCTS.
+ EXPECT_CALL(*mock_ct_policy_enforcer_, CheckCompliance(_, _, _))
+ .WillOnce(Return(net::ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
+
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
+ source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+ source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+ CreateSignedExchangeHandler(CreateTestURLRequestContext());
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(net::OK, error());
+ // EV status should be removed.
+ EXPECT_FALSE(resource_response().ssl_info->cert_status &
+ net::CERT_STATUS_IS_EV);
+ EXPECT_TRUE(resource_response().ssl_info->cert_status &
+ net::CERT_STATUS_CT_COMPLIANCE_FAILED);
+ EXPECT_FALSE(resource_response().ssl_info->ct_policy_compliance_required);
+ EXPECT_EQ(net::ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
+ resource_response().ssl_info->ct_policy_compliance);
+
+ std::string payload;
+ int rv = ReadPayloadStream(&payload);
+ std::string expected_payload = GetTestFileContents("test.html");
+ EXPECT_EQ(expected_payload, payload);
+ EXPECT_EQ(static_cast<int>(expected_payload.size()), rv);
+}
+
+// Test that SignedExchangeHandler calls CTVerifier and CTPolicyEnforcer
+// with appropriate arguments.
+TEST_P(SignedExchangeHandlerTest, CTVerifierParams) {
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("test.example.org.public.pem.cbor"));
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("prime256v1-sha256.public.pem");
+
+ net::SignedCertificateTimestampAndStatusList fake_sct_list;
+ auto good_sct = base::MakeRefCounted<net::ct::SignedCertificateTimestamp>();
+ fake_sct_list.emplace_back(good_sct, net::ct::SCT_STATUS_OK);
+ auto bad_sct = base::MakeRefCounted<net::ct::SignedCertificateTimestamp>();
+ fake_sct_list.emplace_back(bad_sct, net::ct::SCT_STATUS_INVALID_TIMESTAMP);
+
+ EXPECT_CALL(*mock_ct_policy_enforcer_,
+ CheckCompliance(CertEqualsIncludingChain(original_cert),
+ ElementsAre(good_sct), _ /* net_log */))
+ .WillOnce(
+ Return(net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
+
+ std::unique_ptr<MockCTVerifier> ct_verifier =
+ std::make_unique<MockCTVerifier>();
+ EXPECT_CALL(*ct_verifier,
+ Verify(base::StringPiece("test.example.org"),
+ CertEqualsIncludingChain(original_cert), kDummyOCSPDer,
+ kDummySCTList, _ /* output_scts */, _ /* net_log */))
+ .WillOnce(SetArgPointee<4>(fake_sct_list));
+
+ auto test_url_request_context = std::make_unique<net::TestURLRequestContext>(
+ true /* delay_initialization */);
+ test_url_request_context->set_ct_policy_enforcer(
+ mock_ct_policy_enforcer_.get());
+ test_url_request_context->set_cert_transparency_verifier(ct_verifier.get());
+ test_url_request_context->Init();
+
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+ dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "test.example.org",
+ dummy_result, net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
+
+ std::string contents = GetTestFileContents("test.example.org_test.sxg");
+ source_->AddReadResult(contents.data(), contents.size(), net::OK,
+ net::MockSourceStream::ASYNC);
+ source_->AddReadResult(nullptr, 0, net::OK, net::MockSourceStream::ASYNC);
+
+ CreateSignedExchangeHandler(std::move(test_url_request_context));
WaitForHeader();
ASSERT_TRUE(read_header());
@@ -617,9 +934,4 @@ INSTANTIATE_TEST_CASE_P(SignedExchangeHandlerTests,
::testing::Values(net::MockSourceStream::SYNC,
net::MockSourceStream::ASYNC));
-INSTANTIATE_TEST_CASE_P(SignedExchangeHandlerB1Tests,
- SignedExchangeHandlerB1Test,
- ::testing::Values(net::MockSourceStream::SYNC,
- net::MockSourceStream::ASYNC));
-
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_header_parser_unittest.cc b/chromium/content/browser/web_package/signed_exchange_header_parser_unittest.cc
deleted file mode 100644
index 32f912e9490..00000000000
--- a/chromium/content/browser/web_package/signed_exchange_header_parser_unittest.cc
+++ /dev/null
@@ -1,281 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/web_package/signed_exchange_header_parser.h"
-
-#include "base/callback.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class SignedExchangeHeaderParserTest : public ::testing::Test {
- protected:
- SignedExchangeHeaderParserTest() {}
-};
-
-TEST_F(SignedExchangeHeaderParserTest, ParseSignature) {
- const char hdr_string[] =
- "sig1;"
- " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
- "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;"
- " integrity=\"mi\";"
- " validityUrl=\"https://example.com/resource.validity.1511128380\";"
- " certUrl=\"https://example.com/oldcerts\";"
- " certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
- " date=1511128380; expires=1511733180,"
- "sig2;"
- " sig=*MEQCIGjZRqTRf9iKNkGFyzRMTFgwf/BrY2ZNIP/dykhUV0aYAiBTXg+8wujoT4n/W+"
- "cNgb7pGqQvIUGYZ8u8HZJ5YH26Qg;"
- " integrity=\"mi\";"
- " validityUrl=\"https://example.com/resource.validity.1511128380\";"
- " certUrl=\"https://example.com/newcerts\";"
- " certSha256=*J/lEm9kNRODdCmINbvitpvdYKNQ+YgBj99DlYp4fEXw;"
- " date=1511128380; expires=1511733180";
-
- const uint8_t decoded_sig1[] = {
- 0x30, 0x45, 0x02, 0x21, 0x00, 0xd7, 0x94, 0x8d, 0xa0, 0x37, 0x74, 0x4d,
- 0x06, 0x58, 0x05, 0x8a, 0xe4, 0x4d, 0x16, 0x96, 0x57, 0x70, 0x32, 0x1a,
- 0x52, 0x95, 0xfa, 0x1c, 0x81, 0x30, 0x71, 0x91, 0x1c, 0xd1, 0xc6, 0x58,
- 0x2c, 0x02, 0x20, 0x6b, 0xd0, 0xec, 0x54, 0xe3, 0x0c, 0xfa, 0x0e, 0x58,
- 0xa7, 0x01, 0x01, 0x74, 0x65, 0xb7, 0xb1, 0x2f, 0x9b, 0xbe, 0x79, 0x80,
- 0x24, 0x98, 0x92, 0x33, 0x08, 0x6e, 0x05, 0xda, 0xa9, 0xe5, 0x46};
- const net::SHA256HashValue decoded_cert_sha256_1 = {
- {0x5b, 0xbb, 0x81, 0xf7, 0xaf, 0x5d, 0x15, 0x6d, 0xcc, 0x6f, 0x96,
- 0x5e, 0x7c, 0xf4, 0xbd, 0x4e, 0xae, 0x59, 0x6c, 0x7e, 0x62, 0x4a,
- 0x63, 0x88, 0x2e, 0x98, 0xef, 0xda, 0xa1, 0x00, 0xae, 0x62}};
- const uint8_t decoded_sig2[] = {
- 0x30, 0x44, 0x02, 0x20, 0x68, 0xd9, 0x46, 0xa4, 0xd1, 0x7f, 0xd8, 0x8a,
- 0x36, 0x41, 0x85, 0xcb, 0x34, 0x4c, 0x4c, 0x58, 0x30, 0x7f, 0xf0, 0x6b,
- 0x63, 0x66, 0x4d, 0x20, 0xff, 0xdd, 0xca, 0x48, 0x54, 0x57, 0x46, 0x98,
- 0x02, 0x20, 0x53, 0x5e, 0x0f, 0xbc, 0xc2, 0xe8, 0xe8, 0x4f, 0x89, 0xff,
- 0x5b, 0xe7, 0x0d, 0x81, 0xbe, 0xe9, 0x1a, 0xa4, 0x2f, 0x21, 0x41, 0x98,
- 0x67, 0xcb, 0xbc, 0x1d, 0x92, 0x79, 0x60, 0x7d, 0xba, 0x42};
- const net::SHA256HashValue decoded_cert_sha256_2 = {
- {0x27, 0xf9, 0x44, 0x9b, 0xd9, 0x0d, 0x44, 0xe0, 0xdd, 0x0a, 0x62,
- 0x0d, 0x6e, 0xf8, 0xad, 0xa6, 0xf7, 0x58, 0x28, 0xd4, 0x3e, 0x62,
- 0x00, 0x63, 0xf7, 0xd0, 0xe5, 0x62, 0x9e, 0x1f, 0x11, 0x7c}};
-
- auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, nullptr /* devtools_proxy */);
- ASSERT_TRUE(signatures.has_value());
- ASSERT_EQ(signatures->size(), 2u);
-
- EXPECT_EQ(signatures->at(0).label, "sig1");
- EXPECT_EQ(signatures->at(0).sig,
- std::string(reinterpret_cast<const char*>(decoded_sig1),
- sizeof(decoded_sig1)));
- EXPECT_EQ(signatures->at(0).integrity, "mi");
- EXPECT_EQ(signatures->at(0).validity_url,
- "https://example.com/resource.validity.1511128380");
- EXPECT_EQ(signatures->at(0).cert_url, "https://example.com/oldcerts");
- EXPECT_EQ(signatures->at(0).cert_sha256, decoded_cert_sha256_1);
- EXPECT_EQ(signatures->at(0).date, 1511128380ul);
- EXPECT_EQ(signatures->at(0).expires, 1511733180ul);
-
- EXPECT_EQ(signatures->at(1).label, "sig2");
- EXPECT_EQ(signatures->at(1).sig,
- std::string(reinterpret_cast<const char*>(decoded_sig2),
- sizeof(decoded_sig2)));
- EXPECT_EQ(signatures->at(1).integrity, "mi");
- EXPECT_EQ(signatures->at(1).validity_url,
- "https://example.com/resource.validity.1511128380");
- EXPECT_EQ(signatures->at(1).cert_url, "https://example.com/newcerts");
- EXPECT_EQ(signatures->at(1).cert_sha256, decoded_cert_sha256_2);
- EXPECT_EQ(signatures->at(1).date, 1511128380ul);
- EXPECT_EQ(signatures->at(1).expires, 1511733180ul);
-}
-
-TEST_F(SignedExchangeHeaderParserTest, IncompleteSignature) {
- const char hdr_string[] =
- "sig1;"
- " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
- "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;"
- // no integrity= param
- " validityUrl=\"https://example.com/resource.validity.1511128380\";"
- " certUrl=\"https://example.com/oldcerts\";"
- " certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
- " date=1511128380; expires=1511733180";
- auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, nullptr /* devtools_proxy */);
- EXPECT_FALSE(signatures.has_value());
-}
-
-TEST_F(SignedExchangeHeaderParserTest, DuplicatedParam) {
- const char hdr_string[] =
- "sig1;"
- " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
- "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;"
- " integrity=\"mi\";"
- " validityUrl=\"https://example.com/resource.validity.1511128380\";"
- " certUrl=\"https://example.com/oldcerts\";"
- " certUrl=\"https://example.com/oldcerts\";"
- " certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
- " date=1511128380; expires=1511733180";
- auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, nullptr /* devtools_proxy */);
- EXPECT_FALSE(signatures.has_value());
-}
-
-TEST_F(SignedExchangeHeaderParserTest, InvalidCertURL) {
- const char hdr_string[] =
- "sig1;"
- " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
- "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;"
- " integrity=\"mi\";"
- " validityUrl=\"https://example.com/resource.validity.1511128380\";"
- " certUrl=\"https:://example.com/oldcerts\";"
- " certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
- " date=1511128380; expires=1511733180";
- auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, nullptr /* devtools_proxy */);
- EXPECT_FALSE(signatures.has_value());
-}
-
-TEST_F(SignedExchangeHeaderParserTest, CertURLWithFragment) {
- const char hdr_string[] =
- "sig1;"
- " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
- "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;"
- " integrity=\"mi\";"
- " validityUrl=\"https://example.com/resource.validity.1511128380\";"
- " certUrl=\"https://example.com/oldcerts#test\";"
- " certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
- " date=1511128380; expires=1511733180";
- auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, nullptr /* devtools_proxy */);
- EXPECT_FALSE(signatures.has_value());
-}
-
-TEST_F(SignedExchangeHeaderParserTest, RelativeCertURL) {
- const char hdr_string[] =
- "sig1;"
- " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
- "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;"
- " integrity=\"mi\";"
- " validityUrl=\"https://example.com/resource.validity.1511128380\";"
- " certUrl=\"oldcerts\";"
- " certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
- " date=1511128380; expires=1511733180";
- auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, nullptr /* devtools_proxy */);
- EXPECT_FALSE(signatures.has_value());
-}
-
-TEST_F(SignedExchangeHeaderParserTest, InvalidValidityUrl) {
- const char hdr_string[] =
- "sig1;"
- " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
- "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;"
- " integrity=\"mi\";"
- " validityUrl=\"https:://example.com/resource.validity.1511128380\";"
- " certUrl=\"https://example.com/oldcerts\";"
- " certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
- " date=1511128380; expires=1511733180";
- auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, nullptr /* devtools_proxy */);
- EXPECT_FALSE(signatures.has_value());
-}
-
-TEST_F(SignedExchangeHeaderParserTest, ValidityUrlWithFragment) {
- const char hdr_string[] =
- "sig1;"
- " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
- "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;"
- " integrity=\"mi\";"
- " validityUrl=\"https://example.com/resource.validity.1511128380#test\";"
- " certUrl=\"https://example.com/oldcerts\";"
- " certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
- " date=1511128380; expires=1511733180";
- auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, nullptr /* devtools_proxy */);
- EXPECT_FALSE(signatures.has_value());
-}
-
-TEST_F(SignedExchangeHeaderParserTest, RelativeValidityUrl) {
- const char hdr_string[] =
- "sig1;"
- " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
- "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;"
- " integrity=\"mi\";"
- " validityUrl=\"resource.validity.1511128380\";"
- " certUrl=\"https://example.com/oldcerts\";"
- " certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
- " date=1511128380; expires=1511733180";
- auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, nullptr /* devtools_proxy */);
- EXPECT_FALSE(signatures.has_value());
-}
-
-TEST_F(SignedExchangeHeaderParserTest, InvalidCertSHA256) {
- const char hdr_string[] =
- "sig1;"
- " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
- "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;"
- " integrity=\"mi\";"
- " validityUrl=\"https://example.com/resource.validity.1511128380\";"
- " certUrl=\"https://example.com/oldcerts\";"
- " certSha256=*W7uB969dFW3Mb5ZefPS9;"
- " date=1511128380; expires=1511733180";
- auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, nullptr /* devtools_proxy */);
- EXPECT_FALSE(signatures.has_value());
-}
-
-TEST_F(SignedExchangeHeaderParserTest, OpenQuoteAtEnd) {
- const char hdr_string[] = "sig1; sig=\"";
- auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, nullptr /* devtools_proxy */);
- EXPECT_FALSE(signatures.has_value());
-}
-
-TEST_F(SignedExchangeHeaderParserTest, VersionParam_None) {
- const char content_type[] = "application/signed-exchange";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_TRUE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
- content_type, &version));
- EXPECT_FALSE(version);
-}
-
-TEST_F(SignedExchangeHeaderParserTest, VersionParam_NoneWithSemicolon) {
- const char content_type[] = "application/signed-exchange;";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_FALSE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
- content_type, &version));
-}
-
-TEST_F(SignedExchangeHeaderParserTest, VersionParam_EmptyString) {
- const char content_type[] = "application/signed-exchange;v=";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_FALSE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
- content_type, &version));
-}
-
-TEST_F(SignedExchangeHeaderParserTest, VersionParam_Simple) {
- const char content_type[] = "application/signed-exchange;v=b0";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_TRUE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
- content_type, &version));
- ASSERT_TRUE(version);
- EXPECT_EQ(*version, SignedExchangeVersion::kB0);
-}
-
-TEST_F(SignedExchangeHeaderParserTest, VersionParam_SimpleWithSpace) {
- const char content_type[] = "application/signed-exchange; v=b1";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_TRUE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
- content_type, &version));
- ASSERT_TRUE(version);
- EXPECT_EQ(*version, SignedExchangeVersion::kB1);
-}
-
-TEST_F(SignedExchangeHeaderParserTest, VersionParam_SimpleWithDoublequotes) {
- const char content_type[] = "application/signed-exchange;v=\"b0\"";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_TRUE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
- content_type, &version));
- ASSERT_TRUE(version);
- EXPECT_EQ(*version, SignedExchangeVersion::kB0);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_header_unittest.cc b/chromium/content/browser/web_package/signed_exchange_header_unittest.cc
deleted file mode 100644
index 9c532156460..00000000000
--- a/chromium/content/browser/web_package/signed_exchange_header_unittest.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/web_package/signed_exchange_header.h"
-
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "components/cbor/cbor_values.h"
-#include "components/cbor/cbor_writer.h"
-#include "content/browser/web_package/signed_exchange_consts.h"
-#include "content/public/common/content_paths.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-const char kSignatureString[] =
- "sig1;"
- " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
- "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY;"
- " integrity=\"mi\";"
- " validityUrl=\"https://example.com/resource.validity.1511128380\";"
- " certUrl=\"https://example.com/oldcerts\";"
- " certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
- " date=1511128380; expires=1511733180";
-
-cbor::CBORValue CBORByteString(const char* str) {
- return cbor::CBORValue(str, cbor::CBORValue::Type::BYTE_STRING);
-}
-
-base::Optional<SignedExchangeHeader> GenerateHeaderAndParse(
- const std::map<const char*, const char*>& request_map,
- const std::map<const char*, const char*>& response_map) {
- cbor::CBORValue::MapValue request_cbor_map;
- cbor::CBORValue::MapValue response_cbor_map;
- for (auto& pair : request_map)
- request_cbor_map[CBORByteString(pair.first)] = CBORByteString(pair.second);
- for (auto& pair : response_map)
- response_cbor_map[CBORByteString(pair.first)] = CBORByteString(pair.second);
-
- cbor::CBORValue::ArrayValue array;
- array.push_back(cbor::CBORValue(std::move(request_cbor_map)));
- array.push_back(cbor::CBORValue(std::move(response_cbor_map)));
-
- auto serialized = cbor::CBORWriter::Write(cbor::CBORValue(std::move(array)));
- return SignedExchangeHeader::Parse(
- base::make_span(serialized->data(), serialized->size()),
- nullptr /* devtools_proxy */);
-}
-
-} // namespace
-
-TEST(SignedExchangeHeaderTest, ParseEncodedLength) {
- constexpr struct {
- uint8_t bytes[SignedExchangeHeader::kEncodedLengthInBytes];
- size_t expected;
- } kTestCases[] = {
- {{0x00, 0x00, 0x01}, 1u}, {{0x01, 0xe2, 0x40}, 123456u},
- };
-
- int test_element_index = 0;
- for (const auto& test_case : kTestCases) {
- SCOPED_TRACE(testing::Message() << "testing case " << test_element_index++);
- EXPECT_EQ(SignedExchangeHeader::ParseEncodedLength(test_case.bytes),
- test_case.expected);
- }
-}
-
-TEST(SignedExchangeHeaderTest, ParseGoldenFile) {
- base::FilePath test_htxg_path;
- base::PathService::Get(content::DIR_TEST_DATA, &test_htxg_path);
- test_htxg_path = test_htxg_path.AppendASCII("htxg").AppendASCII(
- "test.example.org_test.htxg");
-
- std::string contents;
- ASSERT_TRUE(base::ReadFileToString(test_htxg_path, &contents));
- auto* contents_bytes = reinterpret_cast<const uint8_t*>(contents.data());
-
- ASSERT_GT(contents.size(), SignedExchangeHeader::kEncodedLengthInBytes);
- size_t header_size = SignedExchangeHeader::ParseEncodedLength(base::make_span(
- contents_bytes, SignedExchangeHeader::kEncodedLengthInBytes));
- ASSERT_GT(contents.size(),
- SignedExchangeHeader::kEncodedLengthInBytes + header_size);
-
- const auto cbor_bytes = base::make_span<const uint8_t>(
- contents_bytes + SignedExchangeHeader::kEncodedLengthInBytes,
- header_size);
- const base::Optional<SignedExchangeHeader> header =
- SignedExchangeHeader::Parse(cbor_bytes, nullptr /* devtools_proxy */);
- ASSERT_TRUE(header.has_value());
- EXPECT_EQ(header->request_url(), GURL("https://test.example.org/test/"));
- EXPECT_EQ(header->request_method(), "GET");
- EXPECT_EQ(header->response_code(), static_cast<net::HttpStatusCode>(200u));
- EXPECT_EQ(header->response_headers().size(), 4u);
- EXPECT_EQ(header->response_headers().find("content-encoding")->second,
- "mi-sha256");
-}
-
-TEST(SignedExchangeHeaderTest, ValidHeader) {
- auto header = GenerateHeaderAndParse(
- {
- {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "GET"},
- },
- {
- {kStatusKey, "200"}, {kSignature, kSignatureString},
- });
- ASSERT_TRUE(header.has_value());
- EXPECT_EQ(header->request_url(), GURL("https://test.example.org/test/"));
- EXPECT_EQ(header->request_method(), "GET");
- EXPECT_EQ(header->response_code(), static_cast<net::HttpStatusCode>(200u));
- EXPECT_EQ(header->response_headers().size(), 1u);
-}
-
-TEST(SignedExchangeHeaderTest, UnsafeMethod) {
- auto header = GenerateHeaderAndParse(
- {
- {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "POST"},
- },
- {
- {kStatusKey, "200"}, {kSignature, kSignatureString},
- });
- ASSERT_FALSE(header.has_value());
-}
-
-TEST(SignedExchangeHeaderTest, InvalidURL) {
- auto header = GenerateHeaderAndParse(
- {
- {kUrlKey, "https:://test.example.org/test/"}, {kMethodKey, "GET"},
- },
- {
- {kStatusKey, "200"}, {kSignature, kSignatureString},
- });
- ASSERT_FALSE(header.has_value());
-}
-
-TEST(SignedExchangeHeaderTest, URLWithFragment) {
- auto header = GenerateHeaderAndParse(
- {
- {kUrlKey, "https://test.example.org/test/#foo"}, {kMethodKey, "GET"},
- },
- {
- {kStatusKey, "200"}, {kSignature, kSignatureString},
- });
- ASSERT_FALSE(header.has_value());
-}
-
-TEST(SignedExchangeHeaderTest, RelativeURL) {
- auto header = GenerateHeaderAndParse(
- {
- {kUrlKey, "test/"}, {kMethodKey, "GET"},
- },
- {
- {kStatusKey, "200"}, {kSignature, kSignatureString},
- });
- ASSERT_FALSE(header.has_value());
-}
-
-TEST(SignedExchangeHeaderTest, StatefulRequestHeader) {
- auto header = GenerateHeaderAndParse(
- {
- {kUrlKey, "https://test.example.org/test/"},
- {kMethodKey, "GET"},
- {"authorization", "Basic Zm9vOmJhcg=="},
- },
- {
- {kStatusKey, "200"}, {kSignature, kSignatureString},
- });
- ASSERT_FALSE(header.has_value());
-}
-
-TEST(SignedExchangeHeaderTest, StatefulResponseHeader) {
- auto header = GenerateHeaderAndParse(
- {
- {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "GET"},
- },
- {
- {kStatusKey, "200"},
- {kSignature, kSignatureString},
- {"set-cookie", "foo=bar"},
- });
- ASSERT_FALSE(header.has_value());
-}
-
-TEST(SignedExchangeHeaderTest, UppercaseRequestMap) {
- auto header = GenerateHeaderAndParse(
- {{kUrlKey, "https://test.example.org/test/"},
- {kMethodKey, "GET"},
- {"Accept-Language", "en-us"}},
- {
- {kStatusKey, "200"}, {kSignature, kSignatureString},
- });
- ASSERT_FALSE(header.has_value());
-}
-
-TEST(SignedExchangeHeaderTest, UppercaseResponseMap) {
- auto header = GenerateHeaderAndParse(
- {
- {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "GET"},
- },
- {{kStatusKey, "200"},
- {kSignature, kSignatureString},
- {"Content-Length", "123"}});
- ASSERT_FALSE(header.has_value());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/web_package/web_package_loader.cc b/chromium/content/browser/web_package/signed_exchange_loader.cc
index ecd1e160eb0..9ede996006a 100644
--- a/chromium/content/browser/web_package/web_package_loader.cc
+++ b/chromium/content/browser/web_package/signed_exchange_loader.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/web_package/web_package_loader.h"
+#include "content/browser/web_package/signed_exchange_loader.h"
#include <memory>
@@ -16,6 +16,8 @@
#include "content/browser/web_package/signed_exchange_handler.h"
#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/common/content_features.h"
+#include "content/public/common/origin_util.h"
+#include "net/base/net_errors.h"
#include "net/cert/cert_status_flags.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request_context_getter.h"
@@ -43,7 +45,7 @@ SignedExchangeHandlerFactory* g_signed_exchange_factory_for_testing_ = nullptr;
} // namespace
-class WebPackageLoader::ResponseTimingInfo {
+class SignedExchangeLoader::ResponseTimingInfo {
public:
explicit ResponseTimingInfo(const network::ResourceResponseHead& response)
: request_start_(response.request_start),
@@ -77,12 +79,15 @@ class WebPackageLoader::ResponseTimingInfo {
DISALLOW_COPY_AND_ASSIGN(ResponseTimingInfo);
};
-WebPackageLoader::WebPackageLoader(
+SignedExchangeLoader::SignedExchangeLoader(
+ const GURL& outer_request_url,
const network::ResourceResponseHead& outer_response,
network::mojom::URLLoaderClientPtr forwarding_client,
network::mojom::URLLoaderClientEndpointsPtr endpoints,
url::Origin request_initiator,
uint32_t url_loader_options,
+ int load_flags,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id,
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
@@ -94,6 +99,8 @@ WebPackageLoader::WebPackageLoader(
url_loader_client_binding_(this),
request_initiator_(request_initiator),
url_loader_options_(url_loader_options),
+ load_flags_(load_flags),
+ throttling_profile_id_(throttling_profile_id),
devtools_proxy_(std::move(devtools_proxy)),
url_loader_factory_(std::move(url_loader_factory)),
url_loader_throttles_getter_(std::move(url_loader_throttles_getter)),
@@ -101,6 +108,46 @@ WebPackageLoader::WebPackageLoader(
weak_factory_(this) {
DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#privacy-considerations
+ // This can be difficult to determine when the exchange is being loaded from
+ // local disk, but when the client itself requested the exchange over a
+ // network it SHOULD require TLS ([I-D.ietf-tls-tls13]) or a successor
+ // transport layer, and MUST NOT accept exchanges transferred over plain HTTP
+ // without TLS. [spec text]
+ if (!IsOriginSecure(outer_request_url)) {
+ devtools_proxy_->ReportError(
+ "Signed exchange response from non secure origin is not supported.",
+ base::nullopt /* error_field */);
+ // Calls OnSignedExchangeReceived() to show the outer response in DevTool's
+ // Network panel and the error message in the Preview panel.
+ devtools_proxy_->OnSignedExchangeReceived(base::nullopt /* header */,
+ nullptr /* certificate */,
+ nullptr /* ssl_info */);
+ // This will asynchronously delete |this|.
+ forwarding_client_->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_INVALID_SIGNED_EXCHANGE));
+ return;
+ }
+
+ // TODO(https://crbug.com/849935): Remove this once we have Network Service
+ // friendly cert, OCSP, and CT verification.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ devtools_proxy_->ReportError(
+ "Currently, signed exchange does not work when "
+ "chrome://flags/#network-service is enabled. "
+ "See http://crbug.com/849935 for details.",
+ base::nullopt /* error_field */);
+ // Calls OnSignedExchangeReceived() to show the outer response in DevTool's
+ // Network panel and the error message in the Preview panel.
+ devtools_proxy_->OnSignedExchangeReceived(base::nullopt /* header */,
+ nullptr /* certificate */,
+ nullptr /* ssl_info */);
+ // This will asynchronously delete |this|.
+ forwarding_client_->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_INVALID_SIGNED_EXCHANGE));
+ return;
+ }
+
// Can't use HttpResponseHeaders::GetMimeType() because SignedExchangeHandler
// checks "v=" parameter.
outer_response.headers->EnumerateHeader(nullptr, "content-type",
@@ -125,60 +172,53 @@ WebPackageLoader::WebPackageLoader(
pending_client_request_ = mojo::MakeRequest(&client_);
}
-WebPackageLoader::~WebPackageLoader() = default;
+SignedExchangeLoader::~SignedExchangeLoader() = default;
-void WebPackageLoader::OnReceiveResponse(
- const network::ResourceResponseHead& response_head,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
- // Must not be called because this WebPackageLoader and the client endpoints
- // were bound after OnReceiveResponse() is called.
+void SignedExchangeLoader::OnReceiveResponse(
+ const network::ResourceResponseHead& response_head) {
+ // Must not be called because this SignedExchangeLoader and the client
+ // endpoints were bound after OnReceiveResponse() is called.
NOTREACHED();
}
-void WebPackageLoader::OnReceiveRedirect(
+void SignedExchangeLoader::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head) {
- // Must not be called because this WebPackageLoader and the client endpoints
- // were bound after OnReceiveResponse() is called.
- NOTREACHED();
-}
-
-void WebPackageLoader::OnDataDownloaded(int64_t data_len,
- int64_t encoded_data_len) {
- // Must not be called because this WebPackageLoader and the client endpoints
- // were bound after OnReceiveResponse() is called.
+ // Must not be called because this SignedExchangeLoader and the client
+ // endpoints were bound after OnReceiveResponse() is called.
NOTREACHED();
}
-void WebPackageLoader::OnUploadProgress(int64_t current_position,
- int64_t total_size,
- OnUploadProgressCallback ack_callback) {
- // Must not be called because this WebPackageLoader and the client endpoints
- // were bound after OnReceiveResponse() is called.
+void SignedExchangeLoader::OnUploadProgress(
+ int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback ack_callback) {
+ // Must not be called because this SignedExchangeLoader and the client
+ // endpoints were bound after OnReceiveResponse() is called.
NOTREACHED();
}
-void WebPackageLoader::OnReceiveCachedMetadata(
+void SignedExchangeLoader::OnReceiveCachedMetadata(
const std::vector<uint8_t>& data) {
- // Curerntly CachedMetadata for WebPackage is not supported.
+ // Curerntly CachedMetadata for Signed Exchange is not supported.
NOTREACHED();
}
-void WebPackageLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
+void SignedExchangeLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
// TODO(https://crbug.com/803774): Implement this to progressively update the
// encoded data length in DevTools.
}
-void WebPackageLoader::OnStartLoadingResponseBody(
+void SignedExchangeLoader::OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) {
auto cert_fetcher_factory = SignedExchangeCertFetcherFactory::Create(
std::move(request_initiator_), std::move(url_loader_factory_),
- std::move(url_loader_throttles_getter_));
+ std::move(url_loader_throttles_getter_), throttling_profile_id_);
if (g_signed_exchange_factory_for_testing_) {
signed_exchange_handler_ = g_signed_exchange_factory_for_testing_->Create(
std::make_unique<DataPipeToSourceStream>(std::move(body)),
- base::BindOnce(&WebPackageLoader::OnHTTPExchangeFound,
+ base::BindOnce(&SignedExchangeLoader::OnHTTPExchangeFound,
weak_factory_.GetWeakPtr()),
std::move(cert_fetcher_factory));
return;
@@ -186,21 +226,23 @@ void WebPackageLoader::OnStartLoadingResponseBody(
signed_exchange_handler_ = std::make_unique<SignedExchangeHandler>(
content_type_, std::make_unique<DataPipeToSourceStream>(std::move(body)),
- base::BindOnce(&WebPackageLoader::OnHTTPExchangeFound,
+ base::BindOnce(&SignedExchangeLoader::OnHTTPExchangeFound,
weak_factory_.GetWeakPtr()),
- std::move(cert_fetcher_factory), std::move(request_context_getter_),
- std::move(devtools_proxy_));
+ std::move(cert_fetcher_factory), load_flags_,
+ std::move(request_context_getter_), std::move(devtools_proxy_));
}
-void WebPackageLoader::OnComplete(
+void SignedExchangeLoader::OnComplete(
const network::URLLoaderCompletionStatus& status) {}
-void WebPackageLoader::FollowRedirect(
+void SignedExchangeLoader::FollowRedirect(
+ const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
NOTREACHED();
}
-void WebPackageLoader::ProceedWithResponse() {
+void SignedExchangeLoader::ProceedWithResponse() {
// TODO(https://crbug.com/791049): Remove this when NetworkService is
// enabled by default.
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
@@ -211,27 +253,27 @@ void WebPackageLoader::ProceedWithResponse() {
client_->OnStartLoadingResponseBody(std::move(pending_body_consumer_));
}
-void WebPackageLoader::SetPriority(net::RequestPriority priority,
- int intra_priority_value) {
+void SignedExchangeLoader::SetPriority(net::RequestPriority priority,
+ int intra_priority_value) {
// TODO(https://crbug.com/803774): Implement this.
}
-void WebPackageLoader::PauseReadingBodyFromNet() {
+void SignedExchangeLoader::PauseReadingBodyFromNet() {
// TODO(https://crbug.com/803774): Implement this.
}
-void WebPackageLoader::ResumeReadingBodyFromNet() {
+void SignedExchangeLoader::ResumeReadingBodyFromNet() {
// TODO(https://crbug.com/803774): Implement this.
}
-void WebPackageLoader::ConnectToClient(
+void SignedExchangeLoader::ConnectToClient(
network::mojom::URLLoaderClientPtr client) {
DCHECK(pending_client_request_.is_pending());
mojo::FuseInterface(std::move(pending_client_request_),
client.PassInterface());
}
-void WebPackageLoader::OnHTTPExchangeFound(
+void SignedExchangeLoader::OnHTTPExchangeFound(
net::Error error,
const GURL& request_url,
const std::string& request_method,
@@ -263,10 +305,9 @@ void WebPackageLoader::OnHTTPExchangeFound(
network::mojom::kURLLoadOptionSendSSLInfoWithResponse)) {
network::ResourceResponseHead response_info = resource_response;
response_info.ssl_info = base::nullopt;
- client_->OnReceiveResponse(response_info, nullptr /* downloaded_file */);
+ client_->OnReceiveResponse(response_info);
} else {
- client_->OnReceiveResponse(resource_response,
- nullptr /* downloaded_file */);
+ client_->OnReceiveResponse(resource_response);
}
// Currently we always assume that we have body.
@@ -278,7 +319,7 @@ void WebPackageLoader::OnHTTPExchangeFound(
body_data_pipe_adapter_ = std::make_unique<SourceStreamToDataPipe>(
std::move(payload_stream), std::move(data_pipe.producer_handle),
- base::BindOnce(&WebPackageLoader::FinishReadingBody,
+ base::BindOnce(&SignedExchangeLoader::FinishReadingBody,
base::Unretained(this)));
if (url_loader_options_ &
@@ -292,7 +333,7 @@ void WebPackageLoader::OnHTTPExchangeFound(
client_->OnStartLoadingResponseBody(std::move(pending_body_consumer_));
}
-void WebPackageLoader::FinishReadingBody(int result) {
+void SignedExchangeLoader::FinishReadingBody(int result) {
// TODO(https://crbug.com/803774): Fill the data length information too.
network::URLLoaderCompletionStatus status;
status.error_code = result;
@@ -309,7 +350,7 @@ void WebPackageLoader::FinishReadingBody(int result) {
client_->OnComplete(status);
}
-void WebPackageLoader::SetSignedExchangeHandlerFactoryForTest(
+void SignedExchangeLoader::SetSignedExchangeHandlerFactoryForTest(
SignedExchangeHandlerFactory* factory) {
g_signed_exchange_factory_for_testing_ = factory;
}
diff --git a/chromium/content/browser/web_package/web_package_loader.h b/chromium/content/browser/web_package/signed_exchange_loader.h
index 0bafea07c9a..2ab0d3a1d66 100644
--- a/chromium/content/browser/web_package/web_package_loader.h
+++ b/chromium/content/browser/web_package/signed_exchange_loader.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_WEB_PACKAGE_WEB_PACKAGE_LOADER_H_
-#define CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_LOADER_H_
+#ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_LOADER_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_LOADER_H_
#include "base/callback.h"
#include "base/optional.h"
@@ -34,38 +34,39 @@ class SignedExchangeHandlerFactory;
class URLLoaderThrottle;
class SourceStreamToDataPipe;
-// WebPackageLoader handles an origin-signed HTTP exchange response. It is
-// created when a WebPackageRequestHandler recieves an origin-signed HTTP
+// SignedExchangeLoader handles an origin-signed HTTP exchange response. It is
+// created when a SignedExchangeRequestHandler recieves an origin-signed HTTP
// exchange response, and is owned by the handler until the StartLoaderCallback
-// of WebPackageRequestHandler::StartResponse is called. After that, it is
+// of SignedExchangeRequestHandler::StartResponse is called. After that, it is
// owned by the URLLoader mojo endpoint.
-class WebPackageLoader final : public network::mojom::URLLoaderClient,
- public network::mojom::URLLoader {
+class SignedExchangeLoader final : public network::mojom::URLLoaderClient,
+ public network::mojom::URLLoader {
public:
using URLLoaderThrottlesGetter = base::RepeatingCallback<
std::vector<std::unique_ptr<content::URLLoaderThrottle>>()>;
- WebPackageLoader(
+ SignedExchangeLoader(
+ const GURL& outer_request_url,
const network::ResourceResponseHead& outer_response,
network::mojom::URLLoaderClientPtr forwarding_client,
network::mojom::URLLoaderClientEndpointsPtr endpoints,
url::Origin request_initiator,
uint32_t url_loader_options,
+ int load_flags,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id,
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
scoped_refptr<net::URLRequestContextGetter> request_context_getter);
- ~WebPackageLoader() override;
+ ~SignedExchangeLoader() override;
// network::mojom::URLLoaderClient implementation
// Only OnStartLoadingResponseBody() and OnComplete() are called.
void OnReceiveResponse(
- const network::ResourceResponseHead& response_head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override;
+ const network::ResourceResponseHead& response_head) override;
void OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head) override;
- void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
@@ -76,7 +77,9 @@ class WebPackageLoader final : public network::mojom::URLLoaderClient,
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
// network::mojom::URLLoader implementation
- void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
@@ -133,6 +136,8 @@ class WebPackageLoader final : public network::mojom::URLLoaderClient,
url::Origin request_initiator_;
const uint32_t url_loader_options_;
+ const int load_flags_;
+ const base::Optional<base::UnguessableToken> throttling_profile_id_;
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
URLLoaderThrottlesGetter url_loader_throttles_getter_;
@@ -142,11 +147,11 @@ class WebPackageLoader final : public network::mojom::URLLoaderClient,
std::string content_type_;
- base::WeakPtrFactory<WebPackageLoader> weak_factory_;
+ base::WeakPtrFactory<SignedExchangeLoader> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(WebPackageLoader);
+ DISALLOW_COPY_AND_ASSIGN(SignedExchangeLoader);
};
} // namespace content
-#endif // CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_LOADER_H_
+#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_LOADER_H_
diff --git a/chromium/content/browser/web_package/web_package_prefetch_handler.cc b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc
index b8ced15cd0c..c28252bf4df 100644
--- a/chromium/content/browser/web_package/web_package_prefetch_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.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/web_package/web_package_prefetch_handler.h"
+#include "content/browser/web_package/signed_exchange_prefetch_handler.h"
#include "base/callback.h"
#include "base/feature_list.h"
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
+#include "content/browser/web_package/signed_exchange_loader.h"
#include "content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h"
-#include "content/browser/web_package/web_package_loader.h"
#include "content/public/common/content_features.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/url_request/url_request_context_getter.h"
@@ -18,9 +18,11 @@
namespace content {
-WebPackagePrefetchHandler::WebPackagePrefetchHandler(
+SignedExchangePrefetchHandler::SignedExchangePrefetchHandler(
base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
bool report_raw_headers,
+ int load_flags,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id,
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr network_loader,
network::mojom::URLLoaderClientRequest network_client_request,
@@ -46,9 +48,10 @@ WebPackagePrefetchHandler::WebPackagePrefetchHandler(
} else {
url_loader_factory = std::move(network_loader_factory);
}
- web_package_loader_ = std::make_unique<WebPackageLoader>(
- response, std::move(client), std::move(endpoints),
+ signed_exchange_loader_ = std::make_unique<SignedExchangeLoader>(
+ outer_request_url, response, std::move(client), std::move(endpoints),
std::move(request_initiator), network::mojom::kURLLoadOptionNone,
+ load_flags, throttling_profile_id,
std::make_unique<SignedExchangeDevToolsProxy>(
outer_request_url, response, std::move(frame_tree_node_id_getter),
base::nullopt /* devtools_navigation_token */, report_raw_headers),
@@ -56,60 +59,54 @@ WebPackagePrefetchHandler::WebPackagePrefetchHandler(
request_context_getter);
}
-WebPackagePrefetchHandler::~WebPackagePrefetchHandler() = default;
+SignedExchangePrefetchHandler::~SignedExchangePrefetchHandler() = default;
network::mojom::URLLoaderClientRequest
-WebPackagePrefetchHandler::FollowRedirect(
+SignedExchangePrefetchHandler::FollowRedirect(
network::mojom::URLLoaderRequest loader_request) {
- DCHECK(web_package_loader_);
+ DCHECK(signed_exchange_loader_);
network::mojom::URLLoaderClientPtr client;
auto pending_request = mojo::MakeRequest(&client);
- web_package_loader_->ConnectToClient(std::move(client));
- mojo::MakeStrongBinding(std::move(web_package_loader_),
+ signed_exchange_loader_->ConnectToClient(std::move(client));
+ mojo::MakeStrongBinding(std::move(signed_exchange_loader_),
std::move(loader_request));
return pending_request;
}
-void WebPackagePrefetchHandler::OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
+void SignedExchangePrefetchHandler::OnReceiveResponse(
+ const network::ResourceResponseHead& head) {
NOTREACHED();
}
-void WebPackagePrefetchHandler::OnReceiveRedirect(
+void SignedExchangePrefetchHandler::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) {
forwarding_client_->OnReceiveRedirect(redirect_info, head);
}
-void WebPackagePrefetchHandler::OnDataDownloaded(int64_t data_length,
- int64_t encoded_length) {
- NOTREACHED();
-}
-
-void WebPackagePrefetchHandler::OnUploadProgress(
+void SignedExchangePrefetchHandler::OnUploadProgress(
int64_t current_position,
int64_t total_size,
base::OnceCallback<void()> callback) {
NOTREACHED();
}
-void WebPackagePrefetchHandler::OnReceiveCachedMetadata(
+void SignedExchangePrefetchHandler::OnReceiveCachedMetadata(
const std::vector<uint8_t>& data) {
NOTREACHED();
}
-void WebPackagePrefetchHandler::OnTransferSizeUpdated(
+void SignedExchangePrefetchHandler::OnTransferSizeUpdated(
int32_t transfer_size_diff) {
NOTREACHED();
}
-void WebPackagePrefetchHandler::OnStartLoadingResponseBody(
+void SignedExchangePrefetchHandler::OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) {
NOTREACHED();
}
-void WebPackagePrefetchHandler::OnComplete(
+void SignedExchangePrefetchHandler::OnComplete(
const network::URLLoaderCompletionStatus& status) {
forwarding_client_->OnComplete(status);
}
diff --git a/chromium/content/browser/web_package/web_package_prefetch_handler.h b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.h
index f6fc27cbdca..0c3551f4108 100644
--- a/chromium/content/browser/web_package/web_package_prefetch_handler.h
+++ b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.h
@@ -2,11 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_PREFETCH_HANDLER_H_
-#define CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_PREFETCH_HANDLER_H_
+#ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PREFETCH_HANDLER_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PREFETCH_HANDLER_H_
#include "base/callback_forward.h"
#include "base/macros.h"
+#include "base/optional.h"
+#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/network/public/mojom/url_loader.mojom.h"
@@ -22,21 +24,24 @@ namespace content {
class ResourceContext;
class URLLoaderThrottle;
-class WebPackageLoader;
+class SignedExchangeLoader;
// Attached to each PrefetchURLLoader if the prefetch is for a signed exchange.
-class WebPackagePrefetchHandler final : public network::mojom::URLLoaderClient {
+class SignedExchangePrefetchHandler final
+ : public network::mojom::URLLoaderClient {
public:
using URLLoaderThrottlesGetter = base::RepeatingCallback<
std::vector<std::unique_ptr<content::URLLoaderThrottle>>()>;
// This takes |network_loader| and |network_client| to set up the
- // WebPackageLoader (so that the loader can load data from the network).
+ // SignedExchangeLoader (so that the loader can load data from the network).
// |forwarding_client| is a pointer to the downstream client (typically who
// creates this handler).
- WebPackagePrefetchHandler(
+ SignedExchangePrefetchHandler(
base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
bool report_raw_headers,
+ int load_flags,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id,
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr network_loader,
network::mojom::URLLoaderClientRequest network_client_request,
@@ -48,24 +53,21 @@ class WebPackagePrefetchHandler final : public network::mojom::URLLoaderClient {
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
network::mojom::URLLoaderClient* forwarding_client);
- ~WebPackagePrefetchHandler() override;
+ ~SignedExchangePrefetchHandler() override;
- // This connects |loader_request| to the WebPackageLoader, and returns the
+ // This connects |loader_request| to the SignedExchangeLoader, and returns the
// pending client request to the loader.
// The returned client request can be bound to the downstream client so that
- // they can start directly receiving upcalls from the WebPackageLoader.
+ // they can start directly receiving upcalls from the SignedExchangeLoader.
// After this point |this| can be destructed.
network::mojom::URLLoaderClientRequest FollowRedirect(
network::mojom::URLLoaderRequest loader_request);
private:
// network::mojom::URLLoaderClient overrides:
- void OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override;
+ void OnReceiveResponse(const network::ResourceResponseHead& head) override;
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) override;
- void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
base::OnceCallback<void()> callback) override;
@@ -77,13 +79,13 @@ class WebPackagePrefetchHandler final : public network::mojom::URLLoaderClient {
mojo::Binding<network::mojom::URLLoaderClient> loader_client_binding_;
- std::unique_ptr<WebPackageLoader> web_package_loader_;
+ std::unique_ptr<SignedExchangeLoader> signed_exchange_loader_;
network::mojom::URLLoaderClient* forwarding_client_;
- DISALLOW_COPY_AND_ASSIGN(WebPackagePrefetchHandler);
+ DISALLOW_COPY_AND_ASSIGN(SignedExchangePrefetchHandler);
};
} // namespace content
-#endif // CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_PREFETCH_HANDLER_H_
+#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PREFETCH_HANDLER_H_
diff --git a/chromium/content/browser/web_package/signed_exchange_prologue.cc b/chromium/content/browser/web_package/signed_exchange_prologue.cc
new file mode 100644
index 00000000000..8f45dc93d90
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_prologue.cc
@@ -0,0 +1,83 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_package/signed_exchange_prologue.h"
+
+#include "base/strings/stringprintf.h"
+#include "base/trace_event/trace_event.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
+
+namespace content {
+
+namespace {
+
+constexpr char kSignedExchangeMagic[] = "sxg1-b1";
+constexpr size_t kMaximumSignatureHeaderFieldLength = 16 * 1024;
+constexpr size_t kMaximumCBORHeaderLength = 512 * 1024;
+
+} // namespace
+
+constexpr size_t SignedExchangePrologue::kEncodedLengthInBytes;
+size_t SignedExchangePrologue::kEncodedPrologueInBytes =
+ sizeof(kSignedExchangeMagic) +
+ SignedExchangePrologue::kEncodedLengthInBytes * 2;
+
+// static
+size_t SignedExchangePrologue::ParseEncodedLength(
+ base::span<const uint8_t> input) {
+ DCHECK_EQ(input.size(), SignedExchangePrologue::kEncodedLengthInBytes);
+ return static_cast<size_t>(input[0]) << 16 |
+ static_cast<size_t>(input[1]) << 8 | static_cast<size_t>(input[2]);
+}
+
+// static
+base::Optional<SignedExchangePrologue> SignedExchangePrologue::Parse(
+ base::span<const uint8_t> input,
+ SignedExchangeDevToolsProxy* devtools_proxy) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangePrologue::Parse");
+
+ CHECK_EQ(input.size(), kEncodedPrologueInBytes);
+
+ const auto magic_string = input.subspan(0, sizeof(kSignedExchangeMagic));
+ const auto encoded_signature_header_field_length =
+ input.subspan(sizeof(kSignedExchangeMagic), kEncodedLengthInBytes);
+ const auto encoded_cbor_header_length =
+ input.subspan(sizeof(kSignedExchangeMagic) + kEncodedLengthInBytes,
+ kEncodedLengthInBytes);
+
+ if (memcmp(magic_string.data(), kSignedExchangeMagic,
+ sizeof(kSignedExchangeMagic)) != 0) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(devtools_proxy,
+ "Wrong magic string");
+ return base::nullopt;
+ }
+
+ size_t signature_header_field_length =
+ ParseEncodedLength(encoded_signature_header_field_length);
+ size_t cbor_header_length = ParseEncodedLength(encoded_cbor_header_length);
+
+ if (signature_header_field_length > kMaximumSignatureHeaderFieldLength) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
+ base::StringPrintf("Signature header field too long: %zu",
+ signature_header_field_length));
+ return base::nullopt;
+ }
+ if (cbor_header_length > kMaximumCBORHeaderLength) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
+ base::StringPrintf("CBOR header too long: %zu", cbor_header_length));
+ return base::nullopt;
+ }
+
+ return SignedExchangePrologue(signature_header_field_length,
+ cbor_header_length);
+}
+
+size_t SignedExchangePrologue::ComputeFollowingSectionsLength() const {
+ return signature_header_field_length_ + cbor_header_length_;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_prologue.h b/chromium/content/browser/web_package/signed_exchange_prologue.h
new file mode 100644
index 00000000000..2106d417e42
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_prologue.h
@@ -0,0 +1,74 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PROLOGUE_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PROLOGUE_H_
+
+#include <string>
+
+#include "base/containers/span.h"
+#include "base/gtest_prod_util.h"
+#include "base/optional.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class SignedExchangeDevToolsProxy;
+
+// SignedExchangePrologue maps to the first bytes of
+// the "application/signed-exchange" format.
+// SignedExchangePrologue derives the lengths of the variable-length sections
+// following the prologue bytes.
+class CONTENT_EXPORT SignedExchangePrologue {
+ public:
+ // Parse encoded length of the variable-length field in the signed exchange.
+ // Note: |input| must be pointing to a valid memory address that has at least
+ // |kEncodedLengthInBytes|.
+ static size_t ParseEncodedLength(base::span<const uint8_t> input);
+
+ // Size of the prologue bytes of the "application/signed-exchange" format
+ // which maps to this class.
+ static size_t kEncodedPrologueInBytes;
+
+ // Parses the first bytes of the "application/signed-exchange" format.
+ // |input| must be a valid span with length of kEncodedPrologueInBytes.
+ // If success, returns the result. Otherwise, returns nullopt and
+ // reports the error to |devtools_proxy|.
+ static base::Optional<SignedExchangePrologue> Parse(
+ base::span<const uint8_t> input,
+ SignedExchangeDevToolsProxy* devtools_proxy);
+
+ SignedExchangePrologue(size_t signature_header_field_length,
+ size_t cbor_header_length)
+ : signature_header_field_length_(signature_header_field_length),
+ cbor_header_length_(cbor_header_length) {}
+ SignedExchangePrologue(const SignedExchangePrologue&) = default;
+ ~SignedExchangePrologue() = default;
+
+ size_t signature_header_field_length() const {
+ return signature_header_field_length_;
+ }
+ size_t cbor_header_length() const { return cbor_header_length_; }
+
+ size_t ComputeFollowingSectionsLength() const;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(SignedExchangePrologueTest, ParseEncodedLength);
+
+ static constexpr size_t kEncodedLengthInBytes = 3;
+
+ // Corresponds to `sigLength` in the spec text.
+ // Encoded length of the Signature header field's value.
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange
+ size_t signature_header_field_length_;
+
+ // Corresponds to `headerLength` in the spec text.
+ // Length of the CBOR representation of the request and response headers.
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#application-signed-exchange
+ size_t cbor_header_length_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PROLOGUE_H_
diff --git a/chromium/content/browser/web_package/signed_exchange_prologue_unittest.cc b/chromium/content/browser/web_package/signed_exchange_prologue_unittest.cc
new file mode 100644
index 00000000000..befb942e039
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_prologue_unittest.cc
@@ -0,0 +1,63 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_package/signed_exchange_prologue.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+TEST(SignedExchangePrologueTest, ParseEncodedLength) {
+ constexpr struct {
+ uint8_t bytes[SignedExchangePrologue::kEncodedLengthInBytes];
+ size_t expected;
+ } kTestCases[] = {
+ {{0x00, 0x00, 0x01}, 1u}, {{0x01, 0xe2, 0x40}, 123456u},
+ };
+
+ int test_element_index = 0;
+ for (const auto& test_case : kTestCases) {
+ SCOPED_TRACE(testing::Message() << "testing case " << test_element_index++);
+ EXPECT_EQ(SignedExchangePrologue::ParseEncodedLength(test_case.bytes),
+ test_case.expected);
+ }
+}
+
+TEST(SignedExchangePrologueTest, Simple) {
+ uint8_t bytes[] = {'s', 'x', 'g', '1', '-', 'b', '1',
+ '\0', 0x00, 0x12, 0x34, 0x00, 0x23, 0x45};
+
+ auto prologue = SignedExchangePrologue::Parse(base::make_span(bytes),
+ nullptr /* devtools_proxy */);
+ EXPECT_TRUE(prologue);
+ EXPECT_EQ(0x1234u, prologue->signature_header_field_length());
+ EXPECT_EQ(0x2345u, prologue->cbor_header_length());
+ EXPECT_EQ(0x3579u, prologue->ComputeFollowingSectionsLength());
+}
+
+TEST(SignedExchangePrologueTest, WrongMagic) {
+ uint8_t bytes[] = {'s', 'x', 'g', '!', '-', 'b', '1',
+ '\0', 0x00, 0x12, 0x34, 0x00, 0x23, 0x45};
+
+ EXPECT_FALSE(SignedExchangePrologue::Parse(base::make_span(bytes),
+ nullptr /* devtools_proxy */));
+}
+
+TEST(SignedExchangePrologueTest, LongSignatureHeaderField) {
+ uint8_t bytes[] = {'s', 'x', 'g', '1', '-', 'b', '1',
+ '\0', 0xff, 0x12, 0x34, 0x00, 0x23, 0x45};
+
+ EXPECT_FALSE(SignedExchangePrologue::Parse(base::make_span(bytes),
+ nullptr /* devtools_proxy */));
+}
+
+TEST(SignedExchangePrologueTest, LongCBORHeader) {
+ uint8_t bytes[] = {'s', 'x', 'g', '1', '-', 'b', '1',
+ '\0', 0x00, 0x12, 0x34, 0xff, 0x23, 0x45};
+
+ EXPECT_FALSE(SignedExchangePrologue::Parse(base::make_span(bytes),
+ nullptr /* devtools_proxy */));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/web_package/web_package_request_handler.cc b/chromium/content/browser/web_package/signed_exchange_request_handler.cc
index f67d3068b54..e5d33126395 100644
--- a/chromium/content/browser/web_package/web_package_request_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_request_handler.cc
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/web_package/web_package_request_handler.h"
+#include "content/browser/web_package/signed_exchange_request_handler.h"
#include <memory>
#include "base/bind.h"
#include "base/feature_list.h"
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
+#include "content/browser/web_package/signed_exchange_loader.h"
#include "content/browser/web_package/signed_exchange_utils.h"
-#include "content/browser/web_package/web_package_loader.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/common/content_features.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -24,18 +24,20 @@
namespace content {
// static
-bool WebPackageRequestHandler::IsSupportedMimeType(
+bool SignedExchangeRequestHandler::IsSupportedMimeType(
const std::string& mime_type) {
return mime_type == "application/signed-exchange";
}
-WebPackageRequestHandler::WebPackageRequestHandler(
+SignedExchangeRequestHandler::SignedExchangeRequestHandler(
url::Origin request_initiator,
const GURL& url,
uint32_t url_loader_options,
int frame_tree_node_id,
const base::UnguessableToken& devtools_navigation_token,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id,
bool report_raw_headers,
+ int load_flags,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
scoped_refptr<net::URLRequestContextGetter> request_context_getter)
@@ -44,7 +46,9 @@ WebPackageRequestHandler::WebPackageRequestHandler(
url_loader_options_(url_loader_options),
frame_tree_node_id_(frame_tree_node_id),
devtools_navigation_token_(devtools_navigation_token),
+ throttling_profile_id_(throttling_profile_id),
report_raw_headers_(report_raw_headers),
+ load_flags_(load_flags),
url_loader_factory_(url_loader_factory),
url_loader_throttles_getter_(std::move(url_loader_throttles_getter)),
request_context_getter_(std::move(request_context_getter)),
@@ -52,9 +56,9 @@ WebPackageRequestHandler::WebPackageRequestHandler(
DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
}
-WebPackageRequestHandler::~WebPackageRequestHandler() = default;
+SignedExchangeRequestHandler::~SignedExchangeRequestHandler() = default;
-void WebPackageRequestHandler::MaybeCreateLoader(
+void SignedExchangeRequestHandler::MaybeCreateLoader(
const network::ResourceRequest& resource_request,
ResourceContext* resource_context,
LoaderCallback callback) {
@@ -62,16 +66,17 @@ void WebPackageRequestHandler::MaybeCreateLoader(
// ongoing matching SignedExchangeHandler which was created by a
// WebPackagePrefetcher.
- if (!web_package_loader_) {
+ if (!signed_exchange_loader_) {
std::move(callback).Run({});
return;
}
- std::move(callback).Run(base::BindOnce(
- &WebPackageRequestHandler::StartResponse, weak_factory_.GetWeakPtr()));
+ std::move(callback).Run(
+ base::BindOnce(&SignedExchangeRequestHandler::StartResponse,
+ weak_factory_.GetWeakPtr()));
}
-bool WebPackageRequestHandler::MaybeCreateLoaderForResponse(
+bool SignedExchangeRequestHandler::MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request,
@@ -87,11 +92,12 @@ bool WebPackageRequestHandler::MaybeCreateLoaderForResponse(
// TODO(https://crbug.com/803774): Consider creating a new ThrottlingURLLoader
// or reusing the existing ThrottlingURLLoader by reattaching URLLoaderClient,
// to support SafeBrowsing checking of the content of the WebPackage.
- web_package_loader_ = std::make_unique<WebPackageLoader>(
- response, std::move(client), url_loader->Unbind(),
- std::move(request_initiator_), url_loader_options_,
+ signed_exchange_loader_ = std::make_unique<SignedExchangeLoader>(
+ url_, response, std::move(client), url_loader->Unbind(),
+ std::move(request_initiator_), url_loader_options_, load_flags_,
+ throttling_profile_id_,
std::make_unique<SignedExchangeDevToolsProxy>(
- std::move(url_), response,
+ url_, response,
base::BindRepeating([](int id) { return id; }, frame_tree_node_id_),
std::move(devtools_navigation_token_), report_raw_headers_),
std::move(url_loader_factory_), std::move(url_loader_throttles_getter_),
@@ -99,11 +105,12 @@ bool WebPackageRequestHandler::MaybeCreateLoaderForResponse(
return true;
}
-void WebPackageRequestHandler::StartResponse(
+void SignedExchangeRequestHandler::StartResponse(
network::mojom::URLLoaderRequest request,
network::mojom::URLLoaderClientPtr client) {
- web_package_loader_->ConnectToClient(std::move(client));
- mojo::MakeStrongBinding(std::move(web_package_loader_), std::move(request));
+ signed_exchange_loader_->ConnectToClient(std::move(client));
+ mojo::MakeStrongBinding(std::move(signed_exchange_loader_),
+ std::move(request));
}
} // namespace content
diff --git a/chromium/content/browser/web_package/web_package_request_handler.h b/chromium/content/browser/web_package/signed_exchange_request_handler.h
index 40f75c63441..02fbd7af3d5 100644
--- a/chromium/content/browser/web_package/web_package_request_handler.h
+++ b/chromium/content/browser/web_package/signed_exchange_request_handler.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_WEB_PACKAGE_WEB_PACKAGE_REQUEST_HANDLER_H_
-#define CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_REQUEST_HANDLER_H_
+#ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_REQUEST_HANDLER_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_REQUEST_HANDLER_H_
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "base/unguessable_token.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/public/common/resource_type.h"
@@ -22,26 +23,28 @@ class SharedURLLoaderFactory;
namespace content {
class URLLoaderThrottle;
-class WebPackageLoader;
+class SignedExchangeLoader;
-class WebPackageRequestHandler final : public NavigationLoaderInterceptor {
+class SignedExchangeRequestHandler final : public NavigationLoaderInterceptor {
public:
using URLLoaderThrottlesGetter = base::RepeatingCallback<
std::vector<std::unique_ptr<content::URLLoaderThrottle>>()>;
static bool IsSupportedMimeType(const std::string& mime_type);
- WebPackageRequestHandler(
+ SignedExchangeRequestHandler(
url::Origin request_initiator,
const GURL& url,
uint32_t url_loader_options,
int frame_tree_node_id,
const base::UnguessableToken& devtools_navigation_token,
+ const base::Optional<base::UnguessableToken>& throttling_profile_id,
bool report_raw_headers,
+ int load_flags,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
scoped_refptr<net::URLRequestContextGetter> request_context_getter);
- ~WebPackageRequestHandler() override;
+ ~SignedExchangeRequestHandler() override;
// NavigationLoaderInterceptor implementation
void MaybeCreateLoader(const network::ResourceRequest& resource_request,
@@ -60,23 +63,25 @@ class WebPackageRequestHandler final : public NavigationLoaderInterceptor {
// Valid after MaybeCreateLoaderForResponse intercepts the request and until
// the loader is re-bound to the new client for the redirected request in
// StartResponse.
- std::unique_ptr<WebPackageLoader> web_package_loader_;
+ std::unique_ptr<SignedExchangeLoader> signed_exchange_loader_;
url::Origin request_initiator_;
GURL url_;
const uint32_t url_loader_options_;
const int frame_tree_node_id_;
base::Optional<const base::UnguessableToken> devtools_navigation_token_;
+ const base::Optional<base::UnguessableToken> throttling_profile_id_;
const bool report_raw_headers_;
+ const int load_flags_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
URLLoaderThrottlesGetter url_loader_throttles_getter_;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
- base::WeakPtrFactory<WebPackageRequestHandler> weak_factory_;
+ base::WeakPtrFactory<SignedExchangeRequestHandler> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(WebPackageRequestHandler);
+ DISALLOW_COPY_AND_ASSIGN(SignedExchangeRequestHandler);
};
} // namespace content
-#endif // CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_REQUEST_HANDLER_H_
+#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_REQUEST_HANDLER_H_
diff --git a/chromium/content/browser/web_package/web_package_request_handler_browsertest.cc b/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
index 993fb9234c6..a2251cab8ce 100644
--- a/chromium/content/browser/web_package/web_package_request_handler_browsertest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
@@ -4,6 +4,7 @@
#include "base/files/file_path.h"
#include "base/path_service.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
@@ -17,6 +18,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_features.h"
+#include "content/public/common/content_paths.h"
#include "content/public/common/page_type.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -27,6 +29,7 @@
#include "net/cert/cert_verify_result.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/test/cert_test_util.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/test_data_directory.h"
#include "net/test/url_request/url_request_mock_http_job.h"
@@ -41,15 +44,13 @@ namespace {
const uint64_t kSignatureHeaderDate = 1520834000; // 2018-03-12T05:53:20Z
-const char* kMockHeaderFileSuffix = ".mock-http-headers";
-
class NavigationFailureObserver : public WebContentsObserver {
public:
explicit NavigationFailureObserver(WebContents* web_contents)
: WebContentsObserver(web_contents) {}
~NavigationFailureObserver() override = default;
- void DidStartNavigation(content::NavigationHandle* handle) override {
+ void DidStartNavigation(NavigationHandle* handle) override {
auto throttle = std::make_unique<TestNavigationThrottle>(handle);
throttle->SetCallback(
TestNavigationThrottle::WILL_FAIL_REQUEST,
@@ -71,27 +72,22 @@ class NavigationFailureObserver : public WebContentsObserver {
} // namespace
-class WebPackageRequestHandlerBrowserTest
- : public ContentBrowserTest,
- public testing::WithParamInterface<bool> {
+class SignedExchangeRequestHandlerBrowserTest : public ContentBrowserTest {
public:
- WebPackageRequestHandlerBrowserTest()
- : mock_cert_verifier_(std::make_unique<net::MockCertVerifier>()){};
- ~WebPackageRequestHandlerBrowserTest() = default;
+ SignedExchangeRequestHandlerBrowserTest()
+ : mock_cert_verifier_(std::make_unique<net::MockCertVerifier>()) {
+ // This installs "root_ca_cert.pem" from which our test certificates are
+ // created. (Needed for the tests that use real certificate, i.e.
+ // RealCertVerifier)
+ net::EmbeddedTestServer::RegisterTestCerts();
+ }
void SetUp() override {
SignedExchangeHandler::SetCertVerifierForTesting(mock_cert_verifier_.get());
SignedExchangeHandler::SetVerificationTimeForTesting(
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(kSignatureHeaderDate));
-
- if (is_network_service_enabled()) {
- feature_list_.InitWithFeatures(
- {features::kSignedHTTPExchange, network::features::kNetworkService},
- {});
- } else {
- feature_list_.InitWithFeatures({features::kSignedHTTPExchange}, {});
- }
+ SetUpFeatures();
ContentBrowserTest::SetUp();
}
@@ -103,20 +99,28 @@ class WebPackageRequestHandlerBrowserTest
}
protected:
+ virtual void SetUpFeatures() {
+ feature_list_.InitWithFeatures({features::kSignedHTTPExchange},
+ {network::features::kNetworkService});
+ }
+
static scoped_refptr<net::X509Certificate> LoadCertificate(
const std::string& cert_file) {
base::ScopedAllowBlockingForTesting allow_io;
+ base::FilePath dir_path;
+ base::PathService::Get(content::DIR_TEST_DATA, &dir_path);
+ dir_path = dir_path.AppendASCII("sxg");
+
return net::CreateCertificateChainFromFile(
- net::GetTestCertsDirectory(), cert_file,
- net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
+ dir_path, cert_file, net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
}
void InstallUrlInterceptor(const GURL& url, const std::string& data_path) {
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
if (!interceptor_) {
interceptor_ =
- std::make_unique<content::URLLoaderInterceptor>(base::BindRepeating(
- &WebPackageRequestHandlerBrowserTest::OnInterceptCallback,
+ std::make_unique<URLLoaderInterceptor>(base::BindRepeating(
+ &SignedExchangeRequestHandlerBrowserTest::OnInterceptCallback,
base::Unretained(this)));
}
interceptor_data_path_map_[url] = data_path;
@@ -127,28 +131,10 @@ class WebPackageRequestHandlerBrowserTest
}
}
+ base::test::ScopedFeatureList feature_list_;
std::unique_ptr<net::MockCertVerifier> mock_cert_verifier_;
private:
- static std::string ReadFile(const std::string& data_path) {
- base::ScopedAllowBlockingForTesting allow_io;
- base::FilePath root_path;
- CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path));
- std::string contents;
- CHECK(base::ReadFileToString(root_path.AppendASCII(data_path), &contents));
- return contents;
- }
-
- static std::string ReadHeaderFile(const std::string& data_path) {
- std::string header_file_relative_path = data_path + kMockHeaderFileSuffix;
- base::ScopedAllowBlockingForTesting allow_io;
- base::FilePath root_path;
- CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path));
- if (!base::PathExists(root_path.AppendASCII(header_file_relative_path)))
- return "HTTP/1.0 200 OK\n";
- return ReadFile(header_file_relative_path);
- }
-
static void InstallMockInterceptors(const GURL& url,
const std::string& data_path) {
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
@@ -159,53 +145,58 @@ class WebPackageRequestHandlerBrowserTest
root_path.AppendASCII(data_path)));
}
- bool OnInterceptCallback(
- content::URLLoaderInterceptor::RequestParams* params) {
+ bool OnInterceptCallback(URLLoaderInterceptor::RequestParams* params) {
DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
const auto it = interceptor_data_path_map_.find(params->url_request.url);
if (it == interceptor_data_path_map_.end())
return false;
- content::URLLoaderInterceptor::WriteResponse(
- ReadHeaderFile(it->second), ReadFile(it->second), params->client.get());
+ URLLoaderInterceptor::WriteResponse(it->second, params->client.get());
return true;
}
- bool is_network_service_enabled() const { return GetParam(); }
-
- base::test::ScopedFeatureList feature_list_;
-
- std::unique_ptr<content::URLLoaderInterceptor> interceptor_;
+ std::unique_ptr<URLLoaderInterceptor> interceptor_;
std::map<GURL, std::string> interceptor_data_path_map_;
- DISALLOW_COPY_AND_ASSIGN(WebPackageRequestHandlerBrowserTest);
+ DISALLOW_COPY_AND_ASSIGN(SignedExchangeRequestHandlerBrowserTest);
};
-IN_PROC_BROWSER_TEST_P(WebPackageRequestHandlerBrowserTest, Simple) {
+class SignedExchangeRequestHandlerWithNetworkServiceBrowserTest
+ : public SignedExchangeRequestHandlerBrowserTest {
+ void SetUpFeatures() override {
+ feature_list_.InitWithFeatures(
+ {features::kSignedHTTPExchange, network::features::kNetworkService},
+ {});
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, Simple) {
InstallUrlInterceptor(
GURL("https://cert.example.org/cert.msg"),
- "content/test/data/htxg/wildcard_example.org.public.pem.msg");
+ "content/test/data/sxg/test.example.org.public.pem.cbor");
- // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
- // "*.example.org".
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("wildcard.pem");
+ LoadCertificate("prime256v1-sha256.public.pem");
net::CertVerifyResult dummy_result;
dummy_result.verified_cert = original_cert;
dummy_result.cert_status = net::OK;
- mock_cert_verifier_->AddResultForCertAndHost(original_cert, "*.example.org",
- dummy_result, net::OK);
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
+ mock_cert_verifier_->AddResultForCertAndHost(
+ original_cert, "test.example.org", dummy_result, net::OK);
embedded_test_server()->RegisterRequestMonitor(
base::BindRepeating([](const net::test_server::HttpRequest& request) {
- if (request.relative_url == "/htxg/test.example.org_test.htxg") {
+ if (request.relative_url == "/sxg/test.example.org_test.sxg") {
const auto& accept_value = request.headers.find("accept")->second;
EXPECT_THAT(accept_value,
- ::testing::HasSubstr("application/signed-exchange;v=b0"));
+ ::testing::HasSubstr("application/signed-exchange;v=b1"));
}
}));
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(embedded_test_server()->Start());
- GURL url = embedded_test_server()->GetURL("/htxg/test.example.org_test.htxg");
+ GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
base::string16 title = base::ASCIIToUTF16("https://test.example.org/test/");
TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), url);
@@ -218,8 +209,9 @@ IN_PROC_BROWSER_TEST_P(WebPackageRequestHandlerBrowserTest, Simple) {
SSLStatus::DISPLAYED_INSECURE_CONTENT));
ASSERT_TRUE(entry->GetSSL().certificate);
- // "wildcard_example.org.public.pem.msg" is generated from "wildcard.pem". So
- // the SHA256 of the certificates must match.
+ // "test.example.org.public.pem.cbor" is generated from
+ // "prime256v1-sha256.public.pem". So the SHA256 of the certificates must
+ // match.
const net::SHA256HashValue fingerprint =
net::X509Certificate::CalculateFingerprint256(
entry->GetSSL().certificate->cert_buffer());
@@ -229,53 +221,129 @@ IN_PROC_BROWSER_TEST_P(WebPackageRequestHandlerBrowserTest, Simple) {
EXPECT_EQ(original_fingerprint, fingerprint);
}
-IN_PROC_BROWSER_TEST_P(WebPackageRequestHandlerBrowserTest,
+IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
InvalidContentType) {
InstallUrlInterceptor(
GURL("https://cert.example.org/cert.msg"),
- "content/test/data/htxg/wildcard_example.org.public.pem.msg");
+ "content/test/data/sxg/test.example.org.public.pem.cbor");
- // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
- // "*.example.org".
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("wildcard.pem");
+ LoadCertificate("prime256v1-sha256.public.pem");
net::CertVerifyResult dummy_result;
dummy_result.verified_cert = original_cert;
dummy_result.cert_status = net::OK;
- mock_cert_verifier_->AddResultForCertAndHost(original_cert, "*.example.org",
- dummy_result, net::OK);
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
+ mock_cert_verifier_->AddResultForCertAndHost(
+ original_cert, "test.example.org", dummy_result, net::OK);
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL(
- "/htxg/test.example.org_test_invalid_content_type.htxg");
+ "/sxg/test.example.org_test_invalid_content_type.sxg");
NavigationFailureObserver failure_observer(shell()->web_contents());
NavigateToURL(shell(), url);
EXPECT_TRUE(failure_observer.did_fail());
NavigationEntry* entry =
shell()->web_contents()->GetController().GetVisibleEntry();
- EXPECT_EQ(content::PAGE_TYPE_ERROR, entry->GetPageType());
+ EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
}
-IN_PROC_BROWSER_TEST_P(WebPackageRequestHandlerBrowserTest, CertNotFound) {
+IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, CertNotFound) {
InstallUrlInterceptor(GURL("https://cert.example.org/cert.msg"),
- "content/test/data/htxg/404.msg");
+ "content/test/data/sxg/404.msg");
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(embedded_test_server()->Start());
- GURL url = embedded_test_server()->GetURL("/htxg/test.example.org_test.htxg");
+ GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
NavigationFailureObserver failure_observer(shell()->web_contents());
NavigateToURL(shell(), url);
EXPECT_TRUE(failure_observer.did_fail());
NavigationEntry* entry =
shell()->web_contents()->GetController().GetVisibleEntry();
- EXPECT_EQ(content::PAGE_TYPE_ERROR, entry->GetPageType());
+ EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
}
-INSTANTIATE_TEST_CASE_P(WebPackageRequestHandlerBrowserTest,
- WebPackageRequestHandlerBrowserTest,
- testing::Bool());
+IN_PROC_BROWSER_TEST_F(
+ SignedExchangeRequestHandlerWithNetworkServiceBrowserTest,
+ NetworkServiceEnabled) {
+ InstallUrlInterceptor(
+ GURL("https://test.example.org/cert.msg"),
+ "content/test/data/sxg/test.example.org.public.pem.cbor");
+
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("prime256v1-sha256.public.pem");
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+ dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
+ mock_cert_verifier_->AddResultForCertAndHost(
+ original_cert, "test.example.org", dummy_result, net::OK);
+
+ embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
+
+ NavigationFailureObserver failure_observer(shell()->web_contents());
+ NavigateToURL(shell(), url);
+ EXPECT_TRUE(failure_observer.did_fail());
+ NavigationEntry* entry =
+ shell()->web_contents()->GetController().GetVisibleEntry();
+ EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
+}
+
+IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
+ RealCertVerifier) {
+ InstallUrlInterceptor(
+ GURL("https://cert.example.org/cert.msg"),
+ "content/test/data/sxg/test.example.org.public.pem.cbor");
+
+ // Use "real" CertVerifier.
+ SignedExchangeHandler::SetCertVerifierForTesting(nullptr);
+
+ embedded_test_server()->RegisterRequestMonitor(
+ base::BindRepeating([](const net::test_server::HttpRequest& request) {
+ if (request.relative_url == "/sxg/test.example.org_test.sxg") {
+ const auto& accept_value = request.headers.find("accept")->second;
+ EXPECT_THAT(accept_value,
+ ::testing::HasSubstr("application/signed-exchange;v=b1"));
+ }
+ }));
+ embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
+
+ // "test.example.org_test.sxg" should pass CertVerifier::Verify() and then
+ // fail at SignedExchangeHandler::CheckOCSPStatus() because of the dummy OCSP
+ // response.
+ // TODO(https://crbug.com/815024): Make this test pass the OCSP check. We'll
+ // need to either generate an OCSP response on the fly, or override the OCSP
+ // verification time.
+ content::ConsoleObserverDelegate console_observer(shell()->web_contents(),
+ "*OCSP*");
+ shell()->web_contents()->SetDelegate(&console_observer);
+
+ NavigationFailureObserver failure_observer(shell()->web_contents());
+ NavigateToURL(shell(), url);
+ EXPECT_TRUE(failure_observer.did_fail());
+ NavigationEntry* entry =
+ shell()->web_contents()->GetController().GetVisibleEntry();
+ EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
+
+ // Verify that it failed at the OCSP check step.
+ // TODO(https://crbug.com/803774): Find a better way than matching against the
+ // error message. We can probably make DevToolsProxy derive some context from
+ // StoragePartition so that we can record and extract the detailed error
+ // status for testing via that.
+ EXPECT_TRUE(base::StartsWith(console_observer.message(), "OCSP check failed.",
+ base::CompareCase::SENSITIVE));
+}
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_header_parser.cc b/chromium/content/browser/web_package/signed_exchange_signature_header_field.cc
index 97cc0a4c7e3..b7bcef2acae 100644
--- a/chromium/content/browser/web_package/signed_exchange_header_parser.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_header_field.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/web_package/signed_exchange_header_parser.h"
+#include "content/browser/web_package/signed_exchange_signature_header_field.h"
#include <map>
#include "base/base64.h"
@@ -19,60 +19,51 @@ namespace content {
namespace {
-// This covers the characters allowed in Numbers, Labels, and Binary Content.
-constexpr char kTokenChars[] =
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_+-*/";
+// This covers the characters allowed in Integers and Identifiers.
+// https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-04#section-4.5
+// https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-04#section-4.8
+constexpr char kTokenChars[] = "0123456789abcdefghijklmnopqrstuvwxyz_-*/";
-struct ParameterisedLabel {
- std::string label;
+struct ParameterisedIdentifier {
+ std::string identifier;
std::map<std::string, std::string> params;
};
// Parser for (a subset of) Structured Headers defined in [SH].
-// [SH] https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-02
+// [SH] https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-04
class StructuredHeaderParser {
public:
explicit StructuredHeaderParser(const base::StringPiece& str)
: input_(str), failed_(false) {}
+ // Callers should call this after ParseSomething(), to check if parser has
+ // consumed all the input successfully.
bool ParsedSuccessfully() const { return !failed_ && input_.empty(); }
- // Parses a List ([SH] 4.8) of Strings.
- void ParseStringList(std::vector<std::string>* values) {
- values->push_back(ReadString());
+ // Parses a Parameterised List ([SH] 4.3).
+ void ParseParameterisedList(std::vector<ParameterisedIdentifier>* values) {
+ values->push_back(ParameterisedIdentifier());
+ ParseParameterisedIdentifier(&values->back());
while (!failed_) {
SkipWhitespaces();
if (!ConsumeChar(','))
break;
SkipWhitespaces();
- values->push_back(ReadString());
+ values->push_back(ParameterisedIdentifier());
+ ParseParameterisedIdentifier(&values->back());
}
}
- // Parses a List ([SH] 4.8) of Parameterised Labels.
- void ParseParameterisedLabelList(std::vector<ParameterisedLabel>* values) {
- values->push_back(ParameterisedLabel());
- ParseParameterisedLabel(&values->back());
- while (!failed_) {
- SkipWhitespaces();
- if (!ConsumeChar(','))
- break;
- SkipWhitespaces();
- values->push_back(ParameterisedLabel());
- ParseParameterisedLabel(&values->back());
- }
- }
-
- // Parses a Parameterised Label ([SH] 4.4).
- void ParseParameterisedLabel(ParameterisedLabel* out) {
- std::string label = ReadToken();
- if (label.empty()) {
- DVLOG(1) << "ParseParameterisedLabel: Label expected, got '"
+ // Parses a Parameterised Identifier ([SH] 4.3.2).
+ void ParseParameterisedIdentifier(ParameterisedIdentifier* out) {
+ std::string identifier = ReadToken();
+ if (identifier.empty()) {
+ DVLOG(1) << "ParseParameterisedIdentifier: Identifier expected, got '"
<< input_.front() << "'";
failed_ = true;
return;
}
- out->label = label;
+ out->identifier = identifier;
while (!failed_) {
SkipWhitespaces();
@@ -82,7 +73,7 @@ class StructuredHeaderParser {
std::string name = ReadToken();
if (name.empty()) {
- DVLOG(1) << "ParseParameterisedLabel: Label expected, got '"
+ DVLOG(1) << "ParseParameterisedIdentifier: Identifier expected, got '"
<< input_.front() << "'";
failed_ = true;
return;
@@ -91,7 +82,8 @@ class StructuredHeaderParser {
if (ConsumeChar('='))
value = ReadItem();
if (!out->params.insert(std::make_pair(name, value)).second) {
- DVLOG(1) << "ParseParameterisedLabel: duplicated parameter: " << name;
+ DVLOG(1) << "ParseParameterisedIdentifier: duplicated parameter: "
+ << name;
failed_ = true;
return;
}
@@ -120,7 +112,7 @@ class StructuredHeaderParser {
return false;
}
- // [SH] 4.2. Strings
+ // [SH] 4.7. Strings
std::string ReadString() {
std::string s;
if (!ConsumeChar('"')) {
@@ -150,25 +142,31 @@ class StructuredHeaderParser {
return s;
}
- // [SH] 4.5. Binary Content
+ // [SH] 4.9. Binary Content
std::string ReadBinary() {
if (!ConsumeChar('*')) {
DVLOG(1) << "ReadBinary: '*' expected, got '" << input_.front() << "'";
failed_ = true;
return std::string();
}
- std::string base64 = ReadToken();
- // Binary Content does not have padding, so we have to add it.
- base64.resize((base64.size() + 3) / 4 * 4, '=');
+ size_t len = input_.find('*');
+ if (len == base::StringPiece::npos) {
+ DVLOG(1) << "ReadBinary: missing closing '*'";
+ failed_ = true;
+ return std::string();
+ }
+ base::StringPiece base64 = input_.substr(0, len);
std::string binary;
if (!base::Base64Decode(base64, &binary)) {
DVLOG(1) << "ReadBinary: failed to decode base64: " << base64;
failed_ = true;
}
+ input_.remove_prefix(len);
+ ConsumeChar('*');
return binary;
}
- // [SH] 4.6. Items
+ // [SH] 4.4. Items
std::string ReadItem() {
if (input_.empty()) {
DVLOG(1) << "ReadItem: unexpected EOF";
@@ -180,7 +178,7 @@ class StructuredHeaderParser {
return ReadString();
case '*':
return ReadBinary();
- default: // label or number
+ default: // identifier or integer
return ReadToken();
}
}
@@ -192,20 +190,19 @@ class StructuredHeaderParser {
} // namespace
// static
-base::Optional<std::vector<SignedExchangeHeaderParser::Signature>>
-SignedExchangeHeaderParser::ParseSignature(
+base::Optional<std::vector<SignedExchangeSignatureHeaderField::Signature>>
+SignedExchangeSignatureHeaderField::ParseSignature(
base::StringPiece signature_str,
SignedExchangeDevToolsProxy* devtools_proxy) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHeaderParser::ParseSignature");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeSignatureHeaderField::ParseSignature");
StructuredHeaderParser parser(signature_str);
- std::vector<ParameterisedLabel> values;
- parser.ParseParameterisedLabelList(&values);
+ std::vector<ParameterisedIdentifier> values;
+ parser.ParseParameterisedList(&values);
if (!parser.ParsedSuccessfully()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
- "Failed to parse signature header.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Failed to parse signature header.");
return base::nullopt;
}
@@ -214,37 +211,38 @@ SignedExchangeHeaderParser::ParseSignature(
for (auto& value : values) {
signatures.push_back(Signature());
Signature& sig = signatures.back();
- sig.label = value.label;
+ sig.label = value.identifier;
sig.sig = value.params[kSig];
if (sig.sig.empty()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
- "'sig' parameter is not set,");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "'sig' parameter is not set,");
return base::nullopt;
}
sig.integrity = value.params[kIntegrity];
if (sig.integrity.empty()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
- "'integrity' parameter is not set.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "'integrity' parameter is not set.");
return base::nullopt;
}
sig.cert_url = GURL(value.params[kCertUrl]);
if (!sig.cert_url.is_valid() || sig.cert_url.has_ref()) {
// TODO(https://crbug.com/819467) : When we will support "ed25519Key", the
- // params may not have "certUrl".
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
- "'certUrl' parameter is not a valid URL.");
+ // params may not have "cert-url".
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "'cert-url' parameter is not a valid URL.");
+ return base::nullopt;
+ }
+ if (!sig.cert_url.SchemeIs("https") && !sig.cert_url.SchemeIs("data")) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "'cert-url' should have 'https' or 'data' scheme.");
return base::nullopt;
}
const std::string cert_sha256_string = value.params[kCertSha256Key];
if (cert_sha256_string.size() != crypto::kSHA256Length) {
// TODO(https://crbug.com/819467) : When we will support "ed25519Key", the
- // params may not have "certSha256".
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
- "'certSha256' parameter is not a SHA-256 digest.");
+ // params may not have "cert-sha256".
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "'cert-sha256' parameter is not a SHA-256 digest.");
return base::nullopt;
}
net::SHA256HashValue cert_sha256;
@@ -254,52 +252,49 @@ SignedExchangeHeaderParser::ParseSignature(
// sig.ed25519_key = value.params["ed25519Key"];
sig.validity_url = GURL(value.params[kValidityUrlKey]);
if (!sig.validity_url.is_valid()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
- "'validityUrl' parameter is not a valid URL.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "'validity-url' parameter is not a valid URL.");
return base::nullopt;
}
if (sig.validity_url.has_ref()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
- "'validityUrl' parameter can't have a fragment.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "'validity-url' parameter can't have a fragment.");
+ return base::nullopt;
+ }
+ if (!sig.validity_url.SchemeIs("https")) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "'validity-url' should have 'https' scheme.");
return base::nullopt;
}
if (!base::StringToUint64(value.params[kDateKey], &sig.date)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
- "'date' parameter is not a number.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "'date' parameter is not a number.");
return base::nullopt;
}
if (!base::StringToUint64(value.params[kExpiresKey], &sig.expires)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
- "'expires' parameter is not a number.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "'expires' parameter is not a number.");
return base::nullopt;
}
}
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHeaderParser::ParseSignature");
return signatures;
}
// static
-bool SignedExchangeHeaderParser::GetVersionParamFromContentType(
+bool SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
base::StringPiece content_type,
base::Optional<SignedExchangeVersion>* version_param) {
DCHECK(version_param);
StructuredHeaderParser parser(content_type);
- ParameterisedLabel parameterised_label;
- parser.ParseParameterisedLabel(&parameterised_label);
+ ParameterisedIdentifier parameterised_identifier;
+ parser.ParseParameterisedIdentifier(&parameterised_identifier);
if (!parser.ParsedSuccessfully())
return false;
- const auto it = parameterised_label.params.find("v");
- if (it == parameterised_label.params.end()) {
+ const auto it = parameterised_identifier.params.find("v");
+ if (it == parameterised_identifier.params.end()) {
*version_param = base::nullopt;
} else {
- if (it->second == "b0")
- *version_param = SignedExchangeVersion::kB0;
- else if (it->second == "b1")
+ if (it->second == "b1")
*version_param = SignedExchangeVersion::kB1;
else
return false;
@@ -307,9 +302,9 @@ bool SignedExchangeHeaderParser::GetVersionParamFromContentType(
return true;
}
-SignedExchangeHeaderParser::Signature::Signature() = default;
-SignedExchangeHeaderParser::Signature::Signature(const Signature& other) =
- default;
-SignedExchangeHeaderParser::Signature::~Signature() = default;
+SignedExchangeSignatureHeaderField::Signature::Signature() = default;
+SignedExchangeSignatureHeaderField::Signature::Signature(
+ const Signature& other) = default;
+SignedExchangeSignatureHeaderField::Signature::~Signature() = default;
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_header_parser.h b/chromium/content/browser/web_package/signed_exchange_signature_header_field.h
index 01697eb5362..166850ce21d 100644
--- a/chromium/content/browser/web_package/signed_exchange_header_parser.h
+++ b/chromium/content/browser/web_package/signed_exchange_signature_header_field.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_WEB_PACKAGE_SIGNED_EXCHANGE_HEADER_PARSER_H_
-#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_HEADER_PARSER_H_
+#ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_SIGNATURE_HEADER_FIELD_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_SIGNATURE_HEADER_FIELD_H_
#include <stdint.h>
#include <string>
@@ -22,9 +22,10 @@ namespace content {
class SignedExchangeDevToolsProxy;
-// Provide parsers for signed-exchange headers.
+// SignedExchangeSignatureHeaderField provides parser for signed exchange's
+// `Signature` header field.
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html
-class CONTENT_EXPORT SignedExchangeHeaderParser {
+class CONTENT_EXPORT SignedExchangeSignatureHeaderField {
public:
struct CONTENT_EXPORT Signature {
Signature();
@@ -49,6 +50,7 @@ class CONTENT_EXPORT SignedExchangeHeaderParser {
base::StringPiece signature_str,
SignedExchangeDevToolsProxy* devtools_proxy);
+ // TODO(kouhei): Move this to another class.
// Parses |content_type| to get the value of "v=" parameter of the signed
// exchange, and converts to SignedExchangeVersion. Returns false if failed to
// parse.
@@ -59,4 +61,4 @@ class CONTENT_EXPORT SignedExchangeHeaderParser {
} // namespace content
-#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_HEADER_PARSER_H_
+#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_SIGNATURE_HEADER_FIELD_H_
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc b/chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc
new file mode 100644
index 00000000000..d47655171a9
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc
@@ -0,0 +1,333 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_package/signed_exchange_signature_header_field.h"
+
+#include "base/callback.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class SignedExchangeSignatureHeaderFieldTest : public ::testing::Test {
+ protected:
+ SignedExchangeSignatureHeaderFieldTest() {}
+};
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, ParseSignature) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https://example.com/resource.validity.1511128380\";"
+ " cert-url=\"https://example.com/oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180,"
+ "sig2;"
+ " sig=*MEQCIGjZRqTRf9iKNkGFyzRMTFgwf/BrY2ZNIP/dykhUV0aYAiBTXg+8wujoT4n/W+"
+ "cNgb7pGqQvIUGYZ8u8HZJ5YH26Qg==*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https://example.com/resource.validity.1511128380\";"
+ " cert-url=\"https://example.com/newcerts\";"
+ " cert-sha256=*J/lEm9kNRODdCmINbvitpvdYKNQ+YgBj99DlYp4fEXw=*;"
+ " date=1511128380; expires=1511733180";
+
+ const uint8_t decoded_sig1[] = {
+ 0x30, 0x45, 0x02, 0x21, 0x00, 0xd7, 0x94, 0x8d, 0xa0, 0x37, 0x74, 0x4d,
+ 0x06, 0x58, 0x05, 0x8a, 0xe4, 0x4d, 0x16, 0x96, 0x57, 0x70, 0x32, 0x1a,
+ 0x52, 0x95, 0xfa, 0x1c, 0x81, 0x30, 0x71, 0x91, 0x1c, 0xd1, 0xc6, 0x58,
+ 0x2c, 0x02, 0x20, 0x6b, 0xd0, 0xec, 0x54, 0xe3, 0x0c, 0xfa, 0x0e, 0x58,
+ 0xa7, 0x01, 0x01, 0x74, 0x65, 0xb7, 0xb1, 0x2f, 0x9b, 0xbe, 0x79, 0x80,
+ 0x24, 0x98, 0x92, 0x33, 0x08, 0x6e, 0x05, 0xda, 0xa9, 0xe5, 0x46};
+ const net::SHA256HashValue decoded_cert_sha256_1 = {
+ {0x5b, 0xbb, 0x81, 0xf7, 0xaf, 0x5d, 0x15, 0x6d, 0xcc, 0x6f, 0x96,
+ 0x5e, 0x7c, 0xf4, 0xbd, 0x4e, 0xae, 0x59, 0x6c, 0x7e, 0x62, 0x4a,
+ 0x63, 0x88, 0x2e, 0x98, 0xef, 0xda, 0xa1, 0x00, 0xae, 0x62}};
+ const uint8_t decoded_sig2[] = {
+ 0x30, 0x44, 0x02, 0x20, 0x68, 0xd9, 0x46, 0xa4, 0xd1, 0x7f, 0xd8, 0x8a,
+ 0x36, 0x41, 0x85, 0xcb, 0x34, 0x4c, 0x4c, 0x58, 0x30, 0x7f, 0xf0, 0x6b,
+ 0x63, 0x66, 0x4d, 0x20, 0xff, 0xdd, 0xca, 0x48, 0x54, 0x57, 0x46, 0x98,
+ 0x02, 0x20, 0x53, 0x5e, 0x0f, 0xbc, 0xc2, 0xe8, 0xe8, 0x4f, 0x89, 0xff,
+ 0x5b, 0xe7, 0x0d, 0x81, 0xbe, 0xe9, 0x1a, 0xa4, 0x2f, 0x21, 0x41, 0x98,
+ 0x67, 0xcb, 0xbc, 0x1d, 0x92, 0x79, 0x60, 0x7d, 0xba, 0x42};
+ const net::SHA256HashValue decoded_cert_sha256_2 = {
+ {0x27, 0xf9, 0x44, 0x9b, 0xd9, 0x0d, 0x44, 0xe0, 0xdd, 0x0a, 0x62,
+ 0x0d, 0x6e, 0xf8, 0xad, 0xa6, 0xf7, 0x58, 0x28, 0xd4, 0x3e, 0x62,
+ 0x00, 0x63, 0xf7, 0xd0, 0xe5, 0x62, 0x9e, 0x1f, 0x11, 0x7c}};
+
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ ASSERT_TRUE(signatures.has_value());
+ ASSERT_EQ(signatures->size(), 2u);
+
+ EXPECT_EQ(signatures->at(0).label, "sig1");
+ EXPECT_EQ(signatures->at(0).sig,
+ std::string(reinterpret_cast<const char*>(decoded_sig1),
+ sizeof(decoded_sig1)));
+ EXPECT_EQ(signatures->at(0).integrity, "mi-draft2");
+ EXPECT_EQ(signatures->at(0).validity_url,
+ "https://example.com/resource.validity.1511128380");
+ EXPECT_EQ(signatures->at(0).cert_url, "https://example.com/oldcerts");
+ EXPECT_EQ(signatures->at(0).cert_sha256, decoded_cert_sha256_1);
+ EXPECT_EQ(signatures->at(0).date, 1511128380ul);
+ EXPECT_EQ(signatures->at(0).expires, 1511733180ul);
+
+ EXPECT_EQ(signatures->at(1).label, "sig2");
+ EXPECT_EQ(signatures->at(1).sig,
+ std::string(reinterpret_cast<const char*>(decoded_sig2),
+ sizeof(decoded_sig2)));
+ EXPECT_EQ(signatures->at(1).integrity, "mi-draft2");
+ EXPECT_EQ(signatures->at(1).validity_url,
+ "https://example.com/resource.validity.1511128380");
+ EXPECT_EQ(signatures->at(1).cert_url, "https://example.com/newcerts");
+ EXPECT_EQ(signatures->at(1).cert_sha256, decoded_cert_sha256_2);
+ EXPECT_EQ(signatures->at(1).date, 1511128380ul);
+ EXPECT_EQ(signatures->at(1).expires, 1511733180ul);
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, IncompleteSignature) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ // no integrity= param
+ " validity-url=\"https://example.com/resource.validity.1511128380\";"
+ " cert-url=\"https://example.com/oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, DuplicatedParam) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https://example.com/resource.validity.1511128380\";"
+ " cert-url=\"https://example.com/oldcerts\";"
+ " cert-url=\"https://example.com/oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, InvalidCertURL) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https://example.com/resource.validity.1511128380\";"
+ " cert-url=\"https:://example.com/oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, CertURLWithFragment) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https://example.com/resource.validity.1511128380\";"
+ " cert-url=\"https://example.com/oldcerts#test\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, CertURLHttpShouldFail) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https://example.com/resource.validity.1511128380\";"
+ " cert-url=\"http://example.com/oldcerts#test\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, RelativeCertURL) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https://example.com/resource.validity.1511128380\";"
+ " cert-url=\"oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, InvalidValidityUrl) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https:://example.com/resource.validity.1511128380\";"
+ " cert-url=\"https://example.com/oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, ValidityUrlWithFragment) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https://example.com/resource.validity.1511128380#test\";"
+ " cert-url=\"https://example.com/oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, ValidityUrlHttpShouldFail) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"http://example.com/resource.validity.1511128380#test\";"
+ " cert-url=\"https://example.com/oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, RelativeValidityUrl) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"resource.validity.1511128380\";"
+ " cert-url=\"https://example.com/oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, InvalidCertSHA256) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https://example.com/resource.validity.1511128380\";"
+ " cert-url=\"https://example.com/oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefPS9;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, OpenQuoteAtEnd) {
+ const char hdr_string[] = "sig1; sig=\"";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, AsteriskInTheMiddleOfBinary) {
+ const char hdr_string[] =
+ "sig1;"
+ " sig=*MEUCIQDXlI2gN3RNBlgFiuRNFpZXcDIaUpX6HIEwcZEc0cZYLAIga9DsVOMM+"
+ "g5YpwEBdGW3sS+bvnmAJJiSMwhuBdqp5UY=*;"
+ " integrity=\"mi-draft2\";"
+ " validity-url=\"https://example.com/resource.validity.1511128380\";"
+ " cert-url=\"https://example.com/oldcerts\";"
+ " cert-sha256=*W7uB969dFW3Mb5ZefP*S9Tq5ZbH5iSmOILpjv2qEArmI=*;"
+ " date=1511128380; expires=1511733180";
+ auto signatures = SignedExchangeSignatureHeaderField::ParseSignature(
+ hdr_string, nullptr /* devtools_proxy */);
+ EXPECT_FALSE(signatures.has_value());
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_None) {
+ const char content_type[] = "application/signed-exchange";
+ base::Optional<SignedExchangeVersion> version;
+ EXPECT_TRUE(
+ SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
+ content_type, &version));
+ EXPECT_FALSE(version);
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_NoneWithSemicolon) {
+ const char content_type[] = "application/signed-exchange;";
+ base::Optional<SignedExchangeVersion> version;
+ EXPECT_FALSE(
+ SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
+ content_type, &version));
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_EmptyString) {
+ const char content_type[] = "application/signed-exchange;v=";
+ base::Optional<SignedExchangeVersion> version;
+ EXPECT_FALSE(
+ SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
+ content_type, &version));
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_Simple) {
+ const char content_type[] = "application/signed-exchange;v=b1";
+ base::Optional<SignedExchangeVersion> version;
+ EXPECT_TRUE(
+ SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
+ content_type, &version));
+ ASSERT_TRUE(version);
+ EXPECT_EQ(*version, SignedExchangeVersion::kB1);
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_SimpleWithSpace) {
+ const char content_type[] = "application/signed-exchange; v=b1";
+ base::Optional<SignedExchangeVersion> version;
+ EXPECT_TRUE(
+ SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
+ content_type, &version));
+ ASSERT_TRUE(version);
+ EXPECT_EQ(*version, SignedExchangeVersion::kB1);
+}
+
+TEST_F(SignedExchangeSignatureHeaderFieldTest,
+ VersionParam_SimpleWithDoublequotes) {
+ const char content_type[] = "application/signed-exchange;v=\"b1\"";
+ base::Optional<SignedExchangeVersion> version;
+ EXPECT_TRUE(
+ SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
+ content_type, &version));
+ ASSERT_TRUE(version);
+ EXPECT_EQ(*version, SignedExchangeVersion::kB1);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc b/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
index cf1322d96aa..e29e5c8cf49 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
@@ -14,8 +14,8 @@
#include "base/trace_event/trace_event.h"
#include "components/cbor/cbor_writer.h"
#include "content/browser/web_package/signed_exchange_consts.h"
-#include "content/browser/web_package/signed_exchange_header.h"
-#include "content/browser/web_package/signed_exchange_header_parser.h"
+#include "content/browser/web_package/signed_exchange_envelope.h"
+#include "content/browser/web_package/signed_exchange_signature_header_field.h"
#include "content/browser/web_package/signed_exchange_utils.h"
#include "crypto/signature_verifier.h"
#include "net/cert/asn1_util.h"
@@ -29,7 +29,7 @@ namespace content {
namespace {
-// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#signature-validity
+// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#signature-validity
// Step 7. "Let message be the concatenation of the following byte strings."
constexpr uint8_t kMessageHeader[] =
// 7.1. "A string that consists of octet 32 (0x20) repeated 64 times."
@@ -38,37 +38,38 @@ constexpr uint8_t kMessageHeader[] =
"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
- // 7.2. "A context string: the ASCII encoding of "HTTP Exchange"."
+ // 7.2. "A context string: the ASCII encoding of "HTTP Exchange 1"." ...
+ // "but implementations of drafts MUST NOT use it and MUST use another
+ // draft-specific string beginning with "HTTP Exchange 1 " instead."
// [spec text]
// 7.3. "A single 0 byte which serves as a separator." [spec text]
- "HTTP Exchange";
+ "HTTP Exchange 1 b1";
base::Optional<cbor::CBORValue> GenerateCanonicalRequestCBOR(
- const SignedExchangeHeader& header) {
+ const SignedExchangeEnvelope& envelope) {
cbor::CBORValue::MapValue map;
map.insert_or_assign(
cbor::CBORValue(kMethodKey, cbor::CBORValue::Type::BYTE_STRING),
- cbor::CBORValue(header.request_method(),
+ cbor::CBORValue(envelope.request_method(),
cbor::CBORValue::Type::BYTE_STRING));
map.insert_or_assign(
cbor::CBORValue(kUrlKey, cbor::CBORValue::Type::BYTE_STRING),
- cbor::CBORValue(header.request_url().spec(),
+ cbor::CBORValue(envelope.request_url().spec(),
cbor::CBORValue::Type::BYTE_STRING));
return cbor::CBORValue(map);
}
base::Optional<cbor::CBORValue> GenerateCanonicalResponseCBOR(
- const SignedExchangeHeader& header) {
- const auto& headers = header.response_headers();
+ const SignedExchangeEnvelope& envelope) {
+ const auto& headers = envelope.response_headers();
cbor::CBORValue::MapValue map;
- std::string response_code_str = base::NumberToString(header.response_code());
+ std::string response_code_str =
+ base::NumberToString(envelope.response_code());
map.insert_or_assign(
cbor::CBORValue(kStatusKey, cbor::CBORValue::Type::BYTE_STRING),
cbor::CBORValue(response_code_str, cbor::CBORValue::Type::BYTE_STRING));
for (const auto& pair : headers) {
- if (pair.first == kSignature)
- continue;
map.insert_or_assign(
cbor::CBORValue(pair.first, cbor::CBORValue::Type::BYTE_STRING),
cbor::CBORValue(pair.second, cbor::CBORValue::Type::BYTE_STRING));
@@ -76,14 +77,14 @@ base::Optional<cbor::CBORValue> GenerateCanonicalResponseCBOR(
return cbor::CBORValue(map);
}
-// Generate CBORValue from |header| as specified in:
+// Generate CBORValue from |envelope| as specified in:
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#cbor-representation
base::Optional<cbor::CBORValue> GenerateCanonicalExchangeHeadersCBOR(
- const SignedExchangeHeader& header) {
- auto req_val = GenerateCanonicalRequestCBOR(header);
+ const SignedExchangeEnvelope& envelope) {
+ auto req_val = GenerateCanonicalRequestCBOR(envelope);
if (!req_val)
return base::nullopt;
- auto res_val = GenerateCanonicalResponseCBOR(header);
+ auto res_val = GenerateCanonicalResponseCBOR(envelope);
if (!res_val)
return base::nullopt;
@@ -94,116 +95,117 @@ base::Optional<cbor::CBORValue> GenerateCanonicalExchangeHeadersCBOR(
}
// Generate a CBOR map value as specified in
-// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#signature-validity
+// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#signature-validity
// Step 7.4.
base::Optional<cbor::CBORValue> GenerateSignedMessageCBOR(
- const SignedExchangeHeader& header) {
- auto headers_val = GenerateCanonicalExchangeHeadersCBOR(header);
+ const SignedExchangeEnvelope& envelope) {
+ auto headers_val = GenerateCanonicalExchangeHeadersCBOR(envelope);
if (!headers_val)
return base::nullopt;
// 7.4. "The bytes of the canonical CBOR serialization (Section 3.4) of
// a CBOR map mapping:" [spec text]
cbor::CBORValue::MapValue map;
- // 7.4.1. "If certSha256 is set: The text string "certSha256" to the byte
- // string value of certSha256." [spec text]
- if (header.signature().cert_sha256.has_value()) {
+ // 7.4.1. "If cert-sha256 is set: The text string "cert-sha256" to the byte
+ // string value of cert-sha256." [spec text]
+ if (envelope.signature().cert_sha256.has_value()) {
map.insert_or_assign(
cbor::CBORValue(kCertSha256Key),
cbor::CBORValue(
base::StringPiece(reinterpret_cast<const char*>(
- header.signature().cert_sha256->data),
- sizeof(header.signature().cert_sha256->data)),
+ envelope.signature().cert_sha256->data),
+ sizeof(envelope.signature().cert_sha256->data)),
cbor::CBORValue::Type::BYTE_STRING));
}
- // 7.4.2. "The text string "validityUrl" to the byte string value of
- // validityUrl." [spec text]
+ // 7.4.2. "The text string "validity-url" to the byte string value of
+ // validity-url." [spec text]
map.insert_or_assign(cbor::CBORValue(kValidityUrlKey),
- cbor::CBORValue(header.signature().validity_url.spec(),
+ cbor::CBORValue(envelope.signature().validity_url.spec(),
cbor::CBORValue::Type::BYTE_STRING));
// 7.4.3. "The text string "date" to the integer value of date." [spec text]
- if (!base::IsValueInRangeForNumericType<int64_t>(header.signature().date))
+ if (!base::IsValueInRangeForNumericType<int64_t>(envelope.signature().date))
return base::nullopt;
map.insert_or_assign(
cbor::CBORValue(kDateKey),
- cbor::CBORValue(base::checked_cast<int64_t>(header.signature().date)));
+ cbor::CBORValue(base::checked_cast<int64_t>(envelope.signature().date)));
// 7.4.4. "The text string "expires" to the integer value of expires."
// [spec text]
- if (!base::IsValueInRangeForNumericType<int64_t>(header.signature().expires))
+ if (!base::IsValueInRangeForNumericType<int64_t>(
+ envelope.signature().expires))
return base::nullopt;
- map.insert_or_assign(
- cbor::CBORValue(kExpiresKey),
- cbor::CBORValue(base::checked_cast<int64_t>(header.signature().expires)));
+ map.insert_or_assign(cbor::CBORValue(kExpiresKey),
+ cbor::CBORValue(base::checked_cast<int64_t>(
+ envelope.signature().expires)));
// 7.4.5. "The text string "headers" to the CBOR representation
// (Section 3.2) of exchange's headers." [spec text]
map.insert_or_assign(cbor::CBORValue(kHeadersKey), std::move(*headers_val));
return cbor::CBORValue(map);
}
-bool VerifySignature(base::span<const uint8_t> sig,
- base::span<const uint8_t> msg,
- scoped_refptr<net::X509Certificate> cert,
- SignedExchangeDevToolsProxy* devtools_proxy) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"), "VerifySignature");
+base::Optional<crypto::SignatureVerifier::SignatureAlgorithm>
+GetSignatureAlgorithm(scoped_refptr<net::X509Certificate> cert,
+ SignedExchangeDevToolsProxy* devtools_proxy) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), "VerifySignature");
base::StringPiece spki;
if (!net::asn1::ExtractSPKIFromDERCert(
net::x509_util::CryptoBufferAsStringPiece(cert->cert_buffer()),
&spki)) {
- TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("loading"), "VerifySignature",
- "error", "Failed to extract SPKI.");
- return false;
+ signed_exchange_utils::ReportErrorAndTraceEvent(devtools_proxy,
+ "Failed to extract SPKI.");
+ return base::nullopt;
}
- crypto::SignatureVerifier::SignatureAlgorithm algorithm;
CBS cbs;
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(spki.data()), spki.size());
bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
if (!pkey || CBS_len(&cbs) != 0) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "VerifySignature", "Failed to parse public key.");
- return false;
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Failed to parse public key.");
+ return base::nullopt;
}
- switch (EVP_PKEY_id(pkey.get())) {
- case EVP_PKEY_RSA:
- algorithm = crypto::SignatureVerifier::RSA_PSS_SHA256;
- break;
- case EVP_PKEY_EC: {
- const EC_GROUP* group =
- EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey.get()));
- switch (EC_GROUP_get_curve_name(group)) {
- case NID_X9_62_prime256v1:
- algorithm = crypto::SignatureVerifier::ECDSA_SHA256;
- break;
- default:
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "VerifySignature", "Unsupported EC group.");
- return false;
- }
- break;
- }
- default:
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "VerifySignature", "Unsupported public key type.");
- return false;
+
+ int pkey_id = EVP_PKEY_id(pkey.get());
+ if (pkey_id != EVP_PKEY_EC) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
+ base::StringPrintf("Unsupported public key type: %d. Only ECDSA keys "
+ "on the secp256r1 curve are supported.",
+ pkey_id));
+ return base::nullopt;
}
+ const EC_GROUP* group = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey.get()));
+ int curve_name = EC_GROUP_get_curve_name(group);
+ if (curve_name == NID_X9_62_prime256v1)
+ return crypto::SignatureVerifier::ECDSA_SHA256;
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
+ base::StringPrintf("Unsupported EC group: %d. Only ECDSA keys on the "
+ "secp256r1 curve are supported.",
+ curve_name));
+ return base::nullopt;
+}
+
+bool VerifySignature(base::span<const uint8_t> sig,
+ base::span<const uint8_t> msg,
+ scoped_refptr<net::X509Certificate> cert,
+ crypto::SignatureVerifier::SignatureAlgorithm algorithm,
+ SignedExchangeDevToolsProxy* devtools_proxy) {
crypto::SignatureVerifier verifier;
if (!net::x509_util::SignatureVerifierInitWithCertificate(
&verifier, algorithm, sig, cert->cert_buffer())) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "VerifySignature",
- "SignatureVerifierInitWithCertificate failed.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "SignatureVerifierInitWithCertificate failed.");
return false;
}
verifier.VerifyUpdate(msg);
if (!verifier.VerifyFinal()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "VerifySignature", "VerifyFinal failed.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(devtools_proxy,
+ "VerifyFinal failed.");
return false;
}
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"), "VerifySignature");
return true;
}
@@ -216,12 +218,13 @@ std::string HexDump(const std::vector<uint8_t>& msg) {
}
base::Optional<std::vector<uint8_t>> GenerateSignedMessage(
- const SignedExchangeHeader& header) {
+ const SignedExchangeEnvelope& envelope) {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
"GenerateSignedMessage");
// GenerateSignedMessageCBOR corresponds to Step 7.4.
- base::Optional<cbor::CBORValue> cbor_val = GenerateSignedMessageCBOR(header);
+ base::Optional<cbor::CBORValue> cbor_val =
+ GenerateSignedMessageCBOR(envelope);
if (!cbor_val) {
TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("loading"),
"GenerateSignedMessage", "error",
@@ -259,12 +262,12 @@ base::Time TimeFromSignedExchangeUnixTime(uint64_t t) {
// Implements steps 5-6 of
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#signature-validity
-bool VerifyTimestamps(const SignedExchangeHeader& header,
+bool VerifyTimestamps(const SignedExchangeEnvelope& envelope,
const base::Time& verification_time) {
base::Time expires_time =
- TimeFromSignedExchangeUnixTime(header.signature().expires);
+ TimeFromSignedExchangeUnixTime(envelope.signature().expires);
base::Time creation_time =
- TimeFromSignedExchangeUnixTime(header.signature().date);
+ TimeFromSignedExchangeUnixTime(envelope.signature().date);
// 5. "If expires is more than 7 days (604800 seconds) after date, return
// "invalid"." [spec text]
@@ -282,84 +285,82 @@ bool VerifyTimestamps(const SignedExchangeHeader& header,
} // namespace
SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
- const SignedExchangeHeader& header,
+ const SignedExchangeEnvelope& envelope,
scoped_refptr<net::X509Certificate> certificate,
const base::Time& verification_time,
SignedExchangeDevToolsProxy* devtools_proxy) {
- TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeSignatureVerifier::Verify");
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeSignatureVerifier::Verify");
- if (!VerifyTimestamps(header, verification_time)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
+ if (!VerifyTimestamps(envelope, verification_time)) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
base::StringPrintf(
"Invalid timestamp. creation_time: %" PRIu64
", expires_time: %" PRIu64 ", verification_time: %" PRIu64,
- header.signature().date, header.signature().expires,
+ envelope.signature().date, envelope.signature().expires,
(verification_time - base::Time::UnixEpoch()).InSeconds()));
return Result::kErrInvalidTimestamp;
}
if (!certificate) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
- "No certificate set.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(devtools_proxy,
+ "No certificate set.");
return Result::kErrNoCertificate;
}
- if (!header.signature().cert_sha256.has_value()) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
- "No certSha256 set.");
+ if (!envelope.signature().cert_sha256.has_value()) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(devtools_proxy,
+ "No cert-sha256 set.");
return Result::kErrNoCertificateSHA256;
}
// The main-certificate is the first certificate in certificate-chain.
- if (*header.signature().cert_sha256 !=
+ if (*envelope.signature().cert_sha256 !=
net::X509Certificate::CalculateFingerprint256(
certificate->cert_buffer())) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
- "certSha256 mismatch.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(devtools_proxy,
+ "cert-sha256 mismatch.");
return Result::kErrCertificateSHA256Mismatch;
}
- auto message = GenerateSignedMessage(header);
+ auto message = GenerateSignedMessage(envelope);
if (!message) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
- "Failed to reconstruct signed message.");
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Failed to reconstruct signed message.");
return Result::kErrInvalidSignatureFormat;
}
- const std::string& sig = header.signature().sig;
+ base::Optional<crypto::SignatureVerifier::SignatureAlgorithm> algorithm =
+ GetSignatureAlgorithm(certificate, devtools_proxy);
+ if (!algorithm)
+ return Result::kErrUnsupportedCertType;
+
+ const std::string& sig = envelope.signature().sig;
if (!VerifySignature(
base::make_span(reinterpret_cast<const uint8_t*>(sig.data()),
sig.size()),
- *message, certificate, devtools_proxy)) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
- "Failed to verify signature \"sig\".");
+ *message, certificate, *algorithm, devtools_proxy)) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy, "Failed to verify signature \"sig\".");
return Result::kErrSignatureVerificationFailed;
}
- if (!base::EqualsCaseInsensitiveASCII(header.signature().integrity, "mi")) {
- signed_exchange_utils::ReportErrorAndEndTraceEvent(
- devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
+ if (!base::EqualsCaseInsensitiveASCII(envelope.signature().integrity,
+ "mi-draft2")) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
"The current implemention only supports \"mi\" integrity scheme.");
return Result::kErrInvalidSignatureIntegrity;
}
-
- TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeSignatureVerifier::Verify");
return Result::kSuccess;
}
base::Optional<std::vector<uint8_t>>
SignedExchangeSignatureVerifier::EncodeCanonicalExchangeHeaders(
- const SignedExchangeHeader& header) {
+ const SignedExchangeEnvelope& envelope) {
base::Optional<cbor::CBORValue> cbor_val =
- GenerateCanonicalExchangeHeadersCBOR(header);
+ GenerateCanonicalExchangeHeadersCBOR(envelope);
if (!cbor_val)
return base::nullopt;
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_verifier.h b/chromium/content/browser/web_package/signed_exchange_signature_verifier.h
index fe8da78f44a..cca2ea786f5 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_verifier.h
+++ b/chromium/content/browser/web_package/signed_exchange_signature_verifier.h
@@ -21,7 +21,7 @@ class Time;
namespace content {
-class SignedExchangeHeader;
+class SignedExchangeEnvelope;
class SignedExchangeDevToolsProxy;
// SignedExchangeSignatureVerifier verifies the signature of the given
@@ -44,16 +44,17 @@ class CONTENT_EXPORT SignedExchangeSignatureVerifier final {
kErrInvalidSignatureFormat,
kErrSignatureVerificationFailed,
kErrInvalidSignatureIntegrity,
- kErrInvalidTimestamp
+ kErrInvalidTimestamp,
+ kErrUnsupportedCertType
};
- static Result Verify(const SignedExchangeHeader& header,
+ static Result Verify(const SignedExchangeEnvelope& envelope,
scoped_refptr<net::X509Certificate> certificate,
const base::Time& verification_time,
SignedExchangeDevToolsProxy* devtools_proxy);
static base::Optional<std::vector<uint8_t>> EncodeCanonicalExchangeHeaders(
- const SignedExchangeHeader& header);
+ const SignedExchangeEnvelope& envelope);
};
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc b/chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc
index b902e1e9f9b..9dbab4e6422 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc
@@ -5,8 +5,8 @@
#include "content/browser/web_package/signed_exchange_signature_verifier.h"
#include "base/callback.h"
-#include "content/browser/web_package/signed_exchange_header.h"
-#include "content/browser/web_package/signed_exchange_header_parser.h"
+#include "content/browser/web_package/signed_exchange_envelope.h"
+#include "content/browser/web_package/signed_exchange_signature_header_field.h"
#include "net/cert/x509_certificate.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -15,15 +15,15 @@ namespace content {
namespace {
TEST(SignedExchangeSignatureVerifier, EncodeCanonicalExchangeHeaders) {
- SignedExchangeHeader header;
- header.set_request_method("GET");
- header.set_request_url(GURL("https://example.com/index.html"));
- header.set_response_code(net::HTTP_OK);
- header.AddResponseHeader("content-type", "text/html; charset=utf-8");
- header.AddResponseHeader("content-encoding", "mi-sha256");
+ SignedExchangeEnvelope envelope;
+ envelope.set_request_method("GET");
+ envelope.set_request_url(GURL("https://example.com/index.html"));
+ envelope.set_response_code(net::HTTP_OK);
+ envelope.AddResponseHeader("content-type", "text/html; charset=utf-8");
+ envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2");
base::Optional<std::vector<uint8_t>> encoded =
- SignedExchangeSignatureVerifier::EncodeCanonicalExchangeHeaders(header);
+ SignedExchangeSignatureVerifier::EncodeCanonicalExchangeHeaders(envelope);
ASSERT_TRUE(encoded.has_value());
static const uint8_t kExpected[] = {
@@ -51,8 +51,9 @@ TEST(SignedExchangeSignatureVerifier, EncodeCanonicalExchangeHeaders) {
0x50, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e,
0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, // bytes "content-encoding"
- 0x49, 0x6d, 0x69, 0x2d, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36,
- // bytes "mi-sha256"
+ 0x50, 0x6d, 0x69, 0x2d, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x2d,
+ 0x64, 0x72, 0x61, 0x66, 0x74, 0x32
+ // bytes "mi-sha256-draft2"
// clang-format on
};
EXPECT_THAT(*encoded,
@@ -62,45 +63,11 @@ TEST(SignedExchangeSignatureVerifier, EncodeCanonicalExchangeHeaders) {
const uint64_t kSignatureHeaderDate = 1517892341;
const uint64_t kSignatureHeaderExpires = 1517895941;
+// See content/testdata/sxg/README on how to generate these data.
// clang-format off
-constexpr char kSignatureHeaderRSA[] =
- "sig; "
- "sig=*RhjjWuXi87riQUu90taBHFJgTo8XBhiCe9qTJMP7/XVPu2diRGipo06HoGsyXkidHiiW"
- "743JgoNmO7CjfeVXLXQgKDxtGidATtPsVadAT4JpBDZJWSUg5qAbWcASXjyO38Uhq9gJkeu4w"
- "1MRMGkvpgVXNjYhi5/9NUer1xEUuJh5UbIDhGrfMihwj+c30nW+qz0n5lCrYonk+Sc0jGcLgc"
- "aDLptqRhOG5S+avwKmbQoqtD0JSc/53L5xXjppyvSA2fRmoDlqVQpX4uzRKq9cny7fZ3qgpZ/"
- "YOCuT7wMj7oVEur175QLe2F8ktKH9arSEiquhFJxBIIIXza8PJnmL5w;"
- "validityUrl=\"https://example.com/resource.validity.msg\"; "
- "integrity=\"mi\"; "
- "certUrl=\"https://example.com/cert.msg\"; "
- "certSha256=*3wfzkF4oKGUwoQ0rE7U11FIdcA/8biGzlaACeRQQH6k; "
- "date=1517892341; expires=1517895941";
-// clang-format on
-
-// See content/testdata/htxg/README on how to generate this data.
-// clang-format off
-constexpr char kSignatureHeaderECDSAP256[] =
- "label; "
- "sig=*MEYCIQDQYQAHAlpznkP/btvuNnvGY5ycO+NOOTFXsoBjF22UhAIhAMyzyMikudaQeIPYB"
- "fh2JdqZVBwgsQ6a3Cn8lFA0XYGW; "
- "validityUrl=\"https://example.com/resource.validity.msg\"; "
- "integrity=\"mi\"; "
- "certUrl=\"https://example.com/cert.msg\"; "
- "certSha256=*CfDj40tr5B7oo6IaWwQF2L1uDgsHH0fA2YOCB7E0tAQ; "
- "date=1517892341; expires=1517895941";
-// clang-format on
-
-// See content/testdata/htxg/README on how to generate this data.
-// clang-format off
-constexpr char kSignatureHeaderECDSAP384[] =
- "label; "
- "sig=*MGQCMDtOqWBsWjx1+WZta9tBpuuMJMLMwp8/eHu+PwNw95qCMMjD1xJiLIm0HUtFzdzSC"
- "wIwVxSUD9IB2t4JIHz6IJPddqR1ex38kkSvOYSmFEwqVPRM1sqAcEtvwdpSU+cLJYbS; "
- "validityUrl=\"https://example.com/resource.validity.msg\"; "
- "integrity=\"mi\"; "
- "certUrl=\"https://example.com/cert.msg\"; "
- "certSha256=*8X8y8nj8vDJHSSa0cxn+TCu+8zGpIJfbdzAnd5cW+jA; "
- "date=1517892341; expires=1517895941";
+constexpr char kSignatureHeaderRSA[] = R"(label; sig=*yYFb09i7VXuqsGBxc3RuJzGL4XMD9bZ20kXWSv1JObEf7KIG0MznSE1nu1fE+7DrgWQxH7FQfSWjyseOAvxsBOfkptmCCi/Ffklz3N1UU8LfwfaLWj80oBqDeofiIYwevSSpsaRKBYie7KjiVOjslFLOGe82MmHyF2utFRKY/i6UAHgMrg2FGfbwBaJsxEgtpPcN8/QnFKgt1la+JjwvYbMHpJhHTedDqx9GCxJOzbJjKRL1E2tIBvhDfK2m3eJv/nqvgWkK3MOd/Xp4FkndciS3eNyZZjwvJ6IL/3x4e0AZ36KvglpS092ZftiE4lKQWnHmVeDRmEHW6qOyv1Q3+w==*; validity-url="https://example.com/resource.validity.msg"; integrity="mi-draft2"; cert-url="https://example.com/cert.msg"; cert-sha256=*tJGJP8ej7KCEW8VnVK3bKwpBza/oLrtWA75z5ZPptuc=*; date=1517892341; expires=1517895941)";
+constexpr char kSignatureHeaderECDSAP256[] = R"(label; sig=*MEQCIA0w6auOuWGT6//MO/h43/xkXBchJUOp53GU5dmA8U+/AiAe0FggCblVxzosT2Ow9rrC2Q8zO0DZPLSNbcu29xYP6g==*; validity-url="https://example.com/resource.validity.msg"; integrity="mi-draft2"; cert-url="https://example.com/cert.msg"; cert-sha256=*KX+BYLSMgDOON8Ju65RoId39Qvajxa12HO+WnD4HpS0=*; date=1517892341; expires=1517895941)";
+constexpr char kSignatureHeaderECDSAP384[] = R"(label; sig=*MGYCMQC/P8m0ZnPrIMlI3I412MixcK9cQSirIECUNR7pOIlTiLaH95L72KXqq2aL+lxxKIICMQDU3s/BhoWtR61eKG9SqgGHd0ZtUJVY24xaJ2yHiYWxZU/QhOr5ZArSj3x1khivpRg=*; validity-url="https://example.com/resource.validity.msg"; integrity="mi-draft2"; cert-url="https://example.com/cert.msg"; cert-sha256=*8X8y8nj8vDJHSSa0cxn+TCu+8zGpIJfbdzAnd5cW+jA=*; date=1517892341; expires=1517895941)";
// clang-format on
// |expires| (1518497142) is more than 7 days (604800 seconds) after |date|
@@ -112,55 +79,57 @@ constexpr char kSignatureHeaderInvalidExpires[] =
"743JgoNmO7CjfeVXLXQgKDxtGidATtPsVadAT4JpBDZJWSUg5qAbWcASXjyO38Uhq9gJkeu4w"
"1MRMGkvpgVXNjYhi5/9NUer1xEUuJh5UbIDhGrfMihwj+c30nW+qz0n5lCrYonk+Sc0jGcLgc"
"aDLptqRhOG5S+avwKmbQoqtD0JSc/53L5xXjppyvSA2fRmoDlqVQpX4uzRKq9cny7fZ3qgpZ/"
- "YOCuT7wMj7oVEur175QLe2F8ktKH9arSEiquhFJxBIIIXza8PJnmL5w;"
- "validityUrl=\"https://example.com/resource.validity.msg\"; "
- "integrity=\"mi\"; "
- "certUrl=\"https://example.com/cert.msg\"; "
- "certSha256=*3wfzkF4oKGUwoQ0rE7U11FIdcA/8biGzlaACeRQQH6k; "
+ "YOCuT7wMj7oVEur175QLe2F8ktKH9arSEiquhFJxBIIIXza8PJnmL5w==*;"
+ "validity-url=\"https://example.com/resource.validity.msg\"; "
+ "integrity=\"mi-draft2\"; "
+ "cert-url=\"https://example.com/cert.msg\"; "
+ "cert-sha256=*3wfzkF4oKGUwoQ0rE7U11FIdcA/8biGzlaACeRQQH6k=*; "
"date=1517892341; expires=1518497142";
// clang-format on
constexpr char kCertPEMRSA[] = R"(
-----BEGIN CERTIFICATE-----
-MIID9zCCAt+gAwIBAgIUde2ndSB4271TAGDk0Ft+WuCCGnMwDQYJKoZIhvcNAQEL
-BQAwUDELMAkGA1UEBhMCSlAxEjAQBgNVBAgTCU1pbmF0by1rdTEOMAwGA1UEBxMF
-VG9reW8xEDAOBgNVBAoTB1Rlc3QgQ0ExCzAJBgNVBAsTAkNBMB4XDTE4MDIwNTA0
-NDUwMFoXDTE5MDIwNTA0NDUwMFowbzELMAkGA1UEBhMCSlAxEjAQBgNVBAgTCU1p
-bmF0by1rdTEOMAwGA1UEBxMFVG9reW8xFDASBgNVBAoTC2V4YW1wbGUuY29tMRIw
-EAYDVQQLEwl3ZWJzZXJ2ZXIxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZI
-hvcNAQEBBQADggEPADCCAQoCggEBAJv0UV5pK/XMtmHuDHUSvU+mNghsDQsKYSeB
-r/CySBIbLWtkeC7oxuYT2R+Mz4vVs0WQ1f3F/e3HIIQxWmy5VYErER13c53yeCNF
-fcBkwpuCZKEO1BURX+WgjYPnzLYX1xDnpBM++TuEZKdxzUVjs/jQjMNB8sbRYzng
-IIbA4HiRUtPvnGjLmY0HxZyskb52yeTWg40jWPdLaC8GMEZXGKynAnGEMl3c/dVw
-8+nKS1VVe6k32Ubfl1NlaqbOXi0xHHMUhLY/l8Lu49E0ivPS7BWL/0nMR9EAmu+I
-AgK9OD7VRoMA0LEKBzIQUEuK70JxLkV7GNvrtnOX83+EwwdfBdUCAwEAAaOBqTCB
-pjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC
-MAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDzp/0BrXKIfDGe3KfJLyBH8azW2MB8G
-A1UdIwQYMBaAFNAPhK4UBktJcx6TIk5QKwZPit4ZMCcGA1UdEQQgMB6CC2V4YW1w
-bGUuY29tgg93d3cuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBAKSQbsOW
-IX2JDv+Vg1lvbOFx+JqwdhvYTkOF4Z9YbRtlqEIZbc8KWjAOzDB1xVJxhSjD+f8+
-vrj7YN/ggCQk6DzuF4lkztBDO95Fxmx4EeIKdKt83WP09Os/2yIOKToOnHkmauBB
-ijY8oxNs+XxKrPX7DN5QQQhiTsZcL625fcnIwPb0DeeuCT7bJYPv8OojMDTR1uDt
-SQ53HYt0aLun+Br3lCwW8cnpxuezJhg0gNezYp/8gC4kByqoT26atpls08eWUdFD
-U0/55zFz2OzNoAHaoBzMRxn4ZSc3+lxl0K1+cCP8ivhwkxdz/vhz5RfOjpSinxqt
-wYxI2+BLS6X5NpI=
+MIIDyTCCArGgAwIBAgIBBDANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
+A1UECgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMB4XDTE3MDYwNTE3
+MTA0NloXDTI3MDYwMzE3MTA0NlowYDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh
+bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB1Rlc3Qg
+Q0ExEjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBANOUHzO0uxUyd3rYUArq33olXC0N1AYNM0wFTjUqUrElLiX48+5hERkG
+hGwC8VG5Zr/2Jw/wtarLiDjg2OfPdwyMp3S7MBTgvXWZ989MUHpx6b0cWM298iOg
+/VeinMphFLDfPDHFWZ7RXBqfk6MGLhI5GgvoooYw2jUmP+elnoizIL/OB08sIYra
+AVrwasoRd+yOmyvQnzw3mZNKpWjeX7NhZCg2nG8B8u78agwAYVWupHnJS2GwhLzy
+19AxU/HmaI9kyyMGmRtbRZ0roCyMDOgEEcWUSYNRP33KLi31uKYqOSblvzmC7kA7
+k5yca3VXlgqg4gnjr9tbOMzMcpeqeaMCAwEAAaOBijCBhzAMBgNVHRMBAf8EAjAA
+MB0GA1UdDgQWBBQYDOtRudM2qckEr/kvFPCZZtJ21DAfBgNVHSMEGDAWgBSbJguK
+mKm7HbkfHOMaQDPtjheIqzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
+GAYDVR0RBBEwD4INKi5leGFtcGxlLm9yZzANBgkqhkiG9w0BAQsFAAOCAQEAvXK0
+UF19i7JkSSdomQwB18WRFaKG8VZpSFsKbEECPRHoxktMl/Pd04wk+W0fZFq433j3
+4D+cjTB6OxAVdPIPSex8U40fYMl9C13K1tejf4o/+rcLxEDdVfv7PUkogrliXzSE
+MCYdcTwruV7hjC2/Ib0t/kdxblRt4dD2I1jdntsFy/VfET/m0J2qRhJWlfYEzCFe
+Hn8H/PZIiIsso5pm2RodTqi9w4/+1r8Yyfmk8TF+EoWDYtbZ+ScgtCH5fldS+onI
+hHgjz/tniqjbY0MRFr9ZxrohmtgOBOvROEKH06c92oOmj2ahyFpM/yU9PL/JvNmF
+SaMW1eOzjHemIWKTMw==
-----END CERTIFICATE-----)";
constexpr char kCertPEMECDSAP256[] = R"(
-----BEGIN CERTIFICATE-----
-MIICQzCCASsCAQEwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxEzARBgNV
-BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoM
-B1Rlc3QgQ0ExFTATBgNVBAMMDFRlc3QgUm9vdCBDQTAeFw0xODAzMjMwNDU3MzRa
-Fw0xOTAzMTgwNDU3MzRaMDcxGTAXBgNVBAMMEHRlc3QuZXhhbXBsZS5vcmcxDTAL
-BgNVBAoMBFRlc3QxCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
-QgAECQYn3HDPPhtMv2hzyjI7E3FU89EjnzTtvLd9OP55GLAsaE/FCTWbx6rKOxF7
-O4jP0N3PsIzr+nT1lIix+HpxujANBgkqhkiG9w0BAQsFAAOCAQEAhKdVMvKm7gBz
-af6nfCkLGRo56KJasi6lJh2byF17vdqq+mSXR+jHZtsRsRZJyl+C+jaSzrT0TnMA
-kLg+U4ZnKZD5sTo7TWnRlTA4G4tOrWaq1tn89FWqe+hbvn6dEyTZ1XFPaO6hzeNH
-ZM5H+bIpngvGmP1lf7K6PtC3Tx/S938zBdQrfKz/4ZB0S5cmIyIUBnlj3PDWtLsB
-KS4wvSnjPj1EyVKxTQH1PdB2NqC4eT8bgFcryNWrkMOWdOUNhGWB55nVwI8yNPQO
-4OrKJLsDZir3v7dzcU9U1erBp4+udGFIfW86g24FX1gn3SavtO6lZt59AFLptyQ6
-LWh1CMv1aQ==
+MIIC1TCCAb2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
+A1UECgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMB4XDTE4MDYyODA1
+MTUzMFoXDTE5MDYyMzA1MTUzMFowNzEZMBcGA1UEAwwQdGVzdC5leGFtcGxlLm9y
+ZzENMAsGA1UECgwEVGVzdDELMAkGA1UEBhMCVVMwWTATBgcqhkjOPQIBBggqhkjO
+PQMBBwNCAAQJBifccM8+G0y/aHPKMjsTcVTz0SOfNO28t304/nkYsCxoT8UJNZvH
+qso7EXs7iM/Q3c+wjOv6dPWUiLH4enG6o4GKMIGHMAkGA1UdEwQCMAAwEAYKKwYB
+BAHWeQIBFgQCBQAwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBS6dTuFdAI6uylsw3cy
+H3FXfh9g+jAfBgNVHSMEGDAWgBSbJguKmKm7HbkfHOMaQDPtjheIqzAbBgNVHREE
+FDASghB0ZXN0LmV4YW1wbGUub3JnMA0GCSqGSIb3DQEBCwUAA4IBAQCi/l1E+JDK
+/g3cLa5GD8vthZJuFwYEF6lGaAj1RtZ+UwbtRs1vnkJbEpLD1xX5rKXAdWT5QI99
+yK6gXbbicaJmw0KjeE0qizTT1oEfavQu7FtJZ4gfBjIHLsk8PVqHI3t8hf/pJwOd
+n+E79k3qQ2w1IeeVFZXJfnjhOsxHp2NTbeY+ZnbWsTSyUiL81n5GkuyKNDeZkoXi
+x5M6kp+6ZZJHJvLQFp4CqhU+wvM2lvP5mYYDcSlRnlti+N8xwDUb/yGR0UdNx76K
+7uFRoc8R1W8e4kFvU2NHkrtVbaLL6m+/vHE2LehVPh0QQT34Fv0QugYm+iYNToCT
+k5bUo19UY4w3
-----END CERTIFICATE-----)";
constexpr char kCertPEMECDSAP384[] = R"(
@@ -190,16 +159,16 @@ class SignedExchangeSignatureVerifierTest : public ::testing::Test {
}
void TestVerifierGivenValidInput(
- const SignedExchangeHeader& header,
+ const SignedExchangeEnvelope& envelope,
scoped_refptr<net::X509Certificate> certificate) {
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
SignedExchangeSignatureVerifier::Verify(
- header, certificate, VerificationTime(),
+ envelope, certificate, VerificationTime(),
nullptr /* devtools_proxy */));
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
SignedExchangeSignatureVerifier::Verify(
- header, certificate,
+ envelope, certificate,
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(kSignatureHeaderDate - 1),
nullptr /* devtools_proxy */
@@ -207,7 +176,7 @@ class SignedExchangeSignatureVerifierTest : public ::testing::Test {
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
SignedExchangeSignatureVerifier::Verify(
- header, certificate,
+ envelope, certificate,
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(kSignatureHeaderExpires),
nullptr /* devtools_proxy */
@@ -215,52 +184,54 @@ class SignedExchangeSignatureVerifierTest : public ::testing::Test {
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
SignedExchangeSignatureVerifier::Verify(
- header, certificate,
+ envelope, certificate,
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(kSignatureHeaderExpires + 1),
nullptr /* devtools_proxy */
));
- SignedExchangeHeader invalid_expires_header(header);
- auto invalid_expires_signature = SignedExchangeHeaderParser::ParseSignature(
- kSignatureHeaderInvalidExpires, nullptr /* devtools_proxy */);
+ SignedExchangeEnvelope invalid_expires_envelope(envelope);
+ auto invalid_expires_signature =
+ SignedExchangeSignatureHeaderField::ParseSignature(
+ kSignatureHeaderInvalidExpires, nullptr /* devtools_proxy */);
ASSERT_TRUE(invalid_expires_signature.has_value());
ASSERT_EQ(1u, invalid_expires_signature->size());
- invalid_expires_header.SetSignatureForTesting(
+ invalid_expires_envelope.SetSignatureForTesting(
(*invalid_expires_signature)[0]);
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
SignedExchangeSignatureVerifier::Verify(
- invalid_expires_header, certificate, VerificationTime(),
+ invalid_expires_envelope, certificate, VerificationTime(),
nullptr /* devtools_proxy */
));
- SignedExchangeHeader corrupted_header(header);
- corrupted_header.set_request_url(GURL("https://example.com/bad.html"));
+ SignedExchangeEnvelope corrupted_envelope(envelope);
+ corrupted_envelope.set_request_url(GURL("https://example.com/bad.html"));
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::
kErrSignatureVerificationFailed,
SignedExchangeSignatureVerifier::Verify(
- corrupted_header, certificate, VerificationTime(),
+ corrupted_envelope, certificate, VerificationTime(),
nullptr /* devtools_proxy */
));
- SignedExchangeHeader badsig_header(header);
- SignedExchangeHeaderParser::Signature badsig = header.signature();
+ SignedExchangeEnvelope badsig_envelope(envelope);
+ SignedExchangeSignatureHeaderField::Signature badsig = envelope.signature();
badsig.sig[0]++;
- badsig_header.SetSignatureForTesting(badsig);
+ badsig_envelope.SetSignatureForTesting(badsig);
EXPECT_EQ(SignedExchangeSignatureVerifier::Result::
kErrSignatureVerificationFailed,
SignedExchangeSignatureVerifier::Verify(
- badsig_header, certificate, VerificationTime(),
+ badsig_envelope, certificate, VerificationTime(),
nullptr /* devtools_proxy */
));
- SignedExchangeHeader badsigsha256_header(header);
- SignedExchangeHeaderParser::Signature badsigsha256 = header.signature();
+ SignedExchangeEnvelope badsigsha256_envelope(envelope);
+ SignedExchangeSignatureHeaderField::Signature badsigsha256 =
+ envelope.signature();
badsigsha256.cert_sha256->data[0]++;
- badsigsha256_header.SetSignatureForTesting(badsigsha256);
+ badsigsha256_envelope.SetSignatureForTesting(badsigsha256);
EXPECT_EQ(
SignedExchangeSignatureVerifier::Result::kErrCertificateSHA256Mismatch,
- SignedExchangeSignatureVerifier::Verify(badsigsha256_header,
+ SignedExchangeSignatureVerifier::Verify(badsigsha256_envelope,
certificate, VerificationTime(),
nullptr /* devtools_proxy */
));
@@ -268,7 +239,7 @@ class SignedExchangeSignatureVerifierTest : public ::testing::Test {
};
TEST_F(SignedExchangeSignatureVerifierTest, VerifyRSA) {
- auto signature = SignedExchangeHeaderParser::ParseSignature(
+ auto signature = SignedExchangeSignatureHeaderField::ParseSignature(
kSignatureHeaderRSA, nullptr /* devtools_proxy */);
ASSERT_TRUE(signature.has_value());
ASSERT_EQ(1u, signature->size());
@@ -279,21 +250,25 @@ TEST_F(SignedExchangeSignatureVerifierTest, VerifyRSA) {
net::X509Certificate::FORMAT_AUTO);
ASSERT_EQ(1u, certlist.size());
- SignedExchangeHeader header;
- header.set_request_method("GET");
- header.set_request_url(GURL("https://example.com/index.html"));
- header.set_response_code(net::HTTP_OK);
- header.AddResponseHeader("content-type", "text/html; charset=utf-8");
- header.AddResponseHeader("content-encoding", "mi-sha256");
- header.AddResponseHeader(
- "mi", "mi-sha256=4ld4G-h-sQSoLBD39ndIO15O_82NXSzq9UMFEYI02JQ");
- header.SetSignatureForTesting((*signature)[0]);
-
- TestVerifierGivenValidInput(header, certlist[0]);
+ SignedExchangeEnvelope envelope;
+ envelope.set_request_method("GET");
+ envelope.set_request_url(GURL("https://test.example.org/test/"));
+ envelope.set_response_code(net::HTTP_OK);
+ envelope.AddResponseHeader("content-type", "text/html; charset=utf-8");
+ envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2");
+ envelope.AddResponseHeader(
+ "mi-draft2",
+ "mi-sha256-draft2=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RI");
+ envelope.SetSignatureForTesting((*signature)[0]);
+
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrUnsupportedCertType,
+ SignedExchangeSignatureVerifier::Verify(
+ envelope, certlist[0], VerificationTime(),
+ nullptr /* devtools_proxy */));
}
TEST_F(SignedExchangeSignatureVerifierTest, VerifyECDSAP256) {
- auto signature = SignedExchangeHeaderParser::ParseSignature(
+ auto signature = SignedExchangeSignatureHeaderField::ParseSignature(
kSignatureHeaderECDSAP256, nullptr /* devtools_proxy */);
ASSERT_TRUE(signature.has_value());
ASSERT_EQ(1u, signature->size());
@@ -304,22 +279,23 @@ TEST_F(SignedExchangeSignatureVerifierTest, VerifyECDSAP256) {
net::X509Certificate::FORMAT_AUTO);
ASSERT_EQ(1u, certlist.size());
- SignedExchangeHeader header;
- header.set_request_method("GET");
- header.set_request_url(GURL("https://test.example.org/test/"));
- header.set_response_code(net::HTTP_OK);
- header.AddResponseHeader("content-type", "text/html; charset=utf-8");
- header.AddResponseHeader("content-encoding", "mi-sha256");
- header.AddResponseHeader(
- "mi", "mi-sha256=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RI");
+ SignedExchangeEnvelope envelope;
+ envelope.set_request_method("GET");
+ envelope.set_request_url(GURL("https://test.example.org/test/"));
+ envelope.set_response_code(net::HTTP_OK);
+ envelope.AddResponseHeader("content-type", "text/html; charset=utf-8");
+ envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2");
+ envelope.AddResponseHeader(
+ "mi-draft2",
+ "mi-sha256-draft2=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RI");
- header.SetSignatureForTesting((*signature)[0]);
+ envelope.SetSignatureForTesting((*signature)[0]);
- TestVerifierGivenValidInput(header, certlist[0]);
+ TestVerifierGivenValidInput(envelope, certlist[0]);
}
TEST_F(SignedExchangeSignatureVerifierTest, VerifyECDSAP384) {
- auto signature = SignedExchangeHeaderParser::ParseSignature(
+ auto signature = SignedExchangeSignatureHeaderField::ParseSignature(
kSignatureHeaderECDSAP384, nullptr /* devtools_proxy */);
ASSERT_TRUE(signature.has_value());
ASSERT_EQ(1u, signature->size());
@@ -330,22 +306,22 @@ TEST_F(SignedExchangeSignatureVerifierTest, VerifyECDSAP384) {
net::X509Certificate::FORMAT_AUTO);
ASSERT_EQ(1u, certlist.size());
- SignedExchangeHeader header;
- header.set_request_method("GET");
- header.set_request_url(GURL("https://test.example.org/test/"));
- header.set_response_code(net::HTTP_OK);
- header.AddResponseHeader("content-type", "text/html; charset=utf-8");
- header.AddResponseHeader("content-encoding", "mi-sha256");
- header.AddResponseHeader(
- "mi", "mi-sha256=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RIG");
-
- header.SetSignatureForTesting((*signature)[0]);
-
- EXPECT_EQ(
- SignedExchangeSignatureVerifier::Result::kErrSignatureVerificationFailed,
- SignedExchangeSignatureVerifier::Verify(header, certlist[0],
- VerificationTime(),
- nullptr /* devtools_proxy */));
+ SignedExchangeEnvelope envelope;
+ envelope.set_request_method("GET");
+ envelope.set_request_url(GURL("https://test.example.org/test/"));
+ envelope.set_response_code(net::HTTP_OK);
+ envelope.AddResponseHeader("content-type", "text/html; charset=utf-8");
+ envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2");
+ envelope.AddResponseHeader(
+ "mi-draft2",
+ "mi-sha256-draft2=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RIG");
+
+ envelope.SetSignatureForTesting((*signature)[0]);
+
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrUnsupportedCertType,
+ SignedExchangeSignatureVerifier::Verify(
+ envelope, certlist[0], VerificationTime(),
+ nullptr /* devtools_proxy */));
}
} // namespace
diff --git a/chromium/content/browser/web_package/signed_exchange_utils.cc b/chromium/content/browser/web_package/signed_exchange_utils.cc
index 4086fd67a6c..bc1a1af246a 100644
--- a/chromium/content/browser/web_package/signed_exchange_utils.cc
+++ b/chromium/content/browser/web_package/signed_exchange_utils.cc
@@ -8,7 +8,8 @@
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
-#include "content/browser/web_package/web_package_request_handler.h"
+#include "content/browser/web_package/signed_exchange_error.h"
+#include "content/browser/web_package/signed_exchange_request_handler.h"
#include "content/public/common/content_features.h"
#include "services/network/public/cpp/resource_response.h"
#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
@@ -16,13 +17,15 @@
namespace content {
namespace signed_exchange_utils {
-void ReportErrorAndEndTraceEvent(SignedExchangeDevToolsProxy* devtools_proxy,
- const char* trace_event_name,
- const std::string& error_message) {
+void ReportErrorAndTraceEvent(
+ SignedExchangeDevToolsProxy* devtools_proxy,
+ const std::string& error_message,
+ base::Optional<SignedExchangeError::FieldIndexPair> error_field) {
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeError", TRACE_EVENT_SCOPE_THREAD, "error",
+ error_message);
if (devtools_proxy)
- devtools_proxy->ReportErrorMessage(error_message);
- TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("loading"), trace_event_name,
- "error", error_message);
+ devtools_proxy->ReportError(error_message, std::move(error_field));
}
bool IsSignedExchangeHandlingEnabled() {
@@ -38,7 +41,7 @@ bool ShouldHandleAsSignedHTTPExchange(
// TODO(crbug/803774): Decide whether we should support it or not.
if (head.was_fetched_via_service_worker)
return false;
- if (!WebPackageRequestHandler::IsSupportedMimeType(head.mime_type))
+ if (!SignedExchangeRequestHandler::IsSupportedMimeType(head.mime_type))
return false;
if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
return true;
diff --git a/chromium/content/browser/web_package/signed_exchange_utils.h b/chromium/content/browser/web_package/signed_exchange_utils.h
index b5c4220daba..105cd892da7 100644
--- a/chromium/content/browser/web_package/signed_exchange_utils.h
+++ b/chromium/content/browser/web_package/signed_exchange_utils.h
@@ -7,6 +7,9 @@
#include <string>
+#include "base/optional.h"
+#include "content/browser/web_package/signed_exchange_error.h"
+
class GURL;
namespace network {
@@ -19,12 +22,14 @@ class SignedExchangeDevToolsProxy;
namespace signed_exchange_utils {
-// Utility method to call SignedExchangeDevToolsProxy::ReportErrorMessage() and
-// TRACE_EVENT_END() to report the error to both DevTools and about:tracing. If
-// |devtools_proxy| is nullptr, it just calls TRACE_EVENT_END().
-void ReportErrorAndEndTraceEvent(SignedExchangeDevToolsProxy* devtools_proxy,
- const char* trace_event_name,
- const std::string& error_message);
+// Utility method to call SignedExchangeDevToolsProxy::ReportError() and
+// TRACE_EVENT_INSTANT1 to report the error to both DevTools and about:tracing.
+// If |devtools_proxy| is nullptr, it just calls TRACE_EVENT_INSTANT1().
+void ReportErrorAndTraceEvent(
+ SignedExchangeDevToolsProxy* devtools_proxy,
+ const std::string& error_message,
+ base::Optional<SignedExchangeError::FieldIndexPair> error_field =
+ base::nullopt);
// Returns true when SignedHTTPExchange feature or SignedHTTPExchangeOriginTrial
// feature is enabled.
diff --git a/chromium/content/browser/webauth/OWNERS b/chromium/content/browser/webauth/OWNERS
index f1f0a3ef8d6..d3733b72b38 100644
--- a/chromium/content/browser/webauth/OWNERS
+++ b/chromium/content/browser/webauth/OWNERS
@@ -1,6 +1,7 @@
engedy@chromium.org
mkwst@chromium.org
-vasilii@chromium.org
+kpaulhamus@chromium.org
+hongjunchoi@chromium.org
per-file *_type_converter*.*=set noparent
per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/browser/webauth/authenticator_impl.cc b/chromium/content/browser/webauth/authenticator_impl.cc
index 2cc796d08e2..80b95998948 100644
--- a/chromium/content/browser/webauth/authenticator_impl.cc
+++ b/chromium/content/browser/webauth/authenticator_impl.cc
@@ -4,6 +4,7 @@
#include "content/browser/webauth/authenticator_impl.h"
+#include <array>
#include <string>
#include <utility>
#include <vector>
@@ -16,6 +17,7 @@
#include "build/build_config.h"
#include "content/browser/bad_message.h"
#include "content/browser/webauth/authenticator_type_converters.h"
+#include "content/public/browser/authenticator_request_client_delegate.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
@@ -27,17 +29,17 @@
#include "content/public/common/origin_util.h"
#include "content/public/common/service_manager_connection.h"
#include "crypto/sha2.h"
+#include "device/base/features.h"
#include "device/fido/authenticator_selection_criteria.h"
#include "device/fido/ctap_get_assertion_request.h"
#include "device/fido/ctap_make_credential_request.h"
+#include "device/fido/fido_authenticator.h"
+#include "device/fido/fido_constants.h"
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/get_assertion_request_handler.h"
#include "device/fido/make_credential_request_handler.h"
#include "device/fido/public_key_credential_descriptor.h"
#include "device/fido/public_key_credential_params.h"
-#include "device/fido/u2f_register.h"
-#include "device/fido/u2f_request.h"
-#include "device/fido/u2f_sign.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
@@ -45,6 +47,10 @@
#include "url/url_constants.h"
#include "url/url_util.h"
+#if defined(OS_MACOSX)
+#include "device/fido/mac/authenticator.h"
+#endif
+
namespace content {
namespace client_data {
@@ -53,7 +59,6 @@ const char kGetType[] = "webauthn.get";
} // namespace client_data
namespace {
-constexpr int32_t kCoseEs256 = -7;
// Ensure that the origin's effective domain is a valid domain.
// Only the domain format of host is valid.
@@ -165,55 +170,16 @@ bool IsAppIdAllowedForOrigin(const GURL& appid, const url::Origin& origin) {
return false;
}
-// Check that at least one of the cryptographic parameters is supported.
-// Only ES256 is currently supported by U2F_V2 (CTAP 1.0).
-bool IsAlgorithmSupportedByU2fAuthenticators(
- const std::vector<webauth::mojom::PublicKeyCredentialParametersPtr>&
- parameters) {
- for (const auto& params : parameters) {
- if (params->algorithm_identifier == kCoseEs256)
- return true;
- }
- return false;
-}
-
-// Verify that the request doesn't contain parameters that U2F authenticators
-// cannot fulfill.
-bool AreOptionsSupportedByU2fAuthenticators(
- const webauth::mojom::PublicKeyCredentialCreationOptionsPtr& options) {
- if (options->authenticator_selection) {
- if (options->authenticator_selection->user_verification ==
- webauth::mojom::UserVerificationRequirement::REQUIRED ||
- options->authenticator_selection->require_resident_key ||
- options->authenticator_selection->authenticator_attachment ==
- webauth::mojom::AuthenticatorAttachment::PLATFORM)
- return false;
- }
- return true;
-}
-
-std::vector<std::vector<uint8_t>> FilterCredentialList(
- const std::vector<webauth::mojom::PublicKeyCredentialDescriptorPtr>&
- descriptors) {
- std::vector<std::vector<uint8_t>> handles;
- for (const auto& credential_descriptor : descriptors) {
- if (credential_descriptor->type ==
- webauth::mojom::PublicKeyCredentialType::PUBLIC_KEY) {
- handles.push_back(credential_descriptor->id);
- }
- }
- return handles;
-}
-
device::CtapMakeCredentialRequest CreateCtapMakeCredentialRequest(
- std::vector<uint8_t> client_data_hash,
- const webauth::mojom::PublicKeyCredentialCreationOptionsPtr& options) {
+ base::span<const uint8_t, device::kClientDataHashLength> client_data_hash,
+ const blink::mojom::PublicKeyCredentialCreationOptionsPtr& options,
+ bool is_individual_attestation) {
auto credential_params = mojo::ConvertTo<
std::vector<device::PublicKeyCredentialParams::CredentialInfo>>(
options->public_key_parameters);
device::CtapMakeCredentialRequest make_credential_param(
- std::move(client_data_hash),
+ client_data_hash,
mojo::ConvertTo<device::PublicKeyCredentialRpEntity>(
options->relying_party),
mojo::ConvertTo<device::PublicKeyCredentialUserEntity>(options->user),
@@ -224,14 +190,17 @@ device::CtapMakeCredentialRequest CreateCtapMakeCredentialRequest(
options->exclude_credentials);
make_credential_param.SetExcludeList(std::move(exclude_list));
+ make_credential_param.SetIsIndividualAttestation(is_individual_attestation);
return make_credential_param;
}
device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
- std::vector<uint8_t> client_data_hash,
- const webauth::mojom::PublicKeyCredentialRequestOptionsPtr& options) {
- device::CtapGetAssertionRequest request_parameter(
- options->relying_party_id, std::move(client_data_hash));
+ base::span<const uint8_t, device::kClientDataHashLength> client_data_hash,
+ const blink::mojom::PublicKeyCredentialRequestOptionsPtr& options,
+ base::Optional<base::span<const uint8_t, device::kRpIdHashLength>>
+ alternative_application_parameter) {
+ device::CtapGetAssertionRequest request_parameter(options->relying_party_id,
+ client_data_hash);
auto allowed_list =
mojo::ConvertTo<std::vector<device::PublicKeyCredentialDescriptor>>(
@@ -242,6 +211,11 @@ device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
mojo::ConvertTo<device::UserVerificationRequirement>(
options->user_verification));
+ if (alternative_application_parameter) {
+ request_parameter.SetAlternativeApplicationParameter(
+ std::move(*alternative_application_parameter));
+ }
+
if (!options->cable_authentication_data.empty()) {
request_parameter.SetCableExtension(
mojo::ConvertTo<
@@ -251,9 +225,10 @@ device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
return request_parameter;
}
-std::vector<uint8_t> ConstructClientDataHash(const std::string& client_data) {
+std::array<uint8_t, crypto::kSHA256Length> ConstructClientDataHash(
+ const std::string& client_data) {
// SHA-256 hash of the JSON data structure.
- std::vector<uint8_t> client_data_hash(crypto::kSHA256Length);
+ std::array<uint8_t, crypto::kSHA256Length> client_data_hash;
crypto::SHA256HashString(client_data, client_data_hash.data(),
client_data_hash.size());
return client_data_hash;
@@ -262,17 +237,16 @@ std::vector<uint8_t> ConstructClientDataHash(const std::string& client_data) {
// The application parameter is the SHA-256 hash of the UTF-8 encoding of
// the application identity (i.e. relying_party_id) of the application
// requesting the registration.
-std::vector<uint8_t> CreateApplicationParameter(
+std::array<uint8_t, crypto::kSHA256Length> CreateApplicationParameter(
const std::string& relying_party_id) {
- std::vector<uint8_t> application_parameter(crypto::kSHA256Length);
+ std::array<uint8_t, crypto::kSHA256Length> application_parameter;
crypto::SHA256HashString(relying_party_id, application_parameter.data(),
application_parameter.size());
return application_parameter;
}
-base::Optional<std::vector<uint8_t>> ProcessAppIdExtension(
- std::string appid,
- const url::Origin& caller_origin) {
+base::Optional<std::array<uint8_t, crypto::kSHA256Length>>
+ProcessAppIdExtension(std::string appid, const url::Origin& caller_origin) {
if (appid.empty()) {
// See step two in the comments in |IsAppIdAllowedForOrigin|.
appid = caller_origin.Serialize() + "/";
@@ -287,12 +261,12 @@ base::Optional<std::vector<uint8_t>> ProcessAppIdExtension(
return CreateApplicationParameter(appid);
}
-webauth::mojom::MakeCredentialAuthenticatorResponsePtr
+blink::mojom::MakeCredentialAuthenticatorResponsePtr
CreateMakeCredentialResponse(
const std::string& client_data_json,
device::AuthenticatorMakeCredentialResponse response_data) {
- auto response = webauth::mojom::MakeCredentialAuthenticatorResponse::New();
- auto common_info = webauth::mojom::CommonCredentialInfo::New();
+ auto response = blink::mojom::MakeCredentialAuthenticatorResponse::New();
+ auto common_info = blink::mojom::CommonCredentialInfo::New();
common_info->client_data_json.assign(client_data_json.begin(),
client_data_json.end());
common_info->raw_id = response_data.raw_credential_id();
@@ -303,12 +277,12 @@ CreateMakeCredentialResponse(
return response;
}
-webauth::mojom::GetAssertionAuthenticatorResponsePtr CreateGetAssertionResponse(
+blink::mojom::GetAssertionAuthenticatorResponsePtr CreateGetAssertionResponse(
const std::string& client_data_json,
device::AuthenticatorGetAssertionResponse response_data,
bool echo_appid_extension) {
- auto response = webauth::mojom::GetAssertionAuthenticatorResponse::New();
- auto common_info = webauth::mojom::CommonCredentialInfo::New();
+ auto response = blink::mojom::GetAssertionAuthenticatorResponse::New();
+ auto common_info = blink::mojom::CommonCredentialInfo::New();
common_info->client_data_json.assign(client_data_json.begin(),
client_data_json.end());
common_info->raw_id = response_data.raw_credential_id();
@@ -361,20 +335,29 @@ AuthenticatorImpl::AuthenticatorImpl(RenderFrameHost* render_frame_host,
protocols_.insert(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
}
-#if defined(OS_MACOSX)
- if (base::FeatureList::IsEnabled(features::kWebAuthTouchId)) {
- protocols_.insert(device::FidoTransportProtocol::kInternal);
- }
-#endif
}
-AuthenticatorImpl::~AuthenticatorImpl() {}
+AuthenticatorImpl::~AuthenticatorImpl() {
+ // This call exists to assert that |render_frame_host_| outlives this object.
+ // If this is violated, ASAN should notice.
+ render_frame_host_->GetRoutingID();
+}
+
+void AuthenticatorImpl::Bind(blink::mojom::AuthenticatorRequest request) {
+ // If |render_frame_host_| is being unloaded then binding requests are
+ // rejected.
+ if (!render_frame_host_->IsCurrent()) {
+ return;
+ }
-void AuthenticatorImpl::Bind(webauth::mojom::AuthenticatorRequest request) {
DCHECK(!binding_.is_bound());
binding_.Bind(std::move(request));
}
+bool AuthenticatorImpl::IsFocused() const {
+ return render_frame_host_->IsCurrent() && request_delegate_->IsFocused();
+}
+
// static
std::string AuthenticatorImpl::SerializeCollectedClientDataToJson(
const std::string& type,
@@ -428,18 +411,29 @@ std::string AuthenticatorImpl::SerializeCollectedClientDataToJson(
// mojom::Authenticator
void AuthenticatorImpl::MakeCredential(
- webauth::mojom::PublicKeyCredentialCreationOptionsPtr options,
+ blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
MakeCredentialCallback callback) {
- if (u2f_request_ || ctap_request_) {
- std::move(callback).Run(
- webauth::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
+ if (request_) {
+ std::move(callback).Run(blink::mojom::AuthenticatorStatus::PENDING_REQUEST,
+ nullptr);
return;
}
- if (!GetContentClient()->browser()->IsFocused(
- WebContents::FromRenderFrameHost(render_frame_host_))) {
- std::move(callback).Run(webauth::mojom::AuthenticatorStatus::NOT_FOCUSED,
- nullptr);
+ DCHECK(!request_delegate_);
+ request_delegate_ =
+ GetContentClient()->browser()->GetWebAuthenticationRequestDelegate(
+ render_frame_host_);
+ if (!request_delegate_) {
+ InvokeCallbackAndCleanup(std::move(callback),
+ blink::mojom::AuthenticatorStatus::PENDING_REQUEST,
+ nullptr, Focus::kDontCheck);
+ return;
+ }
+
+ if (!IsFocused()) {
+ InvokeCallbackAndCleanup(std::move(callback),
+ blink::mojom::AuthenticatorStatus::NOT_FOCUSED,
+ nullptr, Focus::kDontCheck);
return;
}
@@ -449,47 +443,24 @@ void AuthenticatorImpl::MakeCredential(
if (!HasValidEffectiveDomain(caller_origin)) {
bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(),
bad_message::AUTH_INVALID_EFFECTIVE_DOMAIN);
- InvokeCallbackAndCleanup(
- std::move(callback),
- webauth::mojom::AuthenticatorStatus::INVALID_DOMAIN, nullptr,
- Focus::kDontCheck);
+ InvokeCallbackAndCleanup(std::move(callback),
+ blink::mojom::AuthenticatorStatus::INVALID_DOMAIN,
+ nullptr, Focus::kDontCheck);
return;
}
if (!IsRelyingPartyIdValid(relying_party_id_, caller_origin)) {
bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(),
bad_message::AUTH_INVALID_RELYING_PARTY);
- InvokeCallbackAndCleanup(
- std::move(callback),
- webauth::mojom::AuthenticatorStatus::INVALID_DOMAIN, nullptr,
- Focus::kDontCheck);
- return;
- }
-
- // Verify that the request doesn't contain parameters that U2F authenticators
- // cannot fulfill.
- // TODO(crbug.com/819256): Improve messages for "Not Allowed" errors.
- if (!base::FeatureList::IsEnabled(features::kWebAuthCtap2) &&
- !AreOptionsSupportedByU2fAuthenticators(options)) {
- InvokeCallbackAndCleanup(
- std::move(callback),
- webauth::mojom::AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
- nullptr, Focus::kDontCheck);
- return;
- }
-
- if (!base::FeatureList::IsEnabled(features::kWebAuthCtap2) &&
- !IsAlgorithmSupportedByU2fAuthenticators(
- options->public_key_parameters)) {
- InvokeCallbackAndCleanup(
- std::move(callback),
- webauth::mojom::AuthenticatorStatus::ALGORITHM_UNSUPPORTED, nullptr,
- Focus::kDontCheck);
+ InvokeCallbackAndCleanup(std::move(callback),
+ blink::mojom::AuthenticatorStatus::INVALID_DOMAIN,
+ nullptr, Focus::kDontCheck);
return;
}
DCHECK(make_credential_response_callback_.is_null());
make_credential_response_callback_ = std::move(callback);
+ request_delegate_->DidStartRequest();
timer_->Start(
FROM_HERE, options->adjusted_timeout,
@@ -497,12 +468,6 @@ void AuthenticatorImpl::MakeCredential(
if (!connector_)
connector_ = ServiceManagerConnection::GetForProcess()->GetConnector();
- // Extract list of credentials to exclude.
- std::vector<std::vector<uint8_t>> registered_keys;
- for (const auto& credential : options->exclude_credentials) {
- registered_keys.push_back(credential->id);
- }
-
// Save client data to return with the authenticator response.
// TODO(kpaulhamus): Fetch and add the Token Binding ID public key used to
// communicate with the origin.
@@ -511,11 +476,9 @@ void AuthenticatorImpl::MakeCredential(
base::nullopt);
const bool individual_attestation =
- GetContentClient()
- ->browser()
- ->ShouldPermitIndividualAttestationForWebauthnRPID(
- render_frame_host_->GetProcess()->GetBrowserContext(),
- relying_party_id_);
+ options->attestation ==
+ blink::mojom::AttestationConveyancePreference::ENTERPRISE &&
+ request_delegate_->ShouldPermitIndividualAttestation(relying_party_id_);
attestation_preference_ = options->attestation;
@@ -524,43 +487,42 @@ void AuthenticatorImpl::MakeCredential(
protocols_.erase(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
- if (base::FeatureList::IsEnabled(features::kWebAuthCtap2)) {
- auto authenticator_selection_criteria =
- options->authenticator_selection
- ? mojo::ConvertTo<device::AuthenticatorSelectionCriteria>(
- options->authenticator_selection)
- : device::AuthenticatorSelectionCriteria();
-
- ctap_request_ = std::make_unique<device::MakeCredentialRequestHandler>(
- connector_, protocols_,
- CreateCtapMakeCredentialRequest(
- ConstructClientDataHash(client_data_json_), options),
- std::move(authenticator_selection_criteria),
- base::BindOnce(&AuthenticatorImpl::OnRegisterResponse,
- weak_factory_.GetWeakPtr()));
- } else {
- // TODO(kpaulhamus): Mock U2fRegister for unit tests.
- // http://crbug.com/785955.
- // Per fido-u2f-raw-message-formats:
- // The challenge parameter is the SHA-256 hash of the Client Data,
- // Among other things, the Client Data contains the challenge from the
- // relying party (hence the name of the parameter).
- u2f_request_ = device::U2fRegister::TryRegistration(
- connector_, protocols_, registered_keys,
- ConstructClientDataHash(client_data_json_),
- CreateApplicationParameter(relying_party_id_), individual_attestation,
- base::BindOnce(&AuthenticatorImpl::OnRegisterResponse,
- weak_factory_.GetWeakPtr()));
- }
+ auto authenticator_selection_criteria =
+ options->authenticator_selection
+ ? mojo::ConvertTo<device::AuthenticatorSelectionCriteria>(
+ options->authenticator_selection)
+ : device::AuthenticatorSelectionCriteria();
+
+ request_ = std::make_unique<device::MakeCredentialRequestHandler>(
+ connector_, protocols_,
+ CreateCtapMakeCredentialRequest(
+ ConstructClientDataHash(client_data_json_), options,
+ individual_attestation),
+ std::move(authenticator_selection_criteria),
+ base::BindOnce(&AuthenticatorImpl::OnRegisterResponse,
+ weak_factory_.GetWeakPtr()),
+ base::BindOnce(&AuthenticatorImpl::MaybeCreatePlatformAuthenticator,
+ base::Unretained(this)));
}
// mojom:Authenticator
void AuthenticatorImpl::GetAssertion(
- webauth::mojom::PublicKeyCredentialRequestOptionsPtr options,
+ blink::mojom::PublicKeyCredentialRequestOptionsPtr options,
GetAssertionCallback callback) {
- if (u2f_request_ || ctap_request_) {
- std::move(callback).Run(
- webauth::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
+ if (request_) {
+ std::move(callback).Run(blink::mojom::AuthenticatorStatus::PENDING_REQUEST,
+ nullptr);
+ return;
+ }
+
+ DCHECK(!request_delegate_);
+ request_delegate_ =
+ GetContentClient()->browser()->GetWebAuthenticationRequestDelegate(
+ render_frame_host_);
+ if (!request_delegate_) {
+ InvokeCallbackAndCleanup(std::move(callback),
+ blink::mojom::AuthenticatorStatus::PENDING_REQUEST,
+ nullptr);
return;
}
@@ -569,41 +531,28 @@ void AuthenticatorImpl::GetAssertion(
if (!HasValidEffectiveDomain(caller_origin)) {
bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(),
bad_message::AUTH_INVALID_EFFECTIVE_DOMAIN);
- InvokeCallbackAndCleanup(
- std::move(callback),
- webauth::mojom::AuthenticatorStatus::INVALID_DOMAIN, nullptr);
+ InvokeCallbackAndCleanup(std::move(callback),
+ blink::mojom::AuthenticatorStatus::INVALID_DOMAIN,
+ nullptr);
return;
}
if (!IsRelyingPartyIdValid(options->relying_party_id, caller_origin)) {
bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(),
bad_message::AUTH_INVALID_RELYING_PARTY);
- InvokeCallbackAndCleanup(
- std::move(callback),
- webauth::mojom::AuthenticatorStatus::INVALID_DOMAIN, nullptr);
- return;
- }
-
- // To use U2F, the relying party must not require user verification.
- if (!base::FeatureList::IsEnabled(features::kWebAuthCtap2) &&
- options->user_verification ==
- webauth::mojom::UserVerificationRequirement::REQUIRED) {
- InvokeCallbackAndCleanup(
- std::move(callback),
- webauth::mojom::AuthenticatorStatus::USER_VERIFICATION_UNSUPPORTED,
- nullptr);
+ InvokeCallbackAndCleanup(std::move(callback),
+ blink::mojom::AuthenticatorStatus::INVALID_DOMAIN,
+ nullptr);
return;
}
- std::vector<uint8_t> application_parameter =
- CreateApplicationParameter(options->relying_party_id);
-
- base::Optional<std::vector<uint8_t>> alternative_application_parameter;
+ base::Optional<std::array<uint8_t, crypto::kSHA256Length>>
+ alternative_application_parameter;
if (options->appid) {
auto appid_hash = ProcessAppIdExtension(*options->appid, caller_origin);
if (!appid_hash) {
- std::move(callback).Run(
- webauth::mojom::AuthenticatorStatus::INVALID_DOMAIN, nullptr);
+ std::move(callback).Run(blink::mojom::AuthenticatorStatus::INVALID_DOMAIN,
+ nullptr);
return;
}
@@ -612,32 +561,9 @@ void AuthenticatorImpl::GetAssertion(
echo_appid_extension_ = true;
}
- // Pass along valid keys from allow_list.
- std::vector<std::vector<uint8_t>> handles =
- FilterCredentialList(std::move(options->allow_credentials));
-
- // There are two different descriptions of what should happen when
- // "allowCredentials" is empty for U2F.
- // a) WebAuthN 6.2.3 step 6[1] implies "NotAllowedError".
- // b) CTAP step 7.2 step 2[2] says the device should error out with
- // "CTAP2_ERR_OPTION_NOT_SUPPORTED". This also resolves to "NotAllowedError".
- // The behavior in both cases is consistent with the current implementation.
- // When CTAP2 is enabled, however, this check is done by handlers in
- // fido/device on a per-device basis.
-
- // [1] https://w3c.github.io/webauthn/#authenticatorgetassertion
- // [2]
- // https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html
- if (!base::FeatureList::IsEnabled(features::kWebAuthCtap2) &&
- handles.empty()) {
- InvokeCallbackAndCleanup(
- std::move(callback),
- webauth::mojom::AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS, nullptr);
- return;
- }
-
DCHECK(get_assertion_response_callback_.is_null());
get_assertion_response_callback_ = std::move(callback);
+ request_delegate_->DidStartRequest();
timer_->Start(
FROM_HERE, options->adjusted_timeout,
@@ -653,29 +579,33 @@ void AuthenticatorImpl::GetAssertion(
client_data::kGetType, caller_origin, std::move(options->challenge),
base::nullopt);
- if (base::FeatureList::IsEnabled(features::kWebAuthCtap2)) {
- ctap_request_ = std::make_unique<device::GetAssertionRequestHandler>(
- connector_, protocols_,
- CreateCtapGetAssertionRequest(
- ConstructClientDataHash(client_data_json_), options),
- base::BindOnce(&AuthenticatorImpl::OnSignResponse,
- weak_factory_.GetWeakPtr()));
- } else {
- // Communication using Cable protocol is only supported for CTAP2 devices.
- protocols_.erase(
- device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
+ request_ = std::make_unique<device::GetAssertionRequestHandler>(
+ connector_, protocols_,
+ CreateCtapGetAssertionRequest(
+ ConstructClientDataHash(client_data_json_), std::move(options),
+ std::move(alternative_application_parameter)),
+ base::BindOnce(&AuthenticatorImpl::OnSignResponse,
+ weak_factory_.GetWeakPtr()),
+ base::BindOnce(&AuthenticatorImpl::MaybeCreatePlatformAuthenticator,
+ base::Unretained(this)));
+}
- u2f_request_ = device::U2fSign::TrySign(
- connector_, protocols_, handles,
- ConstructClientDataHash(client_data_json_), application_parameter,
- alternative_application_parameter,
- base::BindOnce(&AuthenticatorImpl::OnSignResponse,
- weak_factory_.GetWeakPtr()));
- }
+void AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable(
+ IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) {
+ bool result = false;
+#if defined(OS_MACOSX)
+ result = device::fido::mac::TouchIdAuthenticator::IsAvailable();
+#endif
+ std::move(callback).Run(result);
}
void AuthenticatorImpl::DidFinishNavigation(
NavigationHandle* navigation_handle) {
+ // If the RenderFrameHost itself is navigated then this function will cause
+ // request state to be cleaned up. It's also possible for a navigation in the
+ // same frame to use a fresh RenderFrameHost. In this case,
+ // |render_frame_host_->IsCurrent()| will start returning false, causing all
+ // focus checks to fail if any Mojo requests are made in that state.
if (!navigation_handle->HasCommitted() ||
navigation_handle->IsSameDocument() ||
navigation_handle->GetRenderFrameHost() != render_frame_host_) {
@@ -686,27 +616,14 @@ void AuthenticatorImpl::DidFinishNavigation(
Cleanup();
}
-void AuthenticatorImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
- // In tests, the AuthenticatorImpl may outlive the RenderFrameHost, although
- // this cannot happen in a non-test context because, normally,
- // AuthenticatorImpl is owned by RenderFrameHost.
- if (render_frame_host != render_frame_host_) {
- return;
- }
-
- binding_.Close();
- Cleanup();
-}
-
// Callback to handle the async registration response from a U2fDevice.
void AuthenticatorImpl::OnRegisterResponse(
device::FidoReturnCode status_code,
base::Optional<device::AuthenticatorMakeCredentialResponse> response_data) {
- if (!u2f_request_ && !ctap_request_) {
- // Either the callback has been called immediately (in which case
- // |u2f_request_| / |ctap_request_| won't have been set yet), or
- // |RenderFrameDeleted| / |DidFinishNavigation| noticed that this object has
- // been orphaned.
+ if (!request_) {
+ // Either the callback was called immediately and |request_| has not yet
+ // been assigned (this is a bug), or a navigation caused the request to be
+ // canceled while a callback was enqueued.
return;
}
@@ -717,14 +634,14 @@ void AuthenticatorImpl::OnRegisterResponse(
// |exclude_credentials|.
InvokeCallbackAndCleanup(
std::move(make_credential_response_callback_),
- webauth::mojom::AuthenticatorStatus::CREDENTIAL_EXCLUDED, nullptr,
+ blink::mojom::AuthenticatorStatus::CREDENTIAL_EXCLUDED, nullptr,
Focus::kDoCheck);
return;
case device::FidoReturnCode::kAuthenticatorResponseInvalid:
// The response from the authenticator was corrupted.
InvokeCallbackAndCleanup(
std::move(make_credential_response_callback_),
- webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
+ blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
Focus::kDoCheck);
return;
case device::FidoReturnCode::kUserConsentButCredentialNotRecognized:
@@ -734,21 +651,9 @@ void AuthenticatorImpl::OnRegisterResponse(
DCHECK(response_data.has_value());
if (attestation_preference_ !=
- webauth::mojom::AttestationConveyancePreference::NONE) {
- // Check for focus before (potentially) showing a permissions bubble
- // that might take focus.
- if (!GetContentClient()->browser()->IsFocused(
- WebContents::FromRenderFrameHost(render_frame_host_))) {
- InvokeCallbackAndCleanup(
- std::move(make_credential_response_callback_),
- webauth::mojom::AuthenticatorStatus::NOT_FOCUSED, nullptr,
- Focus::kDontCheck);
- return;
- }
-
- GetContentClient()->browser()->ShouldReturnAttestationForWebauthnRPID(
- render_frame_host_, relying_party_id_,
- render_frame_host_->GetLastCommittedOrigin(),
+ blink::mojom::AttestationConveyancePreference::NONE) {
+ request_delegate_->ShouldReturnAttestation(
+ relying_party_id_,
base::BindOnce(
&AuthenticatorImpl::OnRegisterResponseAttestationDecided,
weak_factory_.GetWeakPtr(), std::move(*response_data)));
@@ -758,7 +663,7 @@ void AuthenticatorImpl::OnRegisterResponse(
response_data->EraseAttestationStatement();
InvokeCallbackAndCleanup(
std::move(make_credential_response_callback_),
- webauth::mojom::AuthenticatorStatus::SUCCESS,
+ blink::mojom::AuthenticatorStatus::SUCCESS,
CreateMakeCredentialResponse(std::move(client_data_json_),
std::move(*response_data)),
Focus::kDoCheck);
@@ -770,24 +675,20 @@ void AuthenticatorImpl::OnRegisterResponse(
void AuthenticatorImpl::OnRegisterResponseAttestationDecided(
device::AuthenticatorMakeCredentialResponse response_data,
bool attestation_permitted) {
- DCHECK(attestation_preference_ !=
- webauth::mojom::AttestationConveyancePreference::NONE);
-
- if (!u2f_request_ && !ctap_request_) {
- // |DidFinishNavigation| / |RenderFrameDeleted| noticed that this object has
- // been orphaned.
+ if (!request_) {
+ // The request has already been cleaned up, probably because a navigation
+ // occured while the permissions prompt was pending.
return;
}
- // At this point, the final focus check has already been done because it's
- // possible that a permissions bubble might have focus and thus, if we did a
- // focus check, it would (incorrectly) fail.
+ DCHECK(attestation_preference_ !=
+ blink::mojom::AttestationConveyancePreference::NONE);
if (!attestation_permitted) {
InvokeCallbackAndCleanup(
std::move(make_credential_response_callback_),
- webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
- Focus::kDontCheck);
+ blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
+ Focus::kDoCheck);
return;
}
@@ -798,11 +699,8 @@ void AuthenticatorImpl::OnRegisterResponseAttestationDecided(
// requesting direct attestation then it knows that it was one of the tokens
// with inappropriate certs.
if (response_data.IsAttestationCertificateInappropriatelyIdentifying() &&
- !GetContentClient()
- ->browser()
- ->ShouldPermitIndividualAttestationForWebauthnRPID(
- render_frame_host_->GetProcess()->GetBrowserContext(),
- relying_party_id_)) {
+ !request_delegate_->ShouldPermitIndividualAttestation(
+ relying_party_id_)) {
// The attestation response is incorrectly individually identifiable, but
// the consent is for make & model information about a token, not for
// individually-identifiable information. Erase the attestation to stop it
@@ -816,20 +714,19 @@ void AuthenticatorImpl::OnRegisterResponseAttestationDecided(
InvokeCallbackAndCleanup(
std::move(make_credential_response_callback_),
- webauth::mojom::AuthenticatorStatus::SUCCESS,
+ blink::mojom::AuthenticatorStatus::SUCCESS,
CreateMakeCredentialResponse(std::move(client_data_json_),
std::move(response_data)),
- Focus::kDontCheck);
+ Focus::kDoCheck);
}
void AuthenticatorImpl::OnSignResponse(
device::FidoReturnCode status_code,
base::Optional<device::AuthenticatorGetAssertionResponse> response_data) {
- if (!u2f_request_ && !ctap_request_) {
- // Either the callback has been called immediately (in which case
- // |u2f_request_| / |ctap_request_| won't have been set yet), or
- // |DidFinishNavigation| / |RenderFrameDeleted| noticed that this object has
- // been orphaned.
+ if (!request_) {
+ // Either the callback was called immediately and |request_| has not yet
+ // been assigned (this is a bug), or a navigation caused the request to be
+ // canceled while a callback was enqueued.
return;
}
@@ -838,14 +735,14 @@ void AuthenticatorImpl::OnSignResponse(
// No authenticators contained the credential.
InvokeCallbackAndCleanup(
std::move(get_assertion_response_callback_),
- webauth::mojom::AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+ blink::mojom::AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
nullptr);
return;
case device::FidoReturnCode::kAuthenticatorResponseInvalid:
// The response from the authenticator was corrupted.
InvokeCallbackAndCleanup(
std::move(get_assertion_response_callback_),
- webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
+ blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
return;
case device::FidoReturnCode::kUserConsentButCredentialExcluded:
NOTREACHED();
@@ -854,7 +751,7 @@ void AuthenticatorImpl::OnSignResponse(
DCHECK(response_data.has_value());
InvokeCallbackAndCleanup(
std::move(get_assertion_response_callback_),
- webauth::mojom::AuthenticatorStatus::SUCCESS,
+ blink::mojom::AuthenticatorStatus::SUCCESS,
CreateGetAssertionResponse(std::move(client_data_json_),
std::move(*response_data),
echo_appid_extension_));
@@ -871,24 +768,22 @@ void AuthenticatorImpl::OnTimeout() {
if (make_credential_response_callback_) {
InvokeCallbackAndCleanup(
std::move(make_credential_response_callback_),
- webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
+ blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
Focus::kDontCheck);
} else if (get_assertion_response_callback_) {
InvokeCallbackAndCleanup(
std::move(get_assertion_response_callback_),
- webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
+ blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
}
}
void AuthenticatorImpl::InvokeCallbackAndCleanup(
MakeCredentialCallback callback,
- webauth::mojom::AuthenticatorStatus status,
- webauth::mojom::MakeCredentialAuthenticatorResponsePtr response,
+ blink::mojom::AuthenticatorStatus status,
+ blink::mojom::MakeCredentialAuthenticatorResponsePtr response,
Focus check_focus) {
- if (check_focus != Focus::kDontCheck &&
- !GetContentClient()->browser()->IsFocused(
- WebContents::FromRenderFrameHost(render_frame_host_))) {
- std::move(callback).Run(webauth::mojom::AuthenticatorStatus::NOT_FOCUSED,
+ if (check_focus != Focus::kDontCheck && !(request_delegate_ && IsFocused())) {
+ std::move(callback).Run(blink::mojom::AuthenticatorStatus::NOT_FOCUSED,
nullptr);
} else {
std::move(callback).Run(status, std::move(response));
@@ -899,20 +794,34 @@ void AuthenticatorImpl::InvokeCallbackAndCleanup(
void AuthenticatorImpl::InvokeCallbackAndCleanup(
GetAssertionCallback callback,
- webauth::mojom::AuthenticatorStatus status,
- webauth::mojom::GetAssertionAuthenticatorResponsePtr response) {
+ blink::mojom::AuthenticatorStatus status,
+ blink::mojom::GetAssertionAuthenticatorResponsePtr response) {
std::move(callback).Run(status, std::move(response));
Cleanup();
}
void AuthenticatorImpl::Cleanup() {
timer_->Stop();
- u2f_request_.reset();
- ctap_request_.reset();
+ request_.reset();
+ request_delegate_.reset();
make_credential_response_callback_.Reset();
get_assertion_response_callback_.Reset();
client_data_json_.clear();
echo_appid_extension_ = false;
}
+std::unique_ptr<device::FidoAuthenticator>
+AuthenticatorImpl::MaybeCreatePlatformAuthenticator() {
+#if defined(OS_MACOSX)
+ auto opt_authenticator_config =
+ request_delegate_->GetTouchIdAuthenticatorConfig();
+ if (opt_authenticator_config) {
+ return device::fido::mac::TouchIdAuthenticator::CreateIfAvailable(
+ std::move(opt_authenticator_config->keychain_access_group),
+ std::move(opt_authenticator_config->metadata_secret));
+ }
+#endif // defined(OS_MACOSX)
+ return nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/webauth/authenticator_impl.h b/chromium/content/browser/webauth/authenticator_impl.h
index 5fe89035a1a..538b06b559c 100644
--- a/chromium/content/browser/webauth/authenticator_impl.h
+++ b/chromium/content/browser/webauth/authenticator_impl.h
@@ -30,7 +30,7 @@ class OneShotTimer;
namespace device {
-class U2fRequest;
+class FidoAuthenticator;
class FidoRequestHandlerBase;
enum class FidoReturnCode : uint8_t;
@@ -47,6 +47,7 @@ class Origin;
namespace content {
+class AuthenticatorRequestClientDelegate;
class RenderFrameHost;
namespace client_data {
@@ -58,7 +59,7 @@ CONTENT_EXPORT extern const char kGetType[];
} // namespace client_data
// Implementation of the public Authenticator interface.
-class CONTENT_EXPORT AuthenticatorImpl : public webauth::mojom::Authenticator,
+class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
public WebContentsObserver {
public:
explicit AuthenticatorImpl(RenderFrameHost* render_frame_host);
@@ -76,7 +77,7 @@ class CONTENT_EXPORT AuthenticatorImpl : public webauth::mojom::Authenticator,
// Note that one AuthenticatorImpl instance can be bound to exactly one
// interface connection at a time, and disconnected when the frame navigates
// to a new active document.
- void Bind(webauth::mojom::AuthenticatorRequest request);
+ void Bind(blink::mojom::AuthenticatorRequest request);
private:
friend class AuthenticatorImplTest;
@@ -87,6 +88,8 @@ class CONTENT_EXPORT AuthenticatorImpl : public webauth::mojom::Authenticator,
kDontCheck,
};
+ bool IsFocused() const;
+
// Builds the CollectedClientData[1] dictionary with the given values,
// serializes it to JSON, and returns the resulting string.
// [1] https://w3c.github.io/webauthn/#dictdef-collectedclientdata
@@ -98,15 +101,15 @@ class CONTENT_EXPORT AuthenticatorImpl : public webauth::mojom::Authenticator,
// mojom:Authenticator
void MakeCredential(
- webauth::mojom::PublicKeyCredentialCreationOptionsPtr options,
+ blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
MakeCredentialCallback callback) override;
- void GetAssertion(
- webauth::mojom::PublicKeyCredentialRequestOptionsPtr options,
- GetAssertionCallback callback) override;
+ void GetAssertion(blink::mojom::PublicKeyCredentialRequestOptionsPtr options,
+ GetAssertionCallback callback) override;
+ void IsUserVerifyingPlatformAuthenticatorAvailable(
+ IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) override;
// WebContentsObserver:
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
- void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
// Callback to handle the async response from a U2fDevice.
void OnRegisterResponse(
@@ -130,25 +133,27 @@ class CONTENT_EXPORT AuthenticatorImpl : public webauth::mojom::Authenticator,
void InvokeCallbackAndCleanup(
MakeCredentialCallback callback,
- webauth::mojom::AuthenticatorStatus status,
- webauth::mojom::MakeCredentialAuthenticatorResponsePtr response,
+ blink::mojom::AuthenticatorStatus status,
+ blink::mojom::MakeCredentialAuthenticatorResponsePtr response,
Focus focus_check);
void InvokeCallbackAndCleanup(
GetAssertionCallback callback,
- webauth::mojom::AuthenticatorStatus status,
- webauth::mojom::GetAssertionAuthenticatorResponsePtr response);
+ blink::mojom::AuthenticatorStatus status,
+ blink::mojom::GetAssertionAuthenticatorResponsePtr response);
void Cleanup();
- RenderFrameHost* render_frame_host_;
+ std::unique_ptr<device::FidoAuthenticator> MaybeCreatePlatformAuthenticator();
+
+ RenderFrameHost* const render_frame_host_;
service_manager::Connector* connector_ = nullptr;
base::flat_set<device::FidoTransportProtocol> protocols_;
- std::unique_ptr<device::U2fRequest> u2f_request_;
- std::unique_ptr<device::FidoRequestHandlerBase> ctap_request_;
+ std::unique_ptr<device::FidoRequestHandlerBase> request_;
+ std::unique_ptr<AuthenticatorRequestClientDelegate> request_delegate_;
MakeCredentialCallback make_credential_response_callback_;
GetAssertionCallback get_assertion_response_callback_;
std::string client_data_json_;
- webauth::mojom::AttestationConveyancePreference attestation_preference_;
+ blink::mojom::AttestationConveyancePreference attestation_preference_;
std::string relying_party_id_;
std::unique_ptr<base::OneShotTimer> timer_;
@@ -159,7 +164,7 @@ class CONTENT_EXPORT AuthenticatorImpl : public webauth::mojom::Authenticator,
bool echo_appid_extension_ = false;
// Owns pipes to this Authenticator from |render_frame_host_|.
- mojo::Binding<webauth::mojom::Authenticator> binding_;
+ mojo::Binding<blink::mojom::Authenticator> binding_;
base::WeakPtrFactory<AuthenticatorImpl> weak_factory_;
diff --git a/chromium/content/browser/webauth/authenticator_impl_unittest.cc b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
index 26ad5fd258c..45908fea5bc 100644
--- a/chromium/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
@@ -9,6 +9,7 @@
#include <utility>
#include <vector>
+#include "base/bind_helpers.h"
#include "base/json/json_parser.h"
#include "base/json/json_writer.h"
#include "base/run_loop.h"
@@ -19,10 +20,12 @@
#include "base/time/time.h"
#include "components/cbor/cbor_reader.h"
#include "components/cbor/cbor_values.h"
+#include "content/public/browser/authenticator_request_client_delegate.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/content_features.h"
#include "content/public/test/test_service_manager_context.h"
#include "content/test/test_render_frame_host.h"
+#include "device/base/features.h"
#include "device/fido/fake_hid_impl_for_testing.h"
#include "device/fido/scoped_virtual_fido_device.h"
#include "device/fido/test_callback_receiver.h"
@@ -35,28 +38,28 @@ namespace content {
using ::testing::_;
+using blink::mojom::AttestationConveyancePreference;
+using blink::mojom::AuthenticatorPtr;
+using blink::mojom::AuthenticatorSelectionCriteria;
+using blink::mojom::AuthenticatorSelectionCriteriaPtr;
+using blink::mojom::AuthenticatorStatus;
+using blink::mojom::GetAssertionAuthenticatorResponsePtr;
+using blink::mojom::MakeCredentialAuthenticatorResponsePtr;
+using blink::mojom::PublicKeyCredentialCreationOptions;
+using blink::mojom::PublicKeyCredentialCreationOptionsPtr;
+using blink::mojom::PublicKeyCredentialDescriptor;
+using blink::mojom::PublicKeyCredentialDescriptorPtr;
+using blink::mojom::PublicKeyCredentialParameters;
+using blink::mojom::PublicKeyCredentialParametersPtr;
+using blink::mojom::PublicKeyCredentialRequestOptions;
+using blink::mojom::PublicKeyCredentialRequestOptionsPtr;
+using blink::mojom::PublicKeyCredentialRpEntity;
+using blink::mojom::PublicKeyCredentialRpEntityPtr;
+using blink::mojom::PublicKeyCredentialType;
+using blink::mojom::PublicKeyCredentialUserEntity;
+using blink::mojom::PublicKeyCredentialUserEntityPtr;
using cbor::CBORValue;
using cbor::CBORReader;
-using webauth::mojom::AttestationConveyancePreference;
-using webauth::mojom::AuthenticatorPtr;
-using webauth::mojom::AuthenticatorSelectionCriteria;
-using webauth::mojom::AuthenticatorSelectionCriteriaPtr;
-using webauth::mojom::AuthenticatorStatus;
-using webauth::mojom::GetAssertionAuthenticatorResponsePtr;
-using webauth::mojom::MakeCredentialAuthenticatorResponsePtr;
-using webauth::mojom::PublicKeyCredentialCreationOptions;
-using webauth::mojom::PublicKeyCredentialCreationOptionsPtr;
-using webauth::mojom::PublicKeyCredentialDescriptor;
-using webauth::mojom::PublicKeyCredentialDescriptorPtr;
-using webauth::mojom::PublicKeyCredentialParameters;
-using webauth::mojom::PublicKeyCredentialParametersPtr;
-using webauth::mojom::PublicKeyCredentialRequestOptions;
-using webauth::mojom::PublicKeyCredentialRequestOptionsPtr;
-using webauth::mojom::PublicKeyCredentialRpEntity;
-using webauth::mojom::PublicKeyCredentialRpEntityPtr;
-using webauth::mojom::PublicKeyCredentialType;
-using webauth::mojom::PublicKeyCredentialUserEntity;
-using webauth::mojom::PublicKeyCredentialUserEntityPtr;
namespace {
@@ -196,6 +199,7 @@ using TestMakeCredentialCallback = device::test::StatusAndValueCallbackReceiver<
using TestGetAssertionCallback = device::test::StatusAndValueCallbackReceiver<
AuthenticatorStatus,
GetAssertionAuthenticatorResponsePtr>;
+using TestRequestStartedCallback = device::test::TestCallbackReceiver<>;
std::vector<uint8_t> GetTestChallengeBytes() {
return std::vector<uint8_t>(std::begin(kTestChallengeBytes),
@@ -223,7 +227,7 @@ std::vector<PublicKeyCredentialParametersPtr>
GetTestPublicKeyCredentialParameters(int32_t algorithm_identifier) {
std::vector<PublicKeyCredentialParametersPtr> parameters;
auto fake_parameter = PublicKeyCredentialParameters::New();
- fake_parameter->type = webauth::mojom::PublicKeyCredentialType::PUBLIC_KEY;
+ fake_parameter->type = blink::mojom::PublicKeyCredentialType::PUBLIC_KEY;
fake_parameter->algorithm_identifier = algorithm_identifier;
parameters.push_back(std::move(fake_parameter));
return parameters;
@@ -232,10 +236,10 @@ GetTestPublicKeyCredentialParameters(int32_t algorithm_identifier) {
AuthenticatorSelectionCriteriaPtr GetTestAuthenticatorSelectionCriteria() {
auto criteria = AuthenticatorSelectionCriteria::New();
criteria->authenticator_attachment =
- webauth::mojom::AuthenticatorAttachment::NO_PREFERENCE;
+ blink::mojom::AuthenticatorAttachment::NO_PREFERENCE;
criteria->require_resident_key = false;
criteria->user_verification =
- webauth::mojom::UserVerificationRequirement::PREFERRED;
+ blink::mojom::UserVerificationRequirement::PREFERRED;
return criteria;
}
@@ -269,7 +273,7 @@ GetTestPublicKeyCredentialRequestOptions() {
options->challenge.assign(32, 0x0A);
options->adjusted_timeout = base::TimeDelta::FromMinutes(1);
options->user_verification =
- webauth::mojom::UserVerificationRequirement::PREFERRED;
+ blink::mojom::UserVerificationRequirement::PREFERRED;
options->allow_credentials = GetTestAllowCredentials();
return options;
}
@@ -282,6 +286,18 @@ class AuthenticatorImplTest : public content::RenderViewHostTestHarness {
~AuthenticatorImplTest() override {}
protected:
+ void TearDown() override {
+ // The |RenderFrameHost| must outlive |AuthenticatorImpl|.
+ authenticator_impl_.reset();
+ content::RenderViewHostTestHarness::TearDown();
+ }
+
+ void NavigateAndCommit(const GURL& url) {
+ // The |RenderFrameHost| must outlive |AuthenticatorImpl|.
+ authenticator_impl_.reset();
+ content::RenderViewHostTestHarness::NavigateAndCommit(url);
+ }
+
// Simulates navigating to a page and getting the page contents and language
// for that navigation.
void SimulateNavigation(const GURL& url) {
@@ -306,6 +322,24 @@ class AuthenticatorImplTest : public content::RenderViewHostTestHarness {
return authenticator;
}
+ AuthenticatorPtr ConstructAuthenticatorWithTimer(
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner) {
+ connector_ = service_manager::Connector::Create(&request_);
+ fake_hid_manager_ = std::make_unique<device::FakeHidManager>();
+ service_manager::Connector::TestApi test_api(connector_.get());
+ test_api.OverrideBinderForTesting(
+ service_manager::Identity(device::mojom::kServiceName),
+ device::mojom::HidManager::Name_,
+ base::Bind(&device::FakeHidManager::AddBinding,
+ base::Unretained(fake_hid_manager_.get())));
+
+ // Set up a timer for testing.
+ auto timer =
+ std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
+ timer->SetTaskRunner(task_runner);
+ return ConnectToAuthenticator(connector_.get(), std::move(timer));
+ }
+
url::Origin GetTestOrigin() {
const GURL test_relying_party_url(kTestOrigin1);
CHECK(test_relying_party_url.is_valid());
@@ -347,8 +381,11 @@ class AuthenticatorImplTest : public content::RenderViewHostTestHarness {
return base::ContainsKey(authenticator_impl_->protocols_, protocol);
}
- private:
+ protected:
std::unique_ptr<AuthenticatorImpl> authenticator_impl_;
+ service_manager::mojom::ConnectorRequest request_;
+ std::unique_ptr<service_manager::Connector> connector_;
+ std::unique_ptr<device::FakeHidManager> fake_hid_manager_;
};
// Verify behavior for various combinations of origins and RP IDs.
@@ -371,14 +408,18 @@ TEST_F(AuthenticatorImplTest, MakeCredentialOriginAndRpIds) {
EXPECT_EQ(AuthenticatorStatus::INVALID_DOMAIN, callback_receiver.status());
}
- // These instances pass the origin and relying party checks and return at
- // the algorithm check.
+ // These instances time out with NOT_ALLOWED_ERROR due to unsupported
+ // algorithm.
for (auto test_case : kValidRelyingPartyTestCases) {
SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
std::string(test_case.origin));
NavigateAndCommit(GURL(test_case.origin));
- AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
+
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
options->relying_party->id = test_case.claimed_authority;
@@ -387,17 +428,23 @@ TEST_F(AuthenticatorImplTest, MakeCredentialOriginAndRpIds) {
TestMakeCredentialCallback callback_receiver;
authenticator->MakeCredential(std::move(options),
callback_receiver.callback());
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::ALGORITHM_UNSUPPORTED,
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
callback_receiver.status());
}
}
-// Test that service returns ALGORITHM_UNSUPPORTED if no parameters contain
-// a supported algorithm.
+// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if no
+// parameters contain a supported algorithm.
TEST_F(AuthenticatorImplTest, MakeCredentialNoSupportedAlgorithm) {
SimulateNavigation(GURL(kTestOrigin1));
- AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
@@ -406,52 +453,68 @@ TEST_F(AuthenticatorImplTest, MakeCredentialNoSupportedAlgorithm) {
TestMakeCredentialCallback callback_receiver;
authenticator->MakeCredential(std::move(options),
callback_receiver.callback());
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::ALGORITHM_UNSUPPORTED,
- callback_receiver.status());
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
}
-// Test that service returns USER_VERIFICATION_UNSUPPORTED if user verification
-// is REQUIRED for get().
+// Test that service returns NOT_ALLOWED_ERROR if user verification is REQUIRED
+// for get().
TEST_F(AuthenticatorImplTest, GetAssertionUserVerification) {
SimulateNavigation(GURL(kTestOrigin1));
- AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
options->user_verification =
- webauth::mojom::UserVerificationRequirement::REQUIRED;
+ blink::mojom::UserVerificationRequirement::REQUIRED;
TestGetAssertionCallback callback_receiver;
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::USER_VERIFICATION_UNSUPPORTED,
- callback_receiver.status());
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
}
-// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if user
-// verification is REQUIRED for create().
+// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if user
+// verification is required for U2F devices.
TEST_F(AuthenticatorImplTest, MakeCredentialUserVerification) {
SimulateNavigation(GURL(kTestOrigin1));
- AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
options->authenticator_selection->user_verification =
- webauth::mojom::UserVerificationRequirement::REQUIRED;
+ blink::mojom::UserVerificationRequirement::REQUIRED;
TestMakeCredentialCallback callback_receiver;
authenticator->MakeCredential(std::move(options),
callback_receiver.callback());
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
- callback_receiver.status());
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
}
-// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if resident key
-// is requested for create().
+// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if resident
+// key is requested for U2F devices on create().
TEST_F(AuthenticatorImplTest, MakeCredentialResidentKey) {
SimulateNavigation(GURL(kTestOrigin1));
- AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
@@ -460,28 +523,34 @@ TEST_F(AuthenticatorImplTest, MakeCredentialResidentKey) {
TestMakeCredentialCallback callback_receiver;
authenticator->MakeCredential(std::move(options),
callback_receiver.callback());
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
- callback_receiver.status());
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
}
-// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if a platform
-// authenticator is requested for U2F.
+// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if a
+// platform authenticator is requested for U2F devices.
TEST_F(AuthenticatorImplTest, MakeCredentialPlatformAuthenticator) {
SimulateNavigation(GURL(kTestOrigin1));
- AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
options->authenticator_selection->authenticator_attachment =
- webauth::mojom::AuthenticatorAttachment::PLATFORM;
+ blink::mojom::AuthenticatorAttachment::PLATFORM;
TestMakeCredentialCallback callback_receiver;
authenticator->MakeCredential(std::move(options),
callback_receiver.callback());
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
- callback_receiver.status());
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
}
// Parses its arguments as JSON and expects that all the keys in the first are
@@ -557,26 +626,9 @@ TEST_F(AuthenticatorImplTest, TestMakeCredentialTimeout) {
GetTestPublicKeyCredentialCreationOptions();
TestMakeCredentialCallback callback_receiver;
- // Set up service_manager::Connector for tests.
- auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
- service_manager::mojom::ConnectorRequest request;
- auto connector = service_manager::Connector::Create(&request);
- service_manager::Connector::TestApi test_api(connector.get());
- test_api.OverrideBinderForTesting(
- service_manager::Identity(device::mojom::kServiceName),
- device::mojom::HidManager::Name_,
- base::Bind(&device::FakeHidManager::AddBinding,
- base::Unretained(fake_hid_manager.get())));
-
- // Set up a timer for testing.
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
- auto timer =
- std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
- timer->SetTaskRunner(task_runner);
- AuthenticatorPtr authenticator =
- ConnectToAuthenticator(connector.get(), std::move(timer));
-
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
authenticator->MakeCredential(std::move(options),
callback_receiver.callback());
@@ -661,26 +713,9 @@ TEST_F(AuthenticatorImplTest, TestGetAssertionTimeout) {
GetTestPublicKeyCredentialRequestOptions();
TestGetAssertionCallback callback_receiver;
- // Set up service_manager::Connector for tests.
- auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
- service_manager::mojom::ConnectorRequest request;
- auto connector = service_manager::Connector::Create(&request);
- service_manager::Connector::TestApi test_api(connector.get());
- test_api.OverrideBinderForTesting(
- service_manager::Identity(device::mojom::kServiceName),
- device::mojom::HidManager::Name_,
- base::Bind(&device::FakeHidManager::AddBinding,
- base::Unretained(fake_hid_manager.get())));
-
- // Set up a timer for testing.
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
- auto timer =
- std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
- timer->SetTaskRunner(task_runner);
- AuthenticatorPtr authenticator =
- ConnectToAuthenticator(connector.get(), std::move(timer));
-
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
// Trigger timer.
@@ -735,8 +770,7 @@ TEST_F(AuthenticatorImplTest, TestCableDiscoveryEnabledWithSwitch) {
TestServiceManagerContext service_manager_context;
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeatures(
- std::vector<base::Feature>{features::kWebAuthCtap2,
- features::kWebAuthCable},
+ std::vector<base::Feature>{features::kWebAuthCable},
std::vector<base::Feature>{});
SimulateNavigation(GURL(kTestOrigin1));
@@ -744,25 +778,9 @@ TEST_F(AuthenticatorImplTest, TestCableDiscoveryEnabledWithSwitch) {
GetTestPublicKeyCredentialRequestOptions();
TestGetAssertionCallback callback_receiver;
- // Set up service_manager::Connector for tests.
- auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
- service_manager::mojom::ConnectorRequest request;
- auto connector = service_manager::Connector::Create(&request);
- service_manager::Connector::TestApi test_api(connector.get());
- test_api.OverrideBinderForTesting(
- service_manager::Identity(device::mojom::kServiceName),
- device::mojom::HidManager::Name_,
- base::Bind(&device::FakeHidManager::AddBinding,
- base::Unretained(fake_hid_manager.get())));
-
- // Set up a timer for testing.
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
- auto timer =
- std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
- timer->SetTaskRunner(task_runner);
- AuthenticatorPtr authenticator =
- ConnectToAuthenticator(connector.get(), std::move(timer));
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
// Trigger timer.
@@ -777,35 +795,16 @@ TEST_F(AuthenticatorImplTest, TestCableDiscoveryEnabledWithSwitch) {
TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledForMakeCredential) {
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatures(
- std::vector<base::Feature>{features::kWebAuthCtap2,
- features::kWebAuthCable},
- std::vector<base::Feature>{});
+ scoped_feature_list.InitAndEnableFeature(features::kWebAuthCable);
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
TestMakeCredentialCallback callback_receiver;
- // Set up service_manager::Connector for tests.
- auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
- service_manager::mojom::ConnectorRequest request;
- auto connector = service_manager::Connector::Create(&request);
- service_manager::Connector::TestApi test_api(connector.get());
- test_api.OverrideBinderForTesting(
- service_manager::Identity(device::mojom::kServiceName),
- device::mojom::HidManager::Name_,
- base::Bind(&device::FakeHidManager::AddBinding,
- base::Unretained(fake_hid_manager.get())));
-
- // Set up a timer for testing.
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
- auto timer =
- std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
- timer->SetTaskRunner(task_runner);
- AuthenticatorPtr authenticator =
- ConnectToAuthenticator(connector.get(), std::move(timer));
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
authenticator->MakeCredential(std::move(options),
callback_receiver.callback());
@@ -820,33 +819,14 @@ TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledForMakeCredential) {
}
TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithoutSwitch) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(features::kWebAuthCtap2);
-
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
TestGetAssertionCallback callback_receiver;
- // Set up service_manager::Connector for tests.
- auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
- service_manager::mojom::ConnectorRequest request;
- auto connector = service_manager::Connector::Create(&request);
- service_manager::Connector::TestApi test_api(connector.get());
- test_api.OverrideBinderForTesting(
- service_manager::Identity(device::mojom::kServiceName),
- device::mojom::HidManager::Name_,
- base::Bind(&device::FakeHidManager::AddBinding,
- base::Unretained(fake_hid_manager.get())));
-
- // Set up a timer for testing.
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
- auto timer =
- std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
- timer->SetTaskRunner(task_runner);
- AuthenticatorPtr authenticator =
- ConnectToAuthenticator(connector.get(), std::move(timer));
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
// Trigger timer.
@@ -859,97 +839,37 @@ TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithoutSwitch) {
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
}
-TEST_F(AuthenticatorImplTest, TestU2fDeviceDoesNotSupportMakeCredential) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(features::kWebAuthCtap2);
-
- SimulateNavigation(GURL(kTestOrigin1));
- PublicKeyCredentialCreationOptionsPtr options =
- GetTestPublicKeyCredentialCreationOptions();
- TestMakeCredentialCallback callback_receiver;
-
- // Set up service_manager::Connector for tests.
- auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
- service_manager::mojom::ConnectorRequest request;
- auto connector = service_manager::Connector::Create(&request);
-
- // Set up a timer for testing.
- auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
- base::Time::Now(), base::TimeTicks::Now());
- auto timer =
- std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
- timer->SetTaskRunner(task_runner);
- AuthenticatorPtr authenticator =
- ConnectToAuthenticator(connector.get(), std::move(timer));
-
- device::test::ScopedVirtualFidoDevice virtual_device;
- authenticator->MakeCredential(std::move(options),
- callback_receiver.callback());
-
- // Trigger timer.
- base::RunLoop().RunUntilIdle();
- task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
- callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
-}
-
-TEST_F(AuthenticatorImplTest, TestU2fDeviceDoesNotSupportGetAssertion) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(features::kWebAuthCtap2);
-
+TEST_F(AuthenticatorImplTest, TestGetAssertionU2fDeviceBackwardsCompatibility) {
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
TestGetAssertionCallback callback_receiver;
-
- // Set up service_manager::Connector for tests.
- auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
- service_manager::mojom::ConnectorRequest request;
- auto connector = service_manager::Connector::Create(&request);
-
- // Set up a timer for testing.
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
- auto timer =
- std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
- timer->SetTaskRunner(task_runner);
- AuthenticatorPtr authenticator =
- ConnectToAuthenticator(connector.get(), std::move(timer));
-
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
device::test::ScopedVirtualFidoDevice virtual_device;
+ // Inject credential ID to the virtual device so that successful sign in is
+ // possible.
+ ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ options->allow_credentials[0]->id, kTestRelyingPartyId));
+
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
// Trigger timer.
- base::RunLoop().RunUntilIdle();
- task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
+ EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
}
-TEST_F(AuthenticatorImplTest, Ctap2AcceptsEmptyAllowCredentials) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(features::kWebAuthCtap2);
-
+TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) {
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
options->allow_credentials.clear();
TestGetAssertionCallback callback_receiver;
- // Set up service_manager::Connector for tests.
- auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
- service_manager::mojom::ConnectorRequest request;
- auto connector = service_manager::Connector::Create(&request);
-
- // Set up a timer for testing.
auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::Time::Now(), base::TimeTicks::Now());
- auto timer =
- std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
- timer->SetTaskRunner(task_runner);
- AuthenticatorPtr authenticator =
- ConnectToAuthenticator(connector.get(), std::move(timer));
-
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
device::test::ScopedVirtualFidoDevice virtual_device;
authenticator->GetAssertion(std::move(options), callback_receiver.callback());
@@ -957,26 +877,7 @@ TEST_F(AuthenticatorImplTest, Ctap2AcceptsEmptyAllowCredentials) {
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
- // Doesn't error out with EMPTY_ALLOW_CREDENTIALS but continues to a
- // NOT_ALLOWED_ERROR.
- EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
-}
-
-TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) {
- device::test::ScopedVirtualFidoDevice scoped_virtual_device;
- TestServiceManagerContext service_manager_context;
-
- SimulateNavigation(GURL(kTestOrigin1));
- AuthenticatorPtr authenticator = ConnectToAuthenticator();
- PublicKeyCredentialRequestOptionsPtr options =
- GetTestPublicKeyCredentialRequestOptions();
- options->allow_credentials.clear();
-
- TestGetAssertionCallback callback_receiver;
- authenticator->GetAssertion(std::move(options), callback_receiver.callback());
- callback_receiver.WaitForCallback();
-
- EXPECT_EQ(AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS,
+ EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
callback_receiver.status());
}
@@ -1028,6 +929,8 @@ TEST_F(AuthenticatorImplTest, MakeCredentialPendingRequest) {
callback_receiver2.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, callback_receiver2.status());
+
+ callback_receiver.WaitForCallback();
}
TEST_F(AuthenticatorImplTest, GetAssertionPendingRequest) {
@@ -1054,6 +957,41 @@ TEST_F(AuthenticatorImplTest, GetAssertionPendingRequest) {
callback_receiver2.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, callback_receiver2.status());
+
+ callback_receiver.WaitForCallback();
+}
+
+TEST_F(AuthenticatorImplTest, NavigationDuringOperation) {
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ TestServiceManagerContext service_manager_context;
+
+ SimulateNavigation(GURL(kTestOrigin1));
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ base::RunLoop run_loop;
+ authenticator.set_connection_error_handler(run_loop.QuitClosure());
+
+ // Make first request.
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+
+ // Delete the |AuthenticatorImpl| during the registration operation to
+ // simulate a navigation while waiting for the user to press the token.
+ scoped_virtual_device.mutable_state()->simulate_press_callback =
+ base::BindRepeating(
+ [](std::unique_ptr<AuthenticatorImpl>* ptr) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(
+ [](std::unique_ptr<AuthenticatorImpl>* ptr) {
+ ptr->reset();
+ },
+ ptr));
+ },
+ &authenticator_impl_);
+
+ run_loop.Run();
}
TEST_F(AuthenticatorImplTest, InvalidResponse) {
@@ -1061,9 +999,11 @@ TEST_F(AuthenticatorImplTest, InvalidResponse) {
TestServiceManagerContext service_manager_context;
scoped_virtual_device.mutable_state()->simulate_invalid_response = true;
-
SimulateNavigation(GURL(kTestOrigin1));
- AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
{
PublicKeyCredentialRequestOptionsPtr options =
@@ -1071,8 +1011,10 @@ TEST_F(AuthenticatorImplTest, InvalidResponse) {
TestGetAssertionCallback callback_receiver;
authenticator->GetAssertion(std::move(options),
callback_receiver.callback());
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
-
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
callback_receiver.status());
}
@@ -1083,8 +1025,10 @@ TEST_F(AuthenticatorImplTest, InvalidResponse) {
TestMakeCredentialCallback callback_receiver;
authenticator->MakeCredential(std::move(options),
callback_receiver.callback());
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
-
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
callback_receiver.status());
}
@@ -1100,44 +1044,74 @@ enum class AttestationConsent {
DENIED,
};
-// Implements ContentBrowserClient and allows webauthn-related calls to be
-// mocked.
-class AuthenticatorTestContentBrowserClient : public ContentBrowserClient {
+class TestAuthenticatorRequestDelegate
+ : public AuthenticatorRequestClientDelegate {
public:
- bool ShouldPermitIndividualAttestationForWebauthnRPID(
- content::BrowserContext* browser_context,
- const std::string& rp_id) override {
+ TestAuthenticatorRequestDelegate(RenderFrameHost* render_frame_host,
+ base::OnceClosure did_start_request_callback,
+ IndividualAttestation individual_attestation,
+ AttestationConsent attestation_consent,
+ bool is_focused)
+ : did_start_request_callback_(std::move(did_start_request_callback)),
+ individual_attestation_(individual_attestation),
+ attestation_consent_(attestation_consent),
+ is_focused_(is_focused) {}
+ ~TestAuthenticatorRequestDelegate() override {}
+
+ void DidStartRequest() override {
+ ASSERT_TRUE(did_start_request_callback_) << "DidStartRequest called twice.";
+ std::move(did_start_request_callback_).Run();
+ }
+
+ bool ShouldPermitIndividualAttestation(
+ const std::string& relying_party_id) override {
return individual_attestation_ == IndividualAttestation::REQUESTED;
}
- void ShouldReturnAttestationForWebauthnRPID(
- content::RenderFrameHost* rfh,
- const std::string& rp_id,
- const url::Origin& origin,
+ void ShouldReturnAttestation(
+ const std::string& relying_party_id,
base::OnceCallback<void(bool)> callback) override {
std::move(callback).Run(attestation_consent_ ==
AttestationConsent::GRANTED);
}
- bool IsFocused(content::WebContents* web_contents) override {
- return focused_;
- }
+ bool IsFocused() override { return is_focused_; }
- void set_individual_attestation(IndividualAttestation value) {
- individual_attestation_ = value;
- }
+ base::OnceClosure did_start_request_callback_;
+ const IndividualAttestation individual_attestation_;
+ const AttestationConsent attestation_consent_;
+ const bool is_focused_;
- void set_attestation_consent(AttestationConsent value) {
- attestation_consent_ = value;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestAuthenticatorRequestDelegate);
+};
+
+class TestAuthenticatorContentBrowserClient : public ContentBrowserClient {
+ public:
+ std::unique_ptr<AuthenticatorRequestClientDelegate>
+ GetWebAuthenticationRequestDelegate(
+ RenderFrameHost* render_frame_host) override {
+ if (return_null_delegate)
+ return nullptr;
+ return std::make_unique<TestAuthenticatorRequestDelegate>(
+ render_frame_host,
+ request_started_callback ? std::move(request_started_callback)
+ : base::DoNothing(),
+ individual_attestation, attestation_consent, is_focused);
}
- void set_focused(bool is_focused) { focused_ = is_focused; }
+ // If set, this closure will be called when the subsequently constructed
+ // delegate is informed that the request has started.
+ base::OnceClosure request_started_callback;
- private:
- IndividualAttestation individual_attestation_ =
+ IndividualAttestation individual_attestation =
IndividualAttestation::NOT_REQUESTED;
- AttestationConsent attestation_consent_ = AttestationConsent::DENIED;
- bool focused_ = true;
+ AttestationConsent attestation_consent = AttestationConsent::DENIED;
+ bool is_focused = true;
+
+ // This emulates scenarios where a nullptr RequestClientDelegate is returned
+ // because a request is already in progress.
+ bool return_null_delegate = false;
};
// A test class that installs and removes an
@@ -1183,8 +1157,8 @@ class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
AttestationConveyancePreferenceToString(test.attestation_requested));
SCOPED_TRACE(i);
- test_client_.set_individual_attestation(test.individual_attestation);
- test_client_.set_attestation_consent(test.attestation_consent);
+ test_client_.individual_attestation = test.individual_attestation;
+ test_client_.attestation_consent = test.attestation_consent;
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
@@ -1217,7 +1191,7 @@ class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
}
protected:
- AuthenticatorTestContentBrowserClient test_client_;
+ TestAuthenticatorContentBrowserClient test_client_;
device::test::ScopedVirtualFidoDevice virtual_device_;
private:
@@ -1230,6 +1204,8 @@ class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
return "indirect";
case AttestationConveyancePreference::DIRECT:
return "direct";
+ case AttestationConveyancePreference::ENTERPRISE:
+ return "enterprise";
default:
NOTREACHED();
return "";
@@ -1311,7 +1287,7 @@ TEST_F(AuthenticatorContentBrowserClientTest, AttestationBehaviour) {
{
AttestationConveyancePreference::INDIRECT,
IndividualAttestation::REQUESTED, AttestationConsent::GRANTED,
- AuthenticatorStatus::SUCCESS, "fido-u2f", kIndividualCommonName,
+ AuthenticatorStatus::SUCCESS, "fido-u2f", kStandardCommonName,
},
{
AttestationConveyancePreference::DIRECT,
@@ -1331,6 +1307,26 @@ TEST_F(AuthenticatorContentBrowserClientTest, AttestationBehaviour) {
{
AttestationConveyancePreference::DIRECT,
IndividualAttestation::REQUESTED, AttestationConsent::GRANTED,
+ AuthenticatorStatus::SUCCESS, "fido-u2f", kStandardCommonName,
+ },
+ {
+ AttestationConveyancePreference::ENTERPRISE,
+ IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, "", "",
+ },
+ {
+ AttestationConveyancePreference::ENTERPRISE,
+ IndividualAttestation::REQUESTED, AttestationConsent::DENIED,
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, "", "",
+ },
+ {
+ AttestationConveyancePreference::ENTERPRISE,
+ IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED,
+ AuthenticatorStatus::SUCCESS, "fido-u2f", kStandardCommonName,
+ },
+ {
+ AttestationConveyancePreference::ENTERPRISE,
+ IndividualAttestation::REQUESTED, AttestationConsent::GRANTED,
AuthenticatorStatus::SUCCESS, "fido-u2f", kIndividualCommonName,
},
};
@@ -1352,7 +1348,7 @@ TEST_F(AuthenticatorContentBrowserClientTest,
const std::vector<TestCase> kTests = {
{
- AttestationConveyancePreference::DIRECT,
+ AttestationConveyancePreference::ENTERPRISE,
IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
AuthenticatorStatus::NOT_ALLOWED_ERROR, "", "",
},
@@ -1366,7 +1362,17 @@ TEST_F(AuthenticatorContentBrowserClientTest,
"none", "",
},
{
- AttestationConveyancePreference::DIRECT,
+ AttestationConveyancePreference::ENTERPRISE,
+ IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED,
+ AuthenticatorStatus::SUCCESS,
+ // If individual attestation was not requested then the attestation
+ // certificate will be removed, even if consent is given, because
+ // the consent isn't to be tracked.
+ "none", "",
+ },
+
+ {
+ AttestationConveyancePreference::ENTERPRISE,
IndividualAttestation::REQUESTED, AttestationConsent::GRANTED,
AuthenticatorStatus::SUCCESS, "fido-u2f", kCommonName,
},
@@ -1380,11 +1386,41 @@ TEST_F(AuthenticatorContentBrowserClientTest,
RunTestCases(kTests);
}
+TEST_F(AuthenticatorContentBrowserClientTest,
+ MakeCredentialRequestStartedCallback) {
+ TestServiceManagerContext smc;
+ NavigateAndCommit(GURL(kTestOrigin1));
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ PublicKeyCredentialCreationOptionsPtr options =
+ GetTestPublicKeyCredentialCreationOptions();
+
+ TestRequestStartedCallback request_started;
+ test_client_.request_started_callback = request_started.callback();
+ authenticator->MakeCredential(std::move(options), base::DoNothing());
+ request_started.WaitForCallback();
+}
+
+TEST_F(AuthenticatorContentBrowserClientTest,
+ GetAssertionRequestStartedCallback) {
+ TestServiceManagerContext smc;
+ NavigateAndCommit(GURL(kTestOrigin1));
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+
+ TestRequestStartedCallback request_started;
+ test_client_.request_started_callback = request_started.callback();
+ authenticator->GetAssertion(std::move(options), base::DoNothing());
+ request_started.WaitForCallback();
+}
+
TEST_F(AuthenticatorContentBrowserClientTest, Unfocused) {
// When the |ContentBrowserClient| considers the tab to be unfocused,
// registration requests should fail with a |NOT_FOCUSED| error, but getting
// assertions should still work.
- test_client_.set_focused(false);
+ test_client_.is_focused = false;
NavigateAndCommit(GURL(kTestOrigin1));
AuthenticatorPtr authenticator = ConnectToAuthenticator();
@@ -1395,9 +1431,14 @@ TEST_F(AuthenticatorContentBrowserClientTest, Unfocused) {
options->public_key_parameters = GetTestPublicKeyCredentialParameters(123);
TestMakeCredentialCallback cb;
+ TestRequestStartedCallback request_started;
+ test_client_.request_started_callback = request_started.callback();
+
authenticator->MakeCredential(std::move(options), cb.callback());
cb.WaitForCallback();
+
EXPECT_EQ(AuthenticatorStatus::NOT_FOCUSED, cb.status());
+ EXPECT_FALSE(request_started.was_called());
}
{
@@ -1414,10 +1455,42 @@ TEST_F(AuthenticatorContentBrowserClientTest, Unfocused) {
options->allow_credentials.emplace_back(std::move(credential));
TestGetAssertionCallback cb;
+ TestRequestStartedCallback request_started;
+ test_client_.request_started_callback = request_started.callback();
+
authenticator->GetAssertion(std::move(options), cb.callback());
cb.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::SUCCESS, cb.status());
+ EXPECT_TRUE(request_started.was_called());
+ }
+}
+
+TEST_F(AuthenticatorContentBrowserClientTest,
+ NullDelegate_RejectsWithPendingRequest) {
+ test_client_.return_null_delegate = true;
+
+ NavigateAndCommit(GURL(kTestOrigin1));
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ {
+ PublicKeyCredentialCreationOptionsPtr options =
+ GetTestPublicKeyCredentialCreationOptions();
+
+ TestMakeCredentialCallback cb;
+ authenticator->MakeCredential(std::move(options), cb.callback());
+ cb.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, cb.status());
+ }
+
+ {
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+
+ TestGetAssertionCallback cb;
+ authenticator->GetAssertion(std::move(options), cb.callback());
+ cb.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, cb.status());
}
}
diff --git a/chromium/content/browser/webauth/authenticator_type_converters.cc b/chromium/content/browser/webauth/authenticator_type_converters.cc
index 47f14b163a7..28985e8756f 100644
--- a/chromium/content/browser/webauth/authenticator_type_converters.cc
+++ b/chromium/content/browser/webauth/authenticator_type_converters.cc
@@ -11,16 +11,16 @@
namespace mojo {
-using ::webauth::mojom::PublicKeyCredentialUserEntityPtr;
-using ::webauth::mojom::PublicKeyCredentialRpEntityPtr;
-using ::webauth::mojom::AuthenticatorTransport;
-using ::webauth::mojom::PublicKeyCredentialType;
-using ::webauth::mojom::PublicKeyCredentialParametersPtr;
-using ::webauth::mojom::PublicKeyCredentialDescriptorPtr;
-using ::webauth::mojom::AuthenticatorSelectionCriteriaPtr;
-using ::webauth::mojom::AuthenticatorAttachment;
-using ::webauth::mojom::UserVerificationRequirement;
-using ::webauth::mojom::CableAuthenticationPtr;
+using ::blink::mojom::PublicKeyCredentialUserEntityPtr;
+using ::blink::mojom::PublicKeyCredentialRpEntityPtr;
+using ::blink::mojom::AuthenticatorTransport;
+using ::blink::mojom::PublicKeyCredentialType;
+using ::blink::mojom::PublicKeyCredentialParametersPtr;
+using ::blink::mojom::PublicKeyCredentialDescriptorPtr;
+using ::blink::mojom::AuthenticatorSelectionCriteriaPtr;
+using ::blink::mojom::AuthenticatorAttachment;
+using ::blink::mojom::UserVerificationRequirement;
+using ::blink::mojom::CableAuthenticationPtr;
// static
::device::FidoTransportProtocol
@@ -88,7 +88,7 @@ TypeConverter<std::vector<::device::PublicKeyCredentialDescriptor>,
::device::UserVerificationRequirement
TypeConverter<::device::UserVerificationRequirement,
UserVerificationRequirement>::
- Convert(const ::webauth::mojom::UserVerificationRequirement& input) {
+ Convert(const UserVerificationRequirement& input) {
switch (input) {
case UserVerificationRequirement::PREFERRED:
return ::device::UserVerificationRequirement::kPreferred;
@@ -180,13 +180,13 @@ TypeConverter<std::vector<::device::FidoCableDiscovery::CableDiscoveryData>,
std::copy(data->authenticator_eid.begin(), data->authenticator_eid.end(),
authenticator_eid.begin());
- ::device::FidoCableDiscovery::SessionKeyArray session_key;
- DCHECK_EQ(session_key.size(), data->session_pre_key.size());
+ ::device::FidoCableDiscovery::SessionPreKeyArray session_pre_key;
+ DCHECK_EQ(session_pre_key.size(), data->session_pre_key.size());
std::copy(data->session_pre_key.begin(), data->session_pre_key.end(),
- session_key.begin());
+ session_pre_key.begin());
discovery_data.push_back(::device::FidoCableDiscovery::CableDiscoveryData{
- data->version, client_eid, authenticator_eid, session_key});
+ data->version, client_eid, authenticator_eid, session_pre_key});
}
return discovery_data;
diff --git a/chromium/content/browser/webauth/authenticator_type_converters.h b/chromium/content/browser/webauth/authenticator_type_converters.h
index 97431318615..cc4a53db728 100644
--- a/chromium/content/browser/webauth/authenticator_type_converters.h
+++ b/chromium/content/browser/webauth/authenticator_type_converters.h
@@ -24,78 +24,78 @@ namespace mojo {
template <>
struct TypeConverter<::device::FidoTransportProtocol,
- ::webauth::mojom::AuthenticatorTransport> {
+ ::blink::mojom::AuthenticatorTransport> {
static ::device::FidoTransportProtocol Convert(
- const ::webauth::mojom::AuthenticatorTransport& input);
+ const ::blink::mojom::AuthenticatorTransport& input);
};
template <>
struct TypeConverter<::device::CredentialType,
- ::webauth::mojom::PublicKeyCredentialType> {
+ ::blink::mojom::PublicKeyCredentialType> {
static ::device::CredentialType Convert(
- const ::webauth::mojom::PublicKeyCredentialType& input);
+ const ::blink::mojom::PublicKeyCredentialType& input);
};
template <>
struct TypeConverter<
std::vector<::device::PublicKeyCredentialParams::CredentialInfo>,
- std::vector<::webauth::mojom::PublicKeyCredentialParametersPtr>> {
+ std::vector<::blink::mojom::PublicKeyCredentialParametersPtr>> {
static std::vector<::device::PublicKeyCredentialParams::CredentialInfo>
- Convert(const std::vector<::webauth::mojom::PublicKeyCredentialParametersPtr>&
+ Convert(const std::vector<::blink::mojom::PublicKeyCredentialParametersPtr>&
input);
};
template <>
struct TypeConverter<
std::vector<::device::PublicKeyCredentialDescriptor>,
- std::vector<::webauth::mojom::PublicKeyCredentialDescriptorPtr>> {
+ std::vector<::blink::mojom::PublicKeyCredentialDescriptorPtr>> {
static std::vector<::device::PublicKeyCredentialDescriptor> Convert(
- const std::vector<::webauth::mojom::PublicKeyCredentialDescriptorPtr>&
+ const std::vector<::blink::mojom::PublicKeyCredentialDescriptorPtr>&
input);
};
template <>
struct TypeConverter<
::device::AuthenticatorSelectionCriteria::AuthenticatorAttachment,
- ::webauth::mojom::AuthenticatorAttachment> {
+ ::blink::mojom::AuthenticatorAttachment> {
static ::device::AuthenticatorSelectionCriteria::AuthenticatorAttachment
- Convert(const ::webauth::mojom::AuthenticatorAttachment& input);
+ Convert(const ::blink::mojom::AuthenticatorAttachment& input);
};
template <>
struct TypeConverter<::device::UserVerificationRequirement,
- ::webauth::mojom::UserVerificationRequirement> {
+ ::blink::mojom::UserVerificationRequirement> {
static ::device::UserVerificationRequirement Convert(
- const ::webauth::mojom::UserVerificationRequirement& input);
+ const ::blink::mojom::UserVerificationRequirement& input);
};
template <>
struct TypeConverter<::device::AuthenticatorSelectionCriteria,
- ::webauth::mojom::AuthenticatorSelectionCriteriaPtr> {
+ ::blink::mojom::AuthenticatorSelectionCriteriaPtr> {
static ::device::AuthenticatorSelectionCriteria Convert(
- const ::webauth::mojom::AuthenticatorSelectionCriteriaPtr& input);
+ const ::blink::mojom::AuthenticatorSelectionCriteriaPtr& input);
};
template <>
struct TypeConverter<::device::PublicKeyCredentialRpEntity,
- ::webauth::mojom::PublicKeyCredentialRpEntityPtr> {
+ ::blink::mojom::PublicKeyCredentialRpEntityPtr> {
static ::device::PublicKeyCredentialRpEntity Convert(
- const ::webauth::mojom::PublicKeyCredentialRpEntityPtr& input);
+ const ::blink::mojom::PublicKeyCredentialRpEntityPtr& input);
};
template <>
struct TypeConverter<::device::PublicKeyCredentialUserEntity,
- ::webauth::mojom::PublicKeyCredentialUserEntityPtr> {
+ ::blink::mojom::PublicKeyCredentialUserEntityPtr> {
static ::device::PublicKeyCredentialUserEntity Convert(
- const ::webauth::mojom::PublicKeyCredentialUserEntityPtr& input);
+ const ::blink::mojom::PublicKeyCredentialUserEntityPtr& input);
};
template <>
struct TypeConverter<
std::vector<::device::FidoCableDiscovery::CableDiscoveryData>,
- std::vector<::webauth::mojom::CableAuthenticationPtr>> {
+ std::vector<::blink::mojom::CableAuthenticationPtr>> {
static std::vector<::device::FidoCableDiscovery::CableDiscoveryData> Convert(
- const std::vector<::webauth::mojom::CableAuthenticationPtr>& input);
+ const std::vector<::blink::mojom::CableAuthenticationPtr>& input);
};
} // namespace mojo
diff --git a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc b/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc
index 630260d0cf8..3f3d4a2df33 100644
--- a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc
+++ b/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc
@@ -15,9 +15,9 @@ namespace content {
namespace {
-webauth::test::mojom::VirtualAuthenticatorPtr GetMojoPtrToVirtualAuthenticator(
+blink::test::mojom::VirtualAuthenticatorPtr GetMojoPtrToVirtualAuthenticator(
VirtualAuthenticator* authenticator) {
- webauth::test::mojom::VirtualAuthenticatorPtr mojo_authenticator_ptr;
+ blink::test::mojom::VirtualAuthenticatorPtr mojo_authenticator_ptr;
authenticator->AddBinding(mojo::MakeRequest(&mojo_authenticator_ptr));
return mojo_authenticator_ptr;
}
@@ -37,12 +37,12 @@ ScopedVirtualAuthenticatorEnvironment::
~ScopedVirtualAuthenticatorEnvironment() = default;
void ScopedVirtualAuthenticatorEnvironment::AddBinding(
- webauth::test::mojom::VirtualAuthenticatorManagerRequest request) {
+ blink::test::mojom::VirtualAuthenticatorManagerRequest request) {
bindings_.AddBinding(this, std::move(request));
}
void ScopedVirtualAuthenticatorEnvironment::CreateAuthenticator(
- webauth::test::mojom::VirtualAuthenticatorOptionsPtr options,
+ blink::test::mojom::VirtualAuthenticatorOptionsPtr options,
CreateAuthenticatorCallback callback) {
auto authenticator = std::make_unique<VirtualAuthenticator>(
mojo::ConvertTo<::device::FidoTransportProtocol>(options->transport));
@@ -61,7 +61,7 @@ void ScopedVirtualAuthenticatorEnvironment::CreateAuthenticator(
void ScopedVirtualAuthenticatorEnvironment::GetAuthenticators(
GetAuthenticatorsCallback callback) {
- std::vector<webauth::test::mojom::VirtualAuthenticatorPtrInfo>
+ std::vector<blink::test::mojom::VirtualAuthenticatorPtrInfo>
mojo_authenticators;
for (auto& authenticator : authenticators_) {
mojo_authenticators.push_back(
diff --git a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h b/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h
index 142f6f2af32..378de2ff2db 100644
--- a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h
+++ b/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h
@@ -31,21 +31,21 @@ class VirtualFidoDiscovery;
// lifetime of the browser process and shared by all frames in all WebContents
// and across all BrowserContexts.
class CONTENT_EXPORT ScopedVirtualAuthenticatorEnvironment
- : public webauth::test::mojom::VirtualAuthenticatorManager,
+ : public blink::test::mojom::VirtualAuthenticatorManager,
protected device::internal::ScopedFidoDiscoveryFactory {
public:
static ScopedVirtualAuthenticatorEnvironment* GetInstance();
void AddBinding(
- webauth::test::mojom::VirtualAuthenticatorManagerRequest request);
+ blink::test::mojom::VirtualAuthenticatorManagerRequest request);
protected:
ScopedVirtualAuthenticatorEnvironment();
~ScopedVirtualAuthenticatorEnvironment() override;
- // webauth::test::mojom::VirtualAuthenticatorManager:
+ // blink::test::mojom::VirtualAuthenticatorManager:
void CreateAuthenticator(
- webauth::test::mojom::VirtualAuthenticatorOptionsPtr options,
+ blink::test::mojom::VirtualAuthenticatorOptionsPtr options,
CreateAuthenticatorCallback callback) override;
void GetAuthenticators(GetAuthenticatorsCallback callback) override;
void RemoveAuthenticator(const std::string& id,
@@ -64,7 +64,7 @@ class CONTENT_EXPORT ScopedVirtualAuthenticatorEnvironment
// Called by VirtualFidoDiscoveries when they are destructed.
void OnDiscoveryDestroyed(VirtualFidoDiscovery* discovery);
- mojo::BindingSet<webauth::test::mojom::VirtualAuthenticatorManager> bindings_;
+ mojo::BindingSet<blink::test::mojom::VirtualAuthenticatorManager> bindings_;
// The key is the unique_id of the corresponding value (the authenticator).
std::map<std::string, std::unique_ptr<VirtualAuthenticator>> authenticators_;
diff --git a/chromium/content/browser/webauth/virtual_authenticator.cc b/chromium/content/browser/webauth/virtual_authenticator.cc
index 71cdfac4400..b93637c3189 100644
--- a/chromium/content/browser/webauth/virtual_authenticator.cc
+++ b/chromium/content/browser/webauth/virtual_authenticator.cc
@@ -22,7 +22,7 @@ VirtualAuthenticator::VirtualAuthenticator(
VirtualAuthenticator::~VirtualAuthenticator() = default;
void VirtualAuthenticator::AddBinding(
- webauth::test::mojom::VirtualAuthenticatorRequest request) {
+ blink::test::mojom::VirtualAuthenticatorRequest request) {
binding_set_.AddBinding(this, std::move(request));
}
@@ -35,13 +35,14 @@ void VirtualAuthenticator::GetUniqueId(GetUniqueIdCallback callback) {
}
void VirtualAuthenticator::GetRegistrations(GetRegistrationsCallback callback) {
- std::vector<webauth::test::mojom::RegisteredKeyPtr> mojo_registered_keys;
+ std::vector<blink::test::mojom::RegisteredKeyPtr> mojo_registered_keys;
for (const auto& registration : state_->registrations) {
- auto mojo_registered_key = webauth::test::mojom::RegisteredKey::New();
+ auto mojo_registered_key = blink::test::mojom::RegisteredKey::New();
mojo_registered_key->key_handle = registration.first;
mojo_registered_key->counter = registration.second.counter;
- mojo_registered_key->application_parameter =
- registration.second.application_parameter;
+ mojo_registered_key->application_parameter.assign(
+ registration.second.application_parameter.begin(),
+ registration.second.application_parameter.end());
registration.second.private_key->ExportPrivateKey(
&mojo_registered_key->private_key);
mojo_registered_keys.push_back(std::move(mojo_registered_key));
@@ -50,16 +51,20 @@ void VirtualAuthenticator::GetRegistrations(GetRegistrationsCallback callback) {
}
void VirtualAuthenticator::AddRegistration(
- webauth::test::mojom::RegisteredKeyPtr registration,
+ blink::test::mojom::RegisteredKeyPtr registration,
AddRegistrationCallback callback) {
+ if (registration->application_parameter.size() != device::kRpIdHashLength) {
+ std::move(callback).Run(false);
+ return;
+ }
+
bool success = false;
std::tie(std::ignore, success) = state_->registrations.emplace(
std::move(registration->key_handle),
::device::VirtualFidoDevice::RegistrationData(
crypto::ECPrivateKey::CreateFromPrivateKeyInfo(
registration->private_key),
- std::move(registration->application_parameter),
- registration->counter));
+ registration->application_parameter, registration->counter));
std::move(callback).Run(success);
}
diff --git a/chromium/content/browser/webauth/virtual_authenticator.h b/chromium/content/browser/webauth/virtual_authenticator.h
index c0ee5797447..d048250f30b 100644
--- a/chromium/content/browser/webauth/virtual_authenticator.h
+++ b/chromium/content/browser/webauth/virtual_authenticator.h
@@ -24,12 +24,12 @@ namespace content {
// state of the authenticator, whereas performing all cryptographic operations
// is delegated to the VirtualFidoDevice class.
class CONTENT_EXPORT VirtualAuthenticator
- : public webauth::test::mojom::VirtualAuthenticator {
+ : public blink::test::mojom::VirtualAuthenticator {
public:
explicit VirtualAuthenticator(::device::FidoTransportProtocol transport);
~VirtualAuthenticator() override;
- void AddBinding(webauth::test::mojom::VirtualAuthenticatorRequest request);
+ void AddBinding(blink::test::mojom::VirtualAuthenticatorRequest request);
::device::FidoTransportProtocol transport() const { return transport_; }
const std::string& unique_id() const { return unique_id_; }
@@ -43,11 +43,11 @@ class CONTENT_EXPORT VirtualAuthenticator
std::unique_ptr<::device::FidoDevice> ConstructDevice();
protected:
- // webauth::test::mojom::VirtualAuthenticator:
+ // blink::test::mojom::VirtualAuthenticator:
void GetUniqueId(GetUniqueIdCallback callback) override;
void GetRegistrations(GetRegistrationsCallback callback) override;
- void AddRegistration(webauth::test::mojom::RegisteredKeyPtr registration,
+ void AddRegistration(blink::test::mojom::RegisteredKeyPtr registration,
AddRegistrationCallback callback) override;
void ClearRegistrations(ClearRegistrationsCallback callback) override;
@@ -58,7 +58,7 @@ class CONTENT_EXPORT VirtualAuthenticator
const ::device::FidoTransportProtocol transport_;
const std::string unique_id_;
scoped_refptr<::device::VirtualFidoDevice::State> state_;
- mojo::BindingSet<webauth::test::mojom::VirtualAuthenticator> binding_set_;
+ mojo::BindingSet<blink::test::mojom::VirtualAuthenticator> binding_set_;
DISALLOW_COPY_AND_ASSIGN(VirtualAuthenticator);
};
diff --git a/chromium/content/browser/webauth/webauth_browsertest.cc b/chromium/content/browser/webauth/webauth_browsertest.cc
index 59b558ffc01..3943e65820e 100644
--- a/chromium/content/browser/webauth/webauth_browsertest.cc
+++ b/chromium/content/browser/webauth/webauth_browsertest.cc
@@ -7,13 +7,16 @@
#include <vector>
#include "base/command_line.h"
+#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
+#include "base/values.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/webauth/authenticator_impl.h"
+#include "content/public/browser/authenticator_request_client_delegate.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/web_contents.h"
@@ -24,12 +27,15 @@
#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/did_commit_provisional_load_interceptor.h"
+#include "device/base/features.h"
#include "device/fido/fake_fido_discovery.h"
#include "device/fido/fake_hid_impl_for_testing.h"
#include "device/fido/fido_test_data.h"
#include "device/fido/mock_fido_device.h"
+#include "device/fido/scoped_virtual_fido_device.h"
#include "device/fido/test_callback_receiver.h"
#include "net/dns/mock_host_resolver.h"
#include "services/device/public/mojom/constants.mojom.h"
@@ -42,11 +48,11 @@ namespace content {
namespace {
-using webauth::mojom::Authenticator;
-using webauth::mojom::AuthenticatorPtr;
-using webauth::mojom::AuthenticatorStatus;
-using webauth::mojom::GetAssertionAuthenticatorResponsePtr;
-using webauth::mojom::MakeCredentialAuthenticatorResponsePtr;
+using blink::mojom::Authenticator;
+using blink::mojom::AuthenticatorPtr;
+using blink::mojom::AuthenticatorStatus;
+using blink::mojom::GetAssertionAuthenticatorResponsePtr;
+using blink::mojom::MakeCredentialAuthenticatorResponsePtr;
using TestCreateCallbackReceiver =
::device::test::StatusAndValueCallbackReceiver<
@@ -57,33 +63,17 @@ using TestGetCallbackReceiver = ::device::test::StatusAndValueCallbackReceiver<
AuthenticatorStatus,
GetAssertionAuthenticatorResponsePtr>;
+constexpr char kTimeoutErrorMessage[] =
+ "webauth: NotAllowedError: The operation either timed out or was not "
+ "allowed. See: https://w3c.github.io/webauthn/#sec-assertion-privacy.";
+
+constexpr char kInvalidStateErrorMessage[] =
+ "webauth: InvalidStateError: The user attempted to use an authenticator "
+ "that recognized none of the provided credentials.";
+
constexpr char kRelyingPartySecurityErrorMessage[] =
- "SecurityError: The relying party ID 'localhost' is not a registrable "
- "domain suffix of, nor equal to 'https://www.acme.com";
-
-constexpr char kAlgorithmUnsupportedErrorMessage[] =
- "NotSupportedError: None of the algorithms specified in "
- "`pubKeyCredParams` are compatible with "
- "CTAP1/U2F authenticators, and CTAP2 "
- "authenticators are not yet supported.";
-
-constexpr char kAuthenticatorCriteriaErrorMessage[] =
- "NotSupportedError: The specified `authenticatorSelection` "
- "criteria cannot be fulfilled by CTAP1/U2F "
- "authenticators, and CTAP2 authenticators "
- "are not yet supported.";
-
-constexpr char kUserVerificationErrorMessage[] =
- "NotSupportedError: The specified `userVerification` "
- "requirement cannot be fulfilled by "
- "CTAP1/U2F authenticators, and CTAP2 "
- "authenticators are not yet supported.";
-
-constexpr char kEmptyAllowCredentialsErrorMessage[] =
- "NotSupportedError: The `allowCredentials` list cannot be left "
- "empty for CTAP1/U2F authenticators, and "
- "support for CTAP2 authenticators is not yet "
- "implemented.";
+ "webauth: SecurityError: The relying party ID 'localhost' is not a "
+ "registrable domain suffix of, nor equal to 'https://www.acme.com";
// Templates to be used with base::ReplaceStringPlaceholders. Can be
// modified to include up to 9 replacements. The default values for
@@ -99,13 +89,17 @@ constexpr char kCreatePublicKeyTemplate[] =
" displayName: 'Avery A. Jones', "
" icon: 'https://pics.acme.com/00/p/aBjjjpqPb.png'},"
" pubKeyCredParams: [{ type: 'public-key', alg: '$4'}],"
- " timeout: 60000,"
+ " timeout: 1000,"
" excludeCredentials: [],"
- " authenticatorSelection : {"
+ " authenticatorSelection: {"
" requireResidentKey: $1,"
" userVerification: '$2',"
- " authenticatorAttachment: '$5' }}"
- "}).catch(c => window.domAutomationController.send(c.toString()));";
+ " authenticatorAttachment: '$5',"
+ " },"
+ " attestation: '$6',"
+ "}}).then(c => window.domAutomationController.send('webauth: OK'),"
+ " e => window.domAutomationController.send("
+ " 'webauth: ' + e.toString()));";
constexpr char kPlatform[] = "platform";
constexpr char kCrossPlatform[] = "cross-platform";
@@ -119,6 +113,7 @@ struct CreateParameters {
const char* user_verification = kPreferredVerification;
const char* authenticator_attachment = kCrossPlatform;
const char* algorithm_identifier = "-7";
+ const char* attestation = "none";
};
std::string BuildCreateCallWithParameters(const CreateParameters& parameters) {
@@ -128,6 +123,7 @@ std::string BuildCreateCallWithParameters(const CreateParameters& parameters) {
substititions.push_back(parameters.rp_id);
substititions.push_back(parameters.algorithm_identifier);
substititions.push_back(parameters.authenticator_attachment);
+ substititions.push_back(parameters.attestation);
return base::ReplaceStringPlaceholders(kCreatePublicKeyTemplate,
substititions, nullptr);
}
@@ -135,11 +131,12 @@ std::string BuildCreateCallWithParameters(const CreateParameters& parameters) {
constexpr char kGetPublicKeyTemplate[] =
"navigator.credentials.get({ publicKey: {"
" challenge: new TextEncoder().encode('climb a mountain'),"
- " rp: 'acme.com',"
- " timeout: 60000,"
+ " rpId: 'acme.com',"
+ " timeout: 1000,"
" userVerification: '$1',"
" $2}"
- "}).catch(c => window.domAutomationController.send(c.toString()));";
+ "}).catch(c => window.domAutomationController.send("
+ " 'webauth: ' + c.toString()));";
// Default values for kGetPublicKeyTemplate.
struct GetParameters {
@@ -170,13 +167,14 @@ class ClosureExecutorBeforeNavigationCommit
~ClosureExecutorBeforeNavigationCommit() override = default;
protected:
- void WillDispatchDidCommitProvisionalLoad(
+ bool WillDispatchDidCommitProvisionalLoad(
RenderFrameHost* render_frame_host,
::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
service_manager::mojom::InterfaceProviderRequest*
interface_provider_request) override {
if (closure_)
std::move(closure_).Run();
+ return true;
}
private:
@@ -187,14 +185,16 @@ class ClosureExecutorBeforeNavigationCommit
// Cancels all navigations in a WebContents while in scope.
class ScopedNavigationCancellingThrottleInstaller : public WebContentsObserver {
public:
- ScopedNavigationCancellingThrottleInstaller(WebContents* web_contents)
+ explicit ScopedNavigationCancellingThrottleInstaller(
+ WebContents* web_contents)
: WebContentsObserver(web_contents) {}
~ScopedNavigationCancellingThrottleInstaller() override = default;
protected:
class CancellingThrottle : public NavigationThrottle {
public:
- CancellingThrottle(NavigationHandle* handle) : NavigationThrottle(handle) {}
+ explicit CancellingThrottle(NavigationHandle* handle)
+ : NavigationThrottle(handle) {}
~CancellingThrottle() override = default;
protected:
@@ -219,6 +219,87 @@ class ScopedNavigationCancellingThrottleInstaller : public WebContentsObserver {
DISALLOW_COPY_AND_ASSIGN(ScopedNavigationCancellingThrottleInstaller);
};
+struct WebAuthBrowserTestState {
+ // Called when the browser is asked to display an attestation prompt. There is
+ // no default so if no callback is installed then the test will crash.
+ base::OnceCallback<void(base::OnceCallback<void(bool)>)>
+ attestation_prompt_callback_;
+
+ // Set when |IsFocused| is called.
+ bool focus_checked = false;
+
+ // If true, request a new render process for each site (i.e. site isolation).
+ // Otherwise have the default behaviour for |ContentBrowserClient|.
+ bool force_new_render_processes = false;
+
+ // This is incremented when an |AuthenticatorRequestClientDelegate| is
+ // created.
+ int delegate_create_count = 0;
+};
+
+class WebAuthBrowserTestClientDelegate
+ : public AuthenticatorRequestClientDelegate {
+ public:
+ explicit WebAuthBrowserTestClientDelegate(WebAuthBrowserTestState* test_state)
+ : test_state_(test_state) {}
+
+ void ShouldReturnAttestation(
+ const std::string& relying_party_id,
+ base::OnceCallback<void(bool)> callback) override {
+ std::move(test_state_->attestation_prompt_callback_)
+ .Run(std::move(callback));
+ }
+
+ bool IsFocused() override {
+ test_state_->focus_checked = true;
+ return AuthenticatorRequestClientDelegate::IsFocused();
+ }
+
+ private:
+ WebAuthBrowserTestState* const test_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebAuthBrowserTestClientDelegate);
+};
+
+// Implements ContentBrowserClient and allows webauthn-related calls to be
+// mocked.
+class WebAuthBrowserTestContentBrowserClient : public ContentBrowserClient {
+ public:
+ explicit WebAuthBrowserTestContentBrowserClient(
+ WebAuthBrowserTestState* test_state)
+ : test_state_(test_state) {}
+
+ std::unique_ptr<AuthenticatorRequestClientDelegate>
+ GetWebAuthenticationRequestDelegate(
+ RenderFrameHost* render_frame_host) override {
+ test_state_->delegate_create_count++;
+ return std::make_unique<WebAuthBrowserTestClientDelegate>(test_state_);
+ }
+
+ bool ShouldUseProcessPerSite(BrowserContext* browser_context,
+ const GURL& effective_url) override {
+ if (test_state_->force_new_render_processes) {
+ return true;
+ }
+ return ContentBrowserClient::ShouldUseProcessPerSite(browser_context,
+ effective_url);
+ }
+
+ bool DoesSiteRequireDedicatedProcess(BrowserContext* browser_context,
+ const GURL& effective_url) override {
+ if (test_state_->force_new_render_processes) {
+ return true;
+ }
+ return ContentBrowserClient::DoesSiteRequireDedicatedProcess(
+ browser_context, effective_url);
+ }
+
+ private:
+ WebAuthBrowserTestState* const test_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebAuthBrowserTestContentBrowserClient);
+};
+
// Test fixture base class for common tasks.
class WebAuthBrowserTestBase : public content::ContentBrowserTest {
protected:
@@ -230,22 +311,32 @@ class WebAuthBrowserTestBase : public content::ContentBrowserTest {
}
void SetUpOnMainThread() override {
+ ContentBrowserTest::SetUpOnMainThread();
+
host_resolver()->AddRule("*", "127.0.0.1");
https_server().ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(https_server().Start());
+ test_client_.reset(
+ new WebAuthBrowserTestContentBrowserClient(&test_state_));
+ old_client_ = SetBrowserClientForTesting(test_client_.get());
+
NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title1.html"));
}
+ void TearDown() override {
+ CHECK_EQ(SetBrowserClientForTesting(old_client_), test_client_.get());
+ ContentBrowserTest::TearDown();
+ }
+
GURL GetHttpsURL(const std::string& hostname,
const std::string& relative_url) {
return https_server_.GetURL(hostname, relative_url);
}
net::EmbeddedTestServer& https_server() { return https_server_; }
- device::test::ScopedFakeFidoDiscoveryFactory* discovery_factory() {
- return &factory_;
- }
+
+ WebAuthBrowserTestState* test_state() { return &test_state_; }
private:
void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -257,16 +348,16 @@ class WebAuthBrowserTestBase : public content::ContentBrowserTest {
base::test::ScopedFeatureList scoped_feature_list_;
net::EmbeddedTestServer https_server_;
- device::test::ScopedFakeFidoDiscoveryFactory factory_;
+ std::unique_ptr<WebAuthBrowserTestContentBrowserClient> test_client_;
+ WebAuthBrowserTestState test_state_;
+ ContentBrowserClient* old_client_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(WebAuthBrowserTestBase);
};
-} // namespace
-
// WebAuthLocalClientBrowserTest ----------------------------------------------
-// Browser test fixture where the webauth::mojom::Authenticator interface is
+// Browser test fixture where the blink::mojom::Authenticator interface is
// accessed from a testing client in the browser process.
class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase {
public:
@@ -290,52 +381,50 @@ class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase {
mojo::MakeRequest(&authenticator_ptr_).PassMessagePipe());
}
- webauth::mojom::PublicKeyCredentialCreationOptionsPtr
+ blink::mojom::PublicKeyCredentialCreationOptionsPtr
BuildBasicCreateOptions() {
- auto rp = webauth::mojom::PublicKeyCredentialRpEntity::New(
+ auto rp = blink::mojom::PublicKeyCredentialRpEntity::New(
"acme.com", "acme.com", base::nullopt);
std::vector<uint8_t> kTestUserId{0, 0, 0};
- auto user = webauth::mojom::PublicKeyCredentialUserEntity::New(
+ auto user = blink::mojom::PublicKeyCredentialUserEntity::New(
kTestUserId, "name", base::nullopt, "displayName");
static constexpr int32_t kCOSEAlgorithmIdentifierES256 = -7;
- auto param = webauth::mojom::PublicKeyCredentialParameters::New();
- param->type = webauth::mojom::PublicKeyCredentialType::PUBLIC_KEY;
+ auto param = blink::mojom::PublicKeyCredentialParameters::New();
+ param->type = blink::mojom::PublicKeyCredentialType::PUBLIC_KEY;
param->algorithm_identifier = kCOSEAlgorithmIdentifierES256;
- std::vector<webauth::mojom::PublicKeyCredentialParametersPtr> parameters;
+ std::vector<blink::mojom::PublicKeyCredentialParametersPtr> parameters;
parameters.push_back(std::move(param));
std::vector<uint8_t> kTestChallenge{0, 0, 0};
- auto mojo_options = webauth::mojom::PublicKeyCredentialCreationOptions::New(
+ auto mojo_options = blink::mojom::PublicKeyCredentialCreationOptions::New(
std::move(rp), std::move(user), kTestChallenge, std::move(parameters),
base::TimeDelta::FromSeconds(30),
- std::vector<webauth::mojom::PublicKeyCredentialDescriptorPtr>(),
- nullptr, webauth::mojom::AttestationConveyancePreference::NONE,
- nullptr);
+ std::vector<blink::mojom::PublicKeyCredentialDescriptorPtr>(), nullptr,
+ blink::mojom::AttestationConveyancePreference::NONE, nullptr);
return mojo_options;
}
- webauth::mojom::PublicKeyCredentialRequestOptionsPtr BuildBasicGetOptions() {
- std::vector<webauth::mojom::PublicKeyCredentialDescriptorPtr> credentials;
- std::vector<webauth::mojom::AuthenticatorTransport> transports;
- transports.push_back(webauth::mojom::AuthenticatorTransport::USB);
+ blink::mojom::PublicKeyCredentialRequestOptionsPtr BuildBasicGetOptions() {
+ std::vector<blink::mojom::PublicKeyCredentialDescriptorPtr> credentials;
+ std::vector<blink::mojom::AuthenticatorTransport> transports;
+ transports.push_back(blink::mojom::AuthenticatorTransport::USB);
- auto descriptor = webauth::mojom::PublicKeyCredentialDescriptor::New(
- webauth::mojom::PublicKeyCredentialType::PUBLIC_KEY,
- std::vector<uint8_t>(
- std::begin(device::test_data::kTestGetAssertionCredentialId),
- std::end(device::test_data::kTestGetAssertionCredentialId)),
+ auto descriptor = blink::mojom::PublicKeyCredentialDescriptor::New(
+ blink::mojom::PublicKeyCredentialType::PUBLIC_KEY,
+ device::fido_parsing_utils::Materialize(
+ device::test_data::kTestGetAssertionCredentialId),
transports);
credentials.push_back(std::move(descriptor));
std::vector<uint8_t> kTestChallenge{0, 0, 0};
- auto mojo_options = webauth::mojom::PublicKeyCredentialRequestOptions::New(
+ auto mojo_options = blink::mojom::PublicKeyCredentialRequestOptions::New(
kTestChallenge, base::TimeDelta::FromSeconds(30), "acme.com",
std::move(credentials),
- webauth::mojom::UserVerificationRequirement::PREFERRED, base::nullopt,
- std::vector<webauth::mojom::CableAuthenticationPtr>());
+ blink::mojom::UserVerificationRequirement::PREFERRED, base::nullopt,
+ std::vector<blink::mojom::CableAuthenticationPtr>());
return mojo_options;
}
@@ -362,7 +451,8 @@ class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase {
// pending navigator.credentials.create({publicKey: ...}) call.
IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
CreatePublicKeyCredentialThenNavigateAway) {
- auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
+ device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
+ auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
TestCreateCallbackReceiver create_callback_receiver;
authenticator()->MakeCredential(BuildBasicCreateOptions(),
create_callback_receiver.callback());
@@ -374,7 +464,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
// The next active document should be able to successfully call
// navigator.credentials.create({publicKey: ...}) again.
ConnectToAuthenticator();
- fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
+ fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
authenticator()->MakeCredential(BuildBasicCreateOptions(),
create_callback_receiver.callback());
fake_hid_discovery->WaitForCallToStartAndSimulateSuccess();
@@ -384,7 +474,8 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
// pending navigator.credentials.get({publicKey: ...}) call.
IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
GetPublicKeyCredentialThenNavigateAway) {
- auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
+ device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
+ auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
TestGetCallbackReceiver get_callback_receiver;
authenticator()->GetAssertion(BuildBasicGetOptions(),
get_callback_receiver.callback());
@@ -396,13 +487,70 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
// The next active document should be able to successfully call
// navigator.credentials.get({publicKey: ...}) again.
ConnectToAuthenticator();
- fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
+ fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
authenticator()->GetAssertion(BuildBasicGetOptions(),
get_callback_receiver.callback());
fake_hid_discovery->WaitForCallToStartAndSimulateSuccess();
}
-// Tests that the webauth::mojom::Authenticator connection is not closed on a
+enum class AttestationCallbackBehavior {
+ IGNORE_CALLBACK,
+ BEFORE_NAVIGATION,
+ AFTER_NAVIGATION,
+};
+
+const char* AttestationCallbackBehaviorToString(
+ AttestationCallbackBehavior behavior) {
+ switch (behavior) {
+ case AttestationCallbackBehavior::IGNORE_CALLBACK:
+ return "IGNORE_CALLBACK";
+ case AttestationCallbackBehavior::BEFORE_NAVIGATION:
+ return "BEFORE_NAVIGATION";
+ case AttestationCallbackBehavior::AFTER_NAVIGATION:
+ return "AFTER_NAVIGATION";
+ }
+}
+
+const AttestationCallbackBehavior kAllAttestationCallbackBehaviors[] = {
+ AttestationCallbackBehavior::IGNORE_CALLBACK,
+ AttestationCallbackBehavior::BEFORE_NAVIGATION,
+ AttestationCallbackBehavior::AFTER_NAVIGATION,
+};
+
+// Tests navigating while an attestation permission prompt is showing.
+IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
+ PromptForAttestationThenNavigateAway) {
+ for (auto behavior : kAllAttestationCallbackBehaviors) {
+ SCOPED_TRACE(AttestationCallbackBehaviorToString(behavior));
+
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ TestCreateCallbackReceiver create_callback_receiver;
+ auto options = BuildBasicCreateOptions();
+ options->attestation =
+ blink::mojom::AttestationConveyancePreference::DIRECT;
+ authenticator()->MakeCredential(std::move(options),
+ create_callback_receiver.callback());
+ bool attestation_callback_was_invoked = false;
+ test_state()->attestation_prompt_callback_ = base::BindLambdaForTesting(
+ [&](base::OnceCallback<void(bool)> callback) {
+ attestation_callback_was_invoked = true;
+
+ if (behavior == AttestationCallbackBehavior::BEFORE_NAVIGATION) {
+ std::move(callback).Run(false);
+ }
+ NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html"));
+ if (behavior == AttestationCallbackBehavior::AFTER_NAVIGATION) {
+ std::move(callback).Run(false);
+ }
+ });
+
+ WaitForConnectionError();
+ ASSERT_TRUE(attestation_callback_was_invoked);
+ ConnectToAuthenticator();
+ }
+}
+
+// Tests that the blink::mojom::Authenticator connection is not closed on a
// cancelled navigation.
IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
CreatePublicKeyCredentialAfterCancelledNavigation) {
@@ -411,7 +559,8 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html"));
- auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
+ device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
+ auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
TestCreateCallbackReceiver create_callback_receiver;
authenticator()->MakeCredential(BuildBasicCreateOptions(),
create_callback_receiver.callback());
@@ -432,7 +581,8 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
create_callback_receiver.callback());
}));
- auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
+ device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
+ auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html"));
WaitForConnectionError();
@@ -447,7 +597,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
// The next active document should be able to successfully call
// navigator.credentials.create({publicKey: ...}) again.
ConnectToAuthenticator();
- fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
+ fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
authenticator()->MakeCredential(BuildBasicCreateOptions(),
create_callback_receiver.callback());
fake_hid_discovery->WaitForCallToStartAndSimulateSuccess();
@@ -485,7 +635,8 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
CreatePublicKeyCredentialWhileRequestIsPending) {
- auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
+ device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
+ auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
TestCreateCallbackReceiver callback_receiver_1;
TestCreateCallbackReceiver callback_receiver_2;
authenticator()->MakeCredential(BuildBasicCreateOptions(),
@@ -502,7 +653,8 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
GetPublicKeyCredentialWhileRequestIsPending) {
- auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
+ device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
+ auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
TestGetCallbackReceiver callback_receiver_1;
TestGetCallbackReceiver callback_receiver_2;
authenticator()->GetAssertion(BuildBasicGetOptions(),
@@ -519,7 +671,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
// WebAuthJavascriptClientBrowserTest -----------------------------------------
-// Browser test fixture where the webauth::mojom::Authenticator interface is
+// Browser test fixture where the blink::mojom::Authenticator interface is
// normally accessed from Javascript in the renderer process.
class WebAuthJavascriptClientBrowserTest : public WebAuthBrowserTestBase {
public:
@@ -532,32 +684,8 @@ class WebAuthJavascriptClientBrowserTest : public WebAuthBrowserTestBase {
DISALLOW_COPY_AND_ASSIGN(WebAuthJavascriptClientBrowserTest);
};
-// Tests that when navigator.credentials.create() is called with user
-// verification required we get a NotSupportedError.
-IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
- CreatePublicKeyCredentialWithUserVerification) {
- CreateParameters parameters;
- parameters.user_verification = kRequiredVerification;
- std::string result;
- ASSERT_TRUE(content::ExecuteScriptAndExtractString(
- shell()->web_contents()->GetMainFrame(),
- BuildCreateCallWithParameters(parameters), &result));
- ASSERT_EQ(kAuthenticatorCriteriaErrorMessage, result);
-}
-
-// Tests that when navigator.credentials.create() is called with resident key
-// required, we get a NotSupportedError.
-IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
- CreatePublicKeyCredentialWithResidentKeyRequired) {
- CreateParameters parameters;
- parameters.require_resident_key = true;
- std::string result;
- ASSERT_TRUE(content::ExecuteScriptAndExtractString(
- shell()->web_contents()->GetMainFrame(),
- BuildCreateCallWithParameters(parameters), &result));
-
- ASSERT_EQ(kAuthenticatorCriteriaErrorMessage, result);
-}
+constexpr device::ProtocolVersion kAllProtocols[] = {
+ device::ProtocolVersion::kCtap, device::ProtocolVersion::kU2f};
// Tests that when navigator.credentials.create() is called with an invalid
// relying party id, we get a SecurityError.
@@ -574,58 +702,111 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
result.substr(0, strlen(kRelyingPartySecurityErrorMessage)));
}
+// Tests that when navigator.credentials.create() is called with user
+// verification required, request times out.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ CreatePublicKeyCredentialWithUserVerification) {
+ for (const auto protocol : kAllProtocols) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ virtual_device.SetSupportedProtocol(protocol);
+
+ CreateParameters parameters;
+ parameters.user_verification = kRequiredVerification;
+ std::string result;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(),
+ BuildCreateCallWithParameters(parameters), &result));
+ ASSERT_EQ(kTimeoutErrorMessage, result);
+ }
+}
+
+// Tests that when navigator.credentials.create() is called with resident key
+// required, request times out.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ CreatePublicKeyCredentialWithResidentKeyRequired) {
+ for (const auto protocol : kAllProtocols) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ virtual_device.SetSupportedProtocol(protocol);
+
+ CreateParameters parameters;
+ parameters.require_resident_key = true;
+ std::string result;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(),
+ BuildCreateCallWithParameters(parameters), &result));
+
+ ASSERT_EQ(kTimeoutErrorMessage, result);
+ }
+}
+
// Tests that when navigator.credentials.create() is called with an
-// unsupported algorithm, we get a NotSupportedError.
+// unsupported algorithm, request times out.
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
CreatePublicKeyCredentialAlgorithmNotSupported) {
- CreateParameters parameters;
- parameters.algorithm_identifier = "123";
- std::string result;
- ASSERT_TRUE(content::ExecuteScriptAndExtractString(
- shell()->web_contents()->GetMainFrame(),
- BuildCreateCallWithParameters(parameters), &result));
-
- ASSERT_EQ(kAlgorithmUnsupportedErrorMessage, result);
+ for (const auto protocol : kAllProtocols) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ virtual_device.SetSupportedProtocol(protocol);
+
+ CreateParameters parameters;
+ parameters.algorithm_identifier = "123";
+ std::string result;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(),
+ BuildCreateCallWithParameters(parameters), &result));
+
+ ASSERT_EQ(kTimeoutErrorMessage, result);
+ }
}
// Tests that when navigator.credentials.create() is called with a
-// platform authenticator requested, we get a NotSupportedError.
+// platform authenticator requested, request times out.
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
CreatePublicKeyCredentialPlatformAuthenticator) {
- CreateParameters parameters;
- parameters.authenticator_attachment = kPlatform;
- std::string result;
- ASSERT_TRUE(content::ExecuteScriptAndExtractString(
- shell()->web_contents()->GetMainFrame(),
- BuildCreateCallWithParameters(parameters), &result));
-
- ASSERT_EQ(kAuthenticatorCriteriaErrorMessage, result);
+ for (const auto protocol : kAllProtocols) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ virtual_device.SetSupportedProtocol(protocol);
+
+ CreateParameters parameters;
+ parameters.authenticator_attachment = kPlatform;
+ std::string result;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(),
+ BuildCreateCallWithParameters(parameters), &result));
+
+ ASSERT_EQ(kTimeoutErrorMessage, result);
+ }
}
// Tests that when navigator.credentials.get() is called with user verification
// required, we get a NotSupportedError.
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
GetPublicKeyCredentialUserVerification) {
- GetParameters parameters;
- parameters.user_verification = "required";
- std::string result;
- ASSERT_TRUE(content::ExecuteScriptAndExtractString(
- shell()->web_contents()->GetMainFrame(),
- BuildGetCallWithParameters(parameters), &result));
- ASSERT_EQ(kUserVerificationErrorMessage, result);
+ for (const auto protocol : kAllProtocols) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ virtual_device.SetSupportedProtocol(protocol);
+
+ GetParameters parameters;
+ parameters.user_verification = "required";
+ std::string result;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(),
+ BuildGetCallWithParameters(parameters), &result));
+ ASSERT_EQ(kTimeoutErrorMessage, result);
+ }
}
// Tests that when navigator.credentials.get() is called with an empty
// allowCredentials list, we get a NotSupportedError.
IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
GetPublicKeyCredentialEmptyAllowCredentialsList) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
GetParameters parameters;
parameters.allow_credentials = "";
std::string result;
ASSERT_TRUE(content::ExecuteScriptAndExtractString(
shell()->web_contents()->GetMainFrame(),
BuildGetCallWithParameters(parameters), &result));
- ASSERT_EQ(kEmptyAllowCredentialsErrorMessage, result);
+ ASSERT_EQ(kInvalidStateErrorMessage, result);
}
// WebAuthBrowserBleDisabledTest
@@ -649,8 +830,9 @@ class WebAuthBrowserBleDisabledTest : public WebAuthLocalClientBrowserTest {
// Tests that the BLE discovery does not start when the WebAuthnBle feature
// flag is disabled.
IN_PROC_BROWSER_TEST_F(WebAuthBrowserBleDisabledTest, CheckBleDisabled) {
- auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
- auto* fake_ble_discovery = discovery_factory()->ForgeNextBleDiscovery();
+ device::test::ScopedFakeFidoDiscoveryFactory discovery_factory;
+ auto* fake_hid_discovery = discovery_factory.ForgeNextHidDiscovery();
+ auto* fake_ble_discovery = discovery_factory.ForgeNextBleDiscovery();
// Do something that will start discoveries.
TestCreateCallbackReceiver create_callback_receiver;
@@ -662,70 +844,251 @@ IN_PROC_BROWSER_TEST_F(WebAuthBrowserBleDisabledTest, CheckBleDisabled) {
EXPECT_FALSE(fake_ble_discovery->is_start_requested());
}
+// Executes Javascript in the given WebContents and waits until a string with
+// the given prefix is received. It will ignore values other than strings, and
+// strings without the given prefix. Since messages are broadcast to
+// DOMMessageQueues, this allows other functions that depend on ExecuteScript
+// (and thus trigger the broadcast of values) to run while this function is
+// waiting for a specific result.
+base::Optional<std::string> ExecuteScriptAndExtractPrefixedString(
+ WebContents* web_contents,
+ const std::string& script,
+ const std::string& result_prefix) {
+ DOMMessageQueue dom_message_queue(web_contents);
+ web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
+ base::UTF8ToUTF16(script));
+
+ for (;;) {
+ std::string json;
+ if (!dom_message_queue.WaitForMessage(&json)) {
+ return base::nullopt;
+ }
+
+ base::JSONReader reader(base::JSON_ALLOW_TRAILING_COMMAS);
+ std::unique_ptr<base::Value> result = reader.ReadToValue(json);
+ if (!result) {
+ return base::nullopt;
+ }
+
+ std::string str;
+ if (result->GetAsString(&str) && str.find(result_prefix) == 0) {
+ return str;
+ }
+ }
+}
+
+// Tests that a credentials.create() call triggered by the main frame will
+// successfully complete even if a subframe navigation takes place while the
+// request is waiting for user consent.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ NavigateSubframeDuringPress) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ bool prompt_callback_was_invoked = false;
+ virtual_device.mutable_state()->simulate_press_callback =
+ base::BindLambdaForTesting([&]() {
+ prompt_callback_was_invoked = true;
+ NavigateIframeToURL(shell()->web_contents(), "test_iframe",
+ GURL("/title2.html"));
+ });
+
+ NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/page_with_iframe.html"));
+
+ // The plain ExecuteScriptAndExtractString cannot be used because
+ // NavigateIframeToURL uses it internally and they get confused about which
+ // message is for whom.
+ base::Optional<std::string> result = ExecuteScriptAndExtractPrefixedString(
+ shell()->web_contents(),
+ BuildCreateCallWithParameters(CreateParameters()), "webauth: ");
+ ASSERT_TRUE(result);
+ ASSERT_EQ("webauth: OK", *result);
+ ASSERT_TRUE(prompt_callback_was_invoked);
+}
+
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ NavigateSubframeDuringAttestationPrompt) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
+
+ for (auto behavior : kAllAttestationCallbackBehaviors) {
+ if (behavior == AttestationCallbackBehavior::IGNORE_CALLBACK) {
+ // If the callback is ignored, then the registration will not complete and
+ // that hangs the test.
+ continue;
+ }
+
+ SCOPED_TRACE(AttestationCallbackBehaviorToString(behavior));
+
+ bool prompt_callback_was_invoked = false;
+ test_state()->attestation_prompt_callback_ = base::BindOnce(
+ [](WebContents* web_contents, bool* prompt_callback_was_invoked,
+ AttestationCallbackBehavior behavior,
+ base::OnceCallback<void(bool)> callback) {
+ *prompt_callback_was_invoked = true;
+
+ if (behavior == AttestationCallbackBehavior::BEFORE_NAVIGATION) {
+ std::move(callback).Run(true);
+ }
+ // Can't use NavigateIframeToURL here because in the
+ // BEFORE_NAVIGATION case we are racing AuthenticatorImpl and
+ // NavigateIframeToURL can get confused by the "OK" message.
+ base::Optional<std::string> result =
+ ExecuteScriptAndExtractPrefixedString(
+ web_contents,
+ "document.getElementById('test_iframe').src = "
+ "'/title2.html'; "
+ "window.domAutomationController.send('iframe: done');",
+ "iframe: ");
+ CHECK(result);
+ CHECK_EQ("iframe: done", *result);
+ if (behavior == AttestationCallbackBehavior::AFTER_NAVIGATION) {
+ std::move(callback).Run(true);
+ }
+ },
+ shell()->web_contents(), &prompt_callback_was_invoked, behavior);
+
+ NavigateToURL(shell(),
+ GetHttpsURL("www.acme.com", "/page_with_iframe.html"));
+
+ CreateParameters parameters;
+ parameters.attestation = "direct";
+ // The plain ExecuteScriptAndExtractString cannot be used because
+ // NavigateIframeToURL uses it internally and they get confused about which
+ // message is for whom.
+ base::Optional<std::string> result = ExecuteScriptAndExtractPrefixedString(
+ shell()->web_contents(), BuildCreateCallWithParameters(parameters),
+ "webauth: ");
+ ASSERT_TRUE(result);
+ ASSERT_EQ("webauth: OK", *result);
+ ASSERT_TRUE(prompt_callback_was_invoked);
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+ RegisterDuringUnload) {
+ // Request new render processes for each site in order to test concurrent
+ // unloading with a different RenderFrame showing the new page.
+ test_state()->force_new_render_processes = true;
+
+ NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title1.html"));
+ const std::string script = base::ReplaceStringPlaceholders(
+ R"(
+ window.addEventListener('unload', function(e) {
+ $1
+ });
+
+ // Trigger a webauthn operation so that the bindings are established
+ // before unload.
+ navigator.credentials.get({ publicKey: {
+ challenge: new TextEncoder().encode('climb a mountain'),
+ timeout: 1,
+ }}).catch(c => window.location = '$2');
+ )",
+ {BuildCreateCallWithParameters(CreateParameters()),
+ GetHttpsURL("www.acme2.com", "/title2.html").spec()},
+ nullptr);
+
+ RenderFrameHost* render_frame_host = shell()->web_contents()->GetMainFrame();
+ RenderFrameDeletedObserver observer(render_frame_host);
+ render_frame_host->ExecuteJavaScriptForTests(base::UTF8ToUTF16(script));
+ observer.WaitUntilDeleted();
+
+ // The |MakeCredential| call from the unload handler should not have reached
+ // the point where focus was checked.
+ EXPECT_FALSE(test_state()->focus_checked);
+
+ // Two delegates should have been created: one for the GetAssertion call that
+ // primes the binding and a second for the MakeCredential call in the unload
+ // handler.
+ ASSERT_EQ(2, test_state()->delegate_create_count);
+}
+
// WebAuthBrowserCtapTest ----------------------------------------------
-// A test fixture that enables CTAP only flag.
class WebAuthBrowserCtapTest : public WebAuthLocalClientBrowserTest {
public:
WebAuthBrowserCtapTest() = default;
+ ~WebAuthBrowserCtapTest() override = default;
- protected:
- std::vector<base::Feature> GetFeaturesToEnable() override {
- return {features::kWebAuth, features::kWebAuthCtap2};
- }
-
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(WebAuthBrowserCtapTest);
};
-// TODO(hongjunchoi): Implement VirtualCtap2Device to replace mocking.
-// See: https://crbugs.com/829413
-IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest, TestCtapMakeCredential) {
- auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
+IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest, TestMakeCredential) {
+ for (const auto protocol : kAllProtocols) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ virtual_device.SetSupportedProtocol(protocol);
- TestCreateCallbackReceiver create_callback_receiver;
- authenticator()->MakeCredential(BuildBasicCreateOptions(),
- create_callback_receiver.callback());
+ TestCreateCallbackReceiver create_callback_receiver;
+ authenticator()->MakeCredential(BuildBasicCreateOptions(),
+ create_callback_receiver.callback());
- fake_hid_discovery->WaitForCallToStartAndSimulateSuccess();
- auto device = std::make_unique<device::MockFidoDevice>();
- EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0"));
- device->ExpectCtap2CommandAndRespondWith(
- device::CtapRequestCommand::kAuthenticatorGetInfo,
- device::test_data::kTestAuthenticatorGetInfoResponse);
- device->ExpectCtap2CommandAndRespondWith(
- device::CtapRequestCommand::kAuthenticatorMakeCredential,
- device::test_data::kTestMakeCredentialResponse);
-
- fake_hid_discovery->AddDevice(std::move(device));
-
- create_callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::SUCCESS, create_callback_receiver.status());
+ create_callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::SUCCESS, create_callback_receiver.status());
+ }
}
-IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest, TestCtapGetAssertion) {
- auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
+IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest,
+ TestMakeCredentialWithDuplicateKeyHandle) {
+ for (const auto protocol : kAllProtocols) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ virtual_device.SetSupportedProtocol(protocol);
+ auto make_credential_request = BuildBasicCreateOptions();
+ auto excluded_credential = blink::mojom::PublicKeyCredentialDescriptor::New(
+ blink::mojom::PublicKeyCredentialType::PUBLIC_KEY,
+ device::fido_parsing_utils::Materialize(
+ device::test_data::kCtap2MakeCredentialCredentialId),
+ std::vector<blink::mojom::AuthenticatorTransport>{
+ blink::mojom::AuthenticatorTransport::USB});
+ make_credential_request->exclude_credentials.push_back(
+ std::move(excluded_credential));
+
+ ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ device::fido_parsing_utils::Materialize(
+ device::test_data::kCtap2MakeCredentialCredentialId),
+ make_credential_request->relying_party->id));
+
+ TestCreateCallbackReceiver create_callback_receiver;
+ authenticator()->MakeCredential(std::move(make_credential_request),
+ create_callback_receiver.callback());
+
+ create_callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_EXCLUDED,
+ create_callback_receiver.status());
+ }
+}
- TestGetCallbackReceiver get_callback_receiver;
- auto get_assertion_request_params = BuildBasicGetOptions();
- authenticator()->GetAssertion(std::move(get_assertion_request_params),
- get_callback_receiver.callback());
+IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest, TestGetAssertion) {
+ for (const auto protocol : kAllProtocols) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ virtual_device.SetSupportedProtocol(protocol);
+ auto get_assertion_request_params = BuildBasicGetOptions();
+ ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+ device::fido_parsing_utils::Materialize(
+ device::test_data::kTestGetAssertionCredentialId),
+ get_assertion_request_params->relying_party_id));
+
+ TestGetCallbackReceiver get_callback_receiver;
+ authenticator()->GetAssertion(std::move(get_assertion_request_params),
+ get_callback_receiver.callback());
+ get_callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::SUCCESS, get_callback_receiver.status());
+ }
+}
- fake_hid_discovery->WaitForCallToStartAndSimulateSuccess();
- auto device = std::make_unique<device::MockFidoDevice>();
- EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0"));
- device->ExpectCtap2CommandAndRespondWith(
- device::CtapRequestCommand::kAuthenticatorGetInfo,
- device::test_data::kTestAuthenticatorGetInfoResponse);
- device->ExpectCtap2CommandAndRespondWith(
- device::CtapRequestCommand::kAuthenticatorGetAssertion,
- device::test_data::kTestGetAssertionResponse);
-
- fake_hid_discovery->AddDevice(std::move(device));
-
- get_callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::SUCCESS, get_callback_receiver.status());
+IN_PROC_BROWSER_TEST_F(WebAuthBrowserCtapTest,
+ TestGetAssertionWithNoMatchingKeyHandles) {
+ for (const auto protocol : kAllProtocols) {
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ virtual_device.SetSupportedProtocol(protocol);
+ auto get_assertion_request_params = BuildBasicGetOptions();
+
+ TestGetCallbackReceiver get_callback_receiver;
+ authenticator()->GetAssertion(std::move(get_assertion_request_params),
+ get_callback_receiver.callback());
+ get_callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+ get_callback_receiver.status());
+ }
}
+} // namespace
+
} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
index 1a57c79ba8c..d0679ee756a 100644
--- a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
@@ -19,23 +19,64 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest-param-test.h"
+#if defined(OS_WIN)
+#include "services/service_manager/sandbox/features.h"
+#endif
+
namespace content {
+namespace {
+
+// Temporary enum, used for running the tests with different combination of
+// flags while audio service is under experiment.
+// TODO(https://crbug.com/850878) Remove after enabling sandboxing on all
+// platforms.
+enum class AudioServiceFeatures {
+ kDisabled,
+ kOutOfProcess,
+#if defined(OS_WIN)
+ kSandboxed,
+#endif
+};
+} // namespace
+
// This class tests the scenario when permission to access mic or camera is
// granted.
-class WebRtcAudioBrowserTest : public WebRtcContentBrowserTestBase,
- public testing::WithParamInterface<bool> {
+class WebRtcAudioBrowserTest
+ : public WebRtcContentBrowserTestBase,
+ public testing::WithParamInterface<AudioServiceFeatures> {
public:
WebRtcAudioBrowserTest() {
std::vector<base::Feature> audio_service_oop_features = {
features::kAudioServiceAudioStreams,
features::kAudioServiceOutOfProcess};
- if (GetParam()) {
- // Force audio service out of process to enabled.
- audio_service_features_.InitWithFeatures(audio_service_oop_features, {});
- } else {
- // Force audio service out of process to disabled.
- audio_service_features_.InitWithFeatures({}, audio_service_oop_features);
+ switch (GetParam()) {
+ case AudioServiceFeatures::kDisabled:
+ // Force audio service out of process to disabled.
+ audio_service_features_.InitWithFeatures({},
+ audio_service_oop_features);
+ break;
+ case AudioServiceFeatures::kOutOfProcess:
+ // Force audio service out of process to enabled.
+ audio_service_features_.InitWithFeatures(
+ audio_service_oop_features,
+#if defined(OS_WIN)
+ // Force audio service sandboxing (available only on Windows) to
+ // disabled.
+ {service_manager::features::kAudioServiceSandbox});
+#else
+ {});
+#endif
+ break;
+#if defined(OS_WIN)
+ case AudioServiceFeatures::kSandboxed:
+ // Force audio service out of process and sandboxing to enabled.
+ audio_service_oop_features.push_back(
+ service_manager::features::kAudioServiceSandbox);
+ audio_service_features_.InitWithFeatures(audio_service_oop_features,
+ {});
+ break;
+#endif
}
}
~WebRtcAudioBrowserTest() override {}
@@ -62,8 +103,8 @@ class WebRtcAudioBrowserTest : public WebRtcContentBrowserTestBase,
ASSERT_TRUE(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseFakeDeviceForMediaStream))
- << "Must run with fake devices since the test will explicitly look "
- << "for the fake device signal.";
+ << "Must run with fake devices since the test will explicitly look "
+ << "for the fake device signal.";
MakeTypicalCall(javascript, "/media/peerconnection-call-audio.html");
}
@@ -129,14 +170,26 @@ IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
// We run these tests with the audio service both in and out of the the browser
// process to have waterfall coverage while the feature rolls out. It should be
// removed after launch.
-#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
+#if defined(OS_LINUX) || defined(OS_MACOSX)
// Supported platforms.
-INSTANTIATE_TEST_CASE_P(, WebRtcAudioBrowserTest, ::testing::Bool());
+INSTANTIATE_TEST_CASE_P(,
+ WebRtcAudioBrowserTest,
+ ::testing::Values(AudioServiceFeatures::kDisabled,
+ AudioServiceFeatures::kOutOfProcess));
+#elif defined(OS_WIN)
+// On Windows, also run in sandboxed mode.
+INSTANTIATE_TEST_CASE_P(,
+ WebRtcAudioBrowserTest,
+ ::testing::Values(AudioServiceFeatures::kDisabled,
+ AudioServiceFeatures::kOutOfProcess,
+ AudioServiceFeatures::kSandboxed));
#elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
// Renderer crashes under Android ASAN: https://crbug.com/408496.
#else
// Platforms where the out of process audio service isn't supported
-INSTANTIATE_TEST_CASE_P(, WebRtcAudioBrowserTest, ::testing::Values(false));
+INSTANTIATE_TEST_CASE_P(,
+ WebRtcAudioBrowserTest,
+ ::testing::Values(AudioServiceFeatures::kDisabled));
#endif
} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index 339d6f044fb..5a997c3dcd8 100644
--- a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -18,6 +18,7 @@
#include "content/browser/webrtc/webrtc_internals.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/service_manager_connection.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
@@ -26,10 +27,14 @@
#include "media/audio/fake_audio_input_stream.h"
#include "media/base/media_switches.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/audio/public/mojom/constants.mojom.h"
+#include "services/audio/public/mojom/testing_api.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
#include "testing/gtest/include/gtest/gtest-param-test.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
+#include "services/service_manager/sandbox/features.h"
#endif
namespace {
@@ -53,6 +58,18 @@ static const char kRenderDuplicatedMediastreamAndStop[] =
// Results returned by JS.
static const char kOK[] = "OK";
+// Temporary enum, used for running the tests with different combination of
+// flags while audio service is under experiment.
+// TODO(https://crbug.com/850878) Remove after enabling sandboxing on all
+// platforms.
+enum class AudioServiceFeatures {
+ kDisabled,
+ kOutOfProcess,
+#if defined(OS_WIN)
+ kSandboxed,
+#endif
+};
+
std::string GenerateGetUserMediaWithMandatorySourceID(
const std::string& function_name,
const std::string& audio_source_id,
@@ -98,8 +115,9 @@ bool VerifyDisableLocalEcho(bool expect_value,
namespace content {
-class WebRtcGetUserMediaBrowserTest : public WebRtcContentBrowserTestBase,
- public testing::WithParamInterface<bool> {
+class WebRtcGetUserMediaBrowserTest
+ : public WebRtcContentBrowserTestBase,
+ public testing::WithParamInterface<AudioServiceFeatures> {
public:
WebRtcGetUserMediaBrowserTest() {
// Automatically grant device permission.
@@ -107,12 +125,33 @@ class WebRtcGetUserMediaBrowserTest : public WebRtcContentBrowserTestBase,
std::vector<base::Feature> audio_service_oop_features = {
features::kAudioServiceAudioStreams,
features::kAudioServiceOutOfProcess};
- if (GetParam()) {
- // Force audio service out of process to enabled.
- audio_service_features_.InitWithFeatures(audio_service_oop_features, {});
- } else {
- // Force audio service out of process to disabled.
- audio_service_features_.InitWithFeatures({}, audio_service_oop_features);
+ switch (GetParam()) {
+ case AudioServiceFeatures::kDisabled:
+ // Force audio service out of process to disabled.
+ audio_service_features_.InitWithFeatures({},
+ audio_service_oop_features);
+ break;
+ case AudioServiceFeatures::kOutOfProcess:
+ // Force audio service out of process to enabled.
+ audio_service_features_.InitWithFeatures(
+ audio_service_oop_features,
+#if defined(OS_WIN)
+ // Force audio service sandboxing (available only on Windows) to
+ // disabled.
+ {service_manager::features::kAudioServiceSandbox});
+#else
+ {});
+#endif
+ break;
+#if defined(OS_WIN)
+ case AudioServiceFeatures::kSandboxed:
+ // Force audio service out of process and sandboxing to enabled.
+ audio_service_oop_features.push_back(
+ service_manager::features::kAudioServiceSandbox);
+ audio_service_features_.InitWithFeatures(audio_service_oop_features,
+ {});
+ break;
+#endif
}
}
~WebRtcGetUserMediaBrowserTest() override {}
@@ -397,8 +436,9 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, TwoGetUserMediaAndStop) {
"twoGetUserMediaAndStop({video: true, audio: true});");
}
+// Flaky. See https://crbug.com/846741.
IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
- TwoGetUserMediaWithEqualConstraints) {
+ DISABLED_TwoGetUserMediaWithEqualConstraints) {
std::string constraints1 = "{video: true, audio: true}";
const std::string& constraints2 = constraints1;
std::string expected_result = "w=640:h=480-w=640:h=480";
@@ -407,8 +447,9 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
expected_result);
}
+// Flaky. See https://crbug.com/843844.
IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
- TwoGetUserMediaWithSecondVideoCropped) {
+ DISABLED_TwoGetUserMediaWithSecondVideoCropped) {
std::string constraints1 = "{video: true}";
std::string constraints2 =
"{video: {width: {exact: 640}, height: {exact: 360}}}";
@@ -417,16 +458,10 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
expected_result);
}
-// Test fails under MSan, http://crbug.com/445745
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_TwoGetUserMediaWithFirstHdSecondVga \
- DISABLED_TwoGetUserMediaWithFirstHdSecondVga
-#else
-#define MAYBE_TwoGetUserMediaWithFirstHdSecondVga \
- TwoGetUserMediaWithFirstHdSecondVga
-#endif
+// Test fails under MSan, http://crbug.com/445745.
+// Flaky. See https://crbug.com/846960.
IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
- MAYBE_TwoGetUserMediaWithFirstHdSecondVga) {
+ DISABLED_TwoGetUserMediaWithFirstHdSecondVga) {
std::string constraints1 =
"{video: {width : {exact: 1280}, height: {exact: 720}}}";
std::string constraints2 =
@@ -488,8 +523,9 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
// This test makes two getUserMedia requests, one with impossible constraints
// that should trigger an error, and one with valid constraints. The test
// verifies getUserMedia can succeed after being given impossible constraints.
+// Flaky. See https://crbug.com/846984.
IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
- TwoGetUserMediaAndCheckCallbackAfterFailure) {
+ DISABLED_TwoGetUserMediaAndCheckCallbackAfterFailure) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -539,8 +575,9 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
}
// This test calls getUserMedia and checks for aspect ratio behavior.
+// Flaky: crbug.com/846582.
IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
- TestGetUserMediaAspectRatio16To9) {
+ DISABLED_TestGetUserMediaAspectRatio16To9) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -690,8 +727,9 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, SrcObjectAddVideoTrack) {
ExecuteJavascriptAndWaitForOk("srcObjectAddVideoTrack()");
}
+// TODO(crbug.com/848330) Flaky on all platforms
IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
- SrcObjectReplaceInactiveTracks) {
+ DISABLE_SrcObjectReplaceInactiveTracks) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
@@ -707,16 +745,9 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk("srcObjectRemoveVideoTrack()");
}
-// Flaky on memory and leak sanitizers. https://crbug.com/843844
-#if defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER)
-#define MAYBE_SrcObjectRemoveFirstOfTwoVideoTracks \
- DISABLED_SrcObjectRemoveFirstOfTwoVideoTracks
-#else
-#define MAYBE_SrcObjectRemoveFirstOfTwoVideoTracks \
- SrcObjectRemoveFirstOfTwoVideoTracks
-#endif
+// Flaky. https://crbug.com/843844
IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
- SrcObjectRemoveFirstOfTwoVideoTracks) {
+ DISABLED_SrcObjectRemoveFirstOfTwoVideoTracks) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
@@ -794,7 +825,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetAudioStreamAndCheckMutingInitiallyUnmuted) {
// Muting tests do not work with the out-of-process audio service.
// https://crbug.com/843490.
- if (GetParam())
+ if (GetParam() != AudioServiceFeatures::kDisabled)
return;
ASSERT_TRUE(embedded_test_server()->Start());
@@ -823,7 +854,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetAudioStreamAndCheckMutingInitiallyMuted) {
// Muting tests do not work with the out-of-process audio service.
// https://crbug.com/843490.
- if (GetParam())
+ if (GetParam() != AudioServiceFeatures::kDisabled)
return;
ASSERT_TRUE(embedded_test_server()->Start());
@@ -849,18 +880,51 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
"failTestAfterTimeout('Got no mute event', 1500);"));
}
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+ RecoverFromCrashInAudioService) {
+ // This test only makes sense with the audio service running out of process,
+ // with or without sandbox.
+ if (GetParam() == AudioServiceFeatures::kDisabled)
+ return;
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+
+ ExecuteJavascriptAndWaitForOk("setUpForAudioServiceCrash()");
+
+ // Crash the utility process for the audio service
+ service_manager::Connector* connector =
+ ServiceManagerConnection::GetForProcess()->GetConnector();
+ audio::mojom::TestingApiPtr service_testing_api;
+ connector->BindInterface(audio::mojom::kServiceName,
+ mojo::MakeRequest(&service_testing_api));
+ service_testing_api->Crash();
+
+ ExecuteJavascriptAndWaitForOk("verifyAfterAudioServiceCrash()");
+}
+
// We run these tests with the audio service both in and out of the the browser
// process to have waterfall coverage while the feature rolls out. It should be
// removed after launch.
-#if (defined(OS_LINUX) && !defined(CHROME_OS)) || defined(OS_MACOSX) || \
- defined(OS_WIN)
+#if (defined(OS_LINUX) && !defined(CHROME_OS)) || defined(OS_MACOSX)
// Supported platforms.
-INSTANTIATE_TEST_CASE_P(, WebRtcGetUserMediaBrowserTest, ::testing::Bool());
+INSTANTIATE_TEST_CASE_P(,
+ WebRtcGetUserMediaBrowserTest,
+ ::testing::Values(AudioServiceFeatures::kDisabled,
+ AudioServiceFeatures::kOutOfProcess));
+#elif defined(OS_WIN)
+// On Windows, also run in sandboxed mode.
+INSTANTIATE_TEST_CASE_P(,
+ WebRtcGetUserMediaBrowserTest,
+ ::testing::Values(AudioServiceFeatures::kDisabled,
+ AudioServiceFeatures::kOutOfProcess,
+ AudioServiceFeatures::kSandboxed));
#else
// Platforms where the out of process audio service is not supported
INSTANTIATE_TEST_CASE_P(,
WebRtcGetUserMediaBrowserTest,
- ::testing::Values(false));
+ ::testing::Values(AudioServiceFeatures::kDisabled));
#endif
} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_internals.cc b/chromium/content/browser/webrtc/webrtc_internals.cc
index b8e4b8b1cc5..89f968cb9a9 100644
--- a/chromium/content/browser/webrtc/webrtc_internals.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals.cc
@@ -133,7 +133,8 @@ WebRTCInternals::WebRTCInternals(int aggregate_updates_ms,
command_line_derived_logging_path_.Append(kEventLogFilename);
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
- logger->EnableLocalLogging(local_logs_path);
+ logger->EnableLocalLogging(local_logs_path,
+ base::OnceCallback<void(bool)>());
}
// For clarity's sake, though these aren't supposed to be regarded now:
event_log_recordings_ = true;
@@ -376,7 +377,8 @@ void WebRTCInternals::EnableLocalEventLogRecordings(
#if defined(OS_ANDROID)
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
- logger->EnableLocalLogging(event_log_recordings_file_path_);
+ logger->EnableLocalLogging(event_log_recordings_file_path_,
+ base::OnceCallback<void(bool)>());
}
#else
DCHECK(web_contents);
@@ -397,7 +399,7 @@ void WebRTCInternals::DisableLocalEventLogRecordings() {
DCHECK(CanToggleEventLogRecordings());
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
- logger->DisableLocalLogging();
+ logger->DisableLocalLogging(base::OnceCallback<void(bool)>());
}
}
@@ -446,7 +448,7 @@ void WebRTCInternals::FileSelected(const base::FilePath& path,
event_log_recordings_ = true;
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
- logger->EnableLocalLogging(path);
+ logger->EnableLocalLogging(path, base::OnceCallback<void(bool)>());
}
break;
}
diff --git a/chromium/content/browser/webrtc/webrtc_stress_image_capture_browsertest.cc b/chromium/content/browser/webrtc/webrtc_stress_image_capture_browsertest.cc
new file mode 100644
index 00000000000..ef0f94848d5
--- /dev/null
+++ b/chromium/content/browser/webrtc/webrtc_stress_image_capture_browsertest.cc
@@ -0,0 +1,126 @@
+// Copyright 2018 The Chromium Authors. 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/test/scoped_feature_list.h"
+#include "build/build_config.h"
+#include "content/browser/webrtc/webrtc_webcam_browsertest.h"
+#include "content/public/common/content_features.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 "media/base/media_switches.h"
+#include "media/capture/video/fake_video_capture_device_factory.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#endif
+
+namespace content {
+
+namespace {
+
+static const char kImageCaptureStressHtmlFile[] =
+ "/media/image_capture_stress_test.html";
+
+enum class TargetVideoCaptureImplementation {
+ DEFAULT,
+#if defined(OS_WIN)
+ WIN_MEDIA_FOUNDATION
+#endif
+};
+
+} // namespace
+
+class WebRtcImageCaptureStressBrowserTest
+ : public UsingRealWebcam_WebRtcWebcamBrowserTest,
+ public testing::WithParamInterface<TargetVideoCaptureImplementation> {
+ public:
+ WebRtcImageCaptureStressBrowserTest() {
+ std::vector<base::Feature> features_to_enable;
+ std::vector<base::Feature> features_to_disable;
+#if defined(OS_WIN)
+ if (GetParam() == TargetVideoCaptureImplementation::WIN_MEDIA_FOUNDATION) {
+ features_to_enable.push_back(media::kMediaFoundationVideoCapture);
+ } else {
+ features_to_disable.push_back(media::kMediaFoundationVideoCapture);
+ }
+#endif
+ scoped_feature_list_.InitWithFeatures(features_to_enable,
+ features_to_disable);
+ }
+ ~WebRtcImageCaptureStressBrowserTest() override = default;
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ UsingRealWebcam_WebRtcWebcamBrowserTest::SetUpCommandLine(command_line);
+
+ ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseFakeDeviceForMediaStream));
+ }
+
+ void SetUp() override {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+ UsingRealWebcam_WebRtcWebcamBrowserTest::SetUp();
+ }
+
+ // Tries to run a |command| JS test, returning true if the test can be safely
+ // skipped or it works as intended, or false otherwise.
+ virtual bool RunImageCaptureTestCase(const std::string& command) {
+ GURL url(embedded_test_server()->GetURL(kImageCaptureStressHtmlFile));
+ NavigateToURL(shell(), url);
+
+ if (!IsWebcamAvailableOnSystem(shell()->web_contents())) {
+ LOG(WARNING) << "No video device; skipping test...";
+ return true;
+ }
+
+ LookupAndLogNameAndIdOfFirstCamera();
+
+ std::string result;
+ if (!ExecuteScriptAndExtractString(shell(), command, &result))
+ return false;
+ DLOG_IF(ERROR, result != "OK") << result;
+ return result == "OK";
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebRtcImageCaptureStressBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureStressBrowserTest,
+ MANUAL_Take10Photos) {
+ embedded_test_server()->StartAcceptingConnections();
+ ASSERT_TRUE(RunImageCaptureTestCase("testTake10PhotosSucceeds()"));
+}
+
+// Tests on real webcam can only run on platforms for which the image capture
+// API has already been implemented.
+// Note, these tests must be run sequentially, since multiple parallel test runs
+// competing for a single physical webcam typically causes failures.
+#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_ANDROID) || \
+ defined(OS_WIN)
+
+const TargetVideoCaptureImplementation
+ kTargetVideoCaptureImplementationsForRealWebcam[] = {
+ TargetVideoCaptureImplementation::DEFAULT,
+#if defined(OS_WIN)
+ TargetVideoCaptureImplementation::WIN_MEDIA_FOUNDATION
+#endif
+};
+
+INSTANTIATE_TEST_CASE_P(
+ UsingRealWebcam, // This prefix can be used with --gtest_filter to
+ // distinguish the tests using a real camera from the ones
+ // that don't.
+ WebRtcImageCaptureStressBrowserTest,
+ testing::ValuesIn(kTargetVideoCaptureImplementationsForRealWebcam));
+#endif
+
+} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc b/chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
new file mode 100644
index 00000000000..f632cd62a5f
--- /dev/null
+++ b/chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
@@ -0,0 +1,473 @@
+// Copyright 2018 The Chromium Authors. 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 "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
+#include "components/viz/common/gl_helper.h"
+#include "components/viz/common/gpu/context_provider.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/service_manager_connection.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 "gpu/command_buffer/client/gles2_interface.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/base/media_switches.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_frame_metadata.h"
+#include "media/capture/video/shared_memory_handle_provider.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/video_capture/public/mojom/constants.mojom.h"
+#include "services/video_capture/public/mojom/device_factory_provider.mojom.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+#include "ui/compositor/compositor.h"
+
+// ImageTransportFactory::GetInstance is not available on all build configs.
+#if defined(USE_AURA) || defined(OS_MACOSX)
+#define CAN_USE_IMAGE_TRANSPORT_FACTORY 1
+#endif
+
+#if defined(CAN_USE_IMAGE_TRANSPORT_FACTORY)
+#include "content/browser/compositor/image_transport_factory.h"
+
+namespace content {
+
+namespace {
+
+class InvokeClosureOnDelete
+ : public video_capture::mojom::ScopedAccessPermission {
+ public:
+ InvokeClosureOnDelete(base::OnceClosure closure)
+ : closure_(std::move(closure)) {}
+
+ ~InvokeClosureOnDelete() override { std::move(closure_).Run(); }
+
+ private:
+ base::OnceClosure closure_;
+};
+
+static const char kVideoCaptureHtmlFile[] = "/media/video_capture_test.html";
+static const char kStartVideoCaptureAndVerifySize[] =
+ "startVideoCaptureFromDeviceNamedVirtualDeviceAndVerifySize()";
+
+static const char kVirtualDeviceId[] = "/virtual/device";
+static const char kVirtualDeviceName[] = "Virtual Device";
+
+static const gfx::Size kDummyFrameDimensions(320, 200);
+static const int kDummyFrameRate = 5;
+
+} // namespace
+
+// Abstraction for logic that is different between exercising
+// DeviceFactory.AddTextureVirtualDevice() and
+// DeviceFactory.AddSharedMemoryVirtualDevice().
+class VirtualDeviceExerciser {
+ public:
+ virtual ~VirtualDeviceExerciser() {}
+ virtual void Initialize() = 0;
+ virtual void RegisterVirtualDeviceAtFactory(
+ video_capture::mojom::DeviceFactoryPtr* factory,
+ const media::VideoCaptureDeviceInfo& info) = 0;
+ virtual void PushNextFrame(base::TimeDelta timestamp) = 0;
+ virtual void ShutDown() = 0;
+};
+
+// A VirtualDeviceExerciser for exercising
+// DeviceFactory.AddTextureVirtualDevice(). It alternates between two texture
+// RGB dummy frames, one dark one and one light one.
+class TextureDeviceExerciser : public VirtualDeviceExerciser {
+ public:
+ TextureDeviceExerciser() : weak_factory_(this) {
+ DETACH_FROM_SEQUENCE(sequence_checker_);
+ }
+
+ void Initialize() override {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ CHECK(factory);
+ context_provider_ =
+ factory->GetContextFactory()->SharedMainThreadContextProvider();
+ CHECK(context_provider_);
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ CHECK(gl);
+ auto gl_helper = std::make_unique<viz::GLHelper>(
+ context_provider_->ContextGL(), context_provider_->ContextSupport());
+
+ const uint8_t kDarkFrameByteValue = 0;
+ const uint8_t kLightFrameByteValue = 200;
+ CreateDummyRgbFrame(gl, gl_helper.get(), kDarkFrameByteValue,
+ &dummy_frame_0_mailbox_holder_);
+ CreateDummyRgbFrame(gl, gl_helper.get(), kLightFrameByteValue,
+ &dummy_frame_1_mailbox_holder_);
+ }
+
+ void RegisterVirtualDeviceAtFactory(
+ video_capture::mojom::DeviceFactoryPtr* factory,
+ const media::VideoCaptureDeviceInfo& info) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ (*factory)->AddTextureVirtualDevice(info,
+ mojo::MakeRequest(&virtual_device_));
+
+ virtual_device_->OnNewMailboxHolderBufferHandle(
+ 0, media::mojom::MailboxBufferHandleSet::New(
+ std::move(dummy_frame_0_mailbox_holder_)));
+ virtual_device_->OnNewMailboxHolderBufferHandle(
+ 1, media::mojom::MailboxBufferHandleSet::New(
+ std::move(dummy_frame_1_mailbox_holder_)));
+ frame_being_consumed_[0] = false;
+ frame_being_consumed_[1] = false;
+ }
+
+ void PushNextFrame(base::TimeDelta timestamp) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (frame_being_consumed_[dummy_frame_index_]) {
+ LOG(INFO) << "Frame " << dummy_frame_index_ << " is still being consumed";
+ return;
+ }
+
+ video_capture::mojom::ScopedAccessPermissionPtr access_permission_proxy;
+ mojo::MakeStrongBinding<video_capture::mojom::ScopedAccessPermission>(
+ std::make_unique<InvokeClosureOnDelete>(
+ base::BindOnce(&TextureDeviceExerciser::OnFrameConsumptionFinished,
+ weak_factory_.GetWeakPtr(), dummy_frame_index_)),
+ mojo::MakeRequest(&access_permission_proxy));
+
+ media::VideoFrameMetadata metadata;
+ metadata.SetDouble(media::VideoFrameMetadata::FRAME_RATE, kDummyFrameRate);
+ metadata.SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
+ base::TimeTicks::Now());
+
+ media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New();
+ info->timestamp = timestamp;
+ info->pixel_format = media::PIXEL_FORMAT_ARGB;
+ info->coded_size = kDummyFrameDimensions;
+ info->visible_rect = gfx::Rect(kDummyFrameDimensions.width(),
+ kDummyFrameDimensions.height());
+ info->metadata = metadata.GetInternalValues().Clone();
+
+ frame_being_consumed_[dummy_frame_index_] = true;
+ virtual_device_->OnFrameReadyInBuffer(dummy_frame_index_,
+ std::move(access_permission_proxy),
+ std::move(info));
+
+ dummy_frame_index_ = (dummy_frame_index_ + 1) % 2;
+ }
+
+ void ShutDown() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ virtual_device_ = nullptr;
+ weak_factory_.InvalidateWeakPtrs();
+ }
+
+ private:
+ void CreateDummyRgbFrame(gpu::gles2::GLES2Interface* gl,
+ viz::GLHelper* gl_helper,
+ uint8_t value_for_all_rgb_bytes,
+ std::vector<gpu::MailboxHolder>* target) {
+ const int32_t kBytesPerRGBPixel = 3;
+ int32_t frame_size_in_bytes = kDummyFrameDimensions.width() *
+ kDummyFrameDimensions.height() *
+ kBytesPerRGBPixel;
+ std::unique_ptr<uint8_t[]> dummy_frame_data(
+ new uint8_t[frame_size_in_bytes]);
+ memset(dummy_frame_data.get(), value_for_all_rgb_bytes,
+ frame_size_in_bytes);
+ for (int i = 0; i < media::VideoFrame::kMaxPlanes; i++) {
+ // For RGB formats, only the first plane needs to be filled with an
+ // actual texture.
+ if (i != 0) {
+ target->push_back(gpu::MailboxHolder());
+ continue;
+ }
+ auto texture_id = gl_helper->CreateTexture();
+ auto mailbox_holder =
+ gl_helper->ProduceMailboxHolderFromTexture(texture_id);
+
+ gl->BindTexture(GL_TEXTURE_2D, texture_id);
+ gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kDummyFrameDimensions.width(),
+ kDummyFrameDimensions.height(), 0, GL_RGB,
+ GL_UNSIGNED_BYTE, dummy_frame_data.get());
+ gl->BindTexture(GL_TEXTURE_2D, 0);
+ target->push_back(std::move(mailbox_holder));
+ }
+ gl->ShallowFlushCHROMIUM();
+ CHECK_EQ(gl->GetError(), static_cast<GLenum>(GL_NO_ERROR));
+ }
+
+ void OnFrameConsumptionFinished(int frame_index) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ frame_being_consumed_[frame_index] = false;
+ }
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ scoped_refptr<viz::ContextProvider> context_provider_;
+ video_capture::mojom::TextureVirtualDevicePtr virtual_device_;
+ int dummy_frame_index_ = 0;
+ std::vector<gpu::MailboxHolder> dummy_frame_0_mailbox_holder_;
+ std::vector<gpu::MailboxHolder> dummy_frame_1_mailbox_holder_;
+ std::array<bool, 2> frame_being_consumed_;
+ base::WeakPtrFactory<TextureDeviceExerciser> weak_factory_;
+};
+
+// A VirtualDeviceExerciser for exercising
+// DeviceFactory.AddSharedMemoryVirtualDevice().
+// It generates (dummy) I420 frame data by setting all bytes equal to the
+// current frame count.
+class SharedMemoryDeviceExerciser : public VirtualDeviceExerciser,
+ public video_capture::mojom::Producer {
+ public:
+ SharedMemoryDeviceExerciser()
+ : producer_binding_(this), weak_factory_(this) {}
+
+ // VirtualDeviceExerciser implementation.
+ void Initialize() override {}
+ void RegisterVirtualDeviceAtFactory(
+ video_capture::mojom::DeviceFactoryPtr* factory,
+ const media::VideoCaptureDeviceInfo& info) override {
+ video_capture::mojom::ProducerPtr producer;
+ static const bool kSendBufferHandlesToProducerAsRawFileDescriptors = false;
+ producer_binding_.Bind(mojo::MakeRequest(&producer));
+ (*factory)->AddSharedMemoryVirtualDevice(
+ info, std::move(producer),
+ kSendBufferHandlesToProducerAsRawFileDescriptors,
+ mojo::MakeRequest(&virtual_device_));
+ }
+ void PushNextFrame(base::TimeDelta timestamp) override {
+ virtual_device_->RequestFrameBuffer(
+ kDummyFrameDimensions, media::VideoPixelFormat::PIXEL_FORMAT_I420,
+ base::BindOnce(&SharedMemoryDeviceExerciser::OnFrameBufferReceived,
+ weak_factory_.GetWeakPtr(), timestamp));
+ }
+ void ShutDown() override {
+ virtual_device_ = nullptr;
+ producer_binding_.Close();
+ weak_factory_.InvalidateWeakPtrs();
+ }
+
+ // video_capture::mojom::Producer implementation.
+ void OnNewBuffer(int32_t buffer_id,
+ media::mojom::VideoBufferHandlePtr buffer_handle,
+ OnNewBufferCallback callback) override {
+ CHECK(buffer_handle->is_shared_buffer_handle());
+ auto handle_provider =
+ std::make_unique<media::SharedMemoryHandleProvider>();
+ handle_provider->InitFromMojoHandle(
+ std::move(buffer_handle->get_shared_buffer_handle()));
+ outgoing_buffer_id_to_buffer_map_.insert(
+ std::make_pair(buffer_id, std::move(handle_provider)));
+ std::move(callback).Run();
+ }
+ void OnBufferRetired(int32_t buffer_id) override {
+ outgoing_buffer_id_to_buffer_map_.erase(buffer_id);
+ }
+
+ private:
+ void OnFrameBufferReceived(base::TimeDelta timestamp, int32_t buffer_id) {
+ if (buffer_id == video_capture::mojom::kInvalidBufferId)
+ return;
+
+ media::VideoFrameMetadata metadata;
+ metadata.SetDouble(media::VideoFrameMetadata::FRAME_RATE, kDummyFrameRate);
+ metadata.SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
+ base::TimeTicks::Now());
+
+ media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New();
+ info->timestamp = timestamp;
+ info->pixel_format = media::PIXEL_FORMAT_I420;
+ info->coded_size = kDummyFrameDimensions;
+ info->visible_rect = gfx::Rect(kDummyFrameDimensions.width(),
+ kDummyFrameDimensions.height());
+ info->metadata = metadata.GetInternalValues().Clone();
+
+ auto outgoing_buffer = outgoing_buffer_id_to_buffer_map_.at(buffer_id)
+ ->GetHandleForInProcessAccess();
+
+ static int frame_count = 0;
+ frame_count++;
+ memset(outgoing_buffer->data(), frame_count % 256,
+ outgoing_buffer->mapped_size());
+
+ virtual_device_->OnFrameReadyInBuffer(buffer_id, std::move(info));
+ }
+
+ mojo::Binding<video_capture::mojom::Producer> producer_binding_;
+ video_capture::mojom::SharedMemoryVirtualDevicePtr virtual_device_;
+ std::map<int32_t /*buffer_id*/,
+ std::unique_ptr<media::SharedMemoryHandleProvider>>
+ outgoing_buffer_id_to_buffer_map_;
+ base::WeakPtrFactory<SharedMemoryDeviceExerciser> weak_factory_;
+};
+
+// Integration test that obtains a connection to the video capture service via
+// the Browser process' service manager. It then registers a virtual device at
+// the service and feeds frames to it. It opens the virtual device in a <video>
+// element on a test page and verifies that the element plays in the expected
+// dimenstions and the pixel content on the element changes.
+class WebRtcVideoCaptureServiceBrowserTest : public ContentBrowserTest {
+ public:
+ WebRtcVideoCaptureServiceBrowserTest()
+ : virtual_device_thread_("Virtual Device Thread"), weak_factory_(this) {
+ scoped_feature_list_.InitAndEnableFeature(features::kMojoVideoCapture);
+ virtual_device_thread_.Start();
+ }
+
+ ~WebRtcVideoCaptureServiceBrowserTest() override {}
+
+ void AddVirtualDeviceAndStartCapture(VirtualDeviceExerciser* device_exerciser,
+ base::OnceClosure finish_test_cb) {
+ DCHECK(virtual_device_thread_.task_runner()->RunsTasksInCurrentSequence());
+ connector_->BindInterface(video_capture::mojom::kServiceName, &provider_);
+ provider_->ConnectToDeviceFactory(mojo::MakeRequest(&factory_));
+
+ media::VideoCaptureDeviceInfo info;
+ info.descriptor.device_id = kVirtualDeviceId;
+ info.descriptor.set_display_name(kVirtualDeviceName);
+ info.descriptor.capture_api = media::VideoCaptureApi::VIRTUAL_DEVICE;
+
+ device_exerciser->RegisterVirtualDeviceAtFactory(&factory_, info);
+
+ main_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcVideoCaptureServiceBrowserTest::
+ OpenVirtualDeviceInRendererAndWaitForPlaying,
+ base::Unretained(this),
+ media::BindToCurrentLoop(base::BindOnce(
+ &WebRtcVideoCaptureServiceBrowserTest::
+ ShutDownVirtualDeviceAndContinue,
+ base::Unretained(this), device_exerciser,
+ std::move(finish_test_cb)))));
+
+ PushDummyFrameAndScheduleNextPush(device_exerciser);
+ }
+
+ void PushDummyFrameAndScheduleNextPush(
+ VirtualDeviceExerciser* device_exerciser) {
+ DCHECK(virtual_device_thread_.task_runner()->RunsTasksInCurrentSequence());
+ device_exerciser->PushNextFrame(CalculateTimeSinceFirstInvocation());
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcVideoCaptureServiceBrowserTest::
+ PushDummyFrameAndScheduleNextPush,
+ weak_factory_.GetWeakPtr(), device_exerciser),
+ base::TimeDelta::FromMilliseconds(1000 / kDummyFrameRate));
+ }
+
+ void ShutDownVirtualDeviceAndContinue(
+ VirtualDeviceExerciser* device_exerciser,
+ base::OnceClosure continuation) {
+ DCHECK(virtual_device_thread_.task_runner()->RunsTasksInCurrentSequence());
+ LOG(INFO) << "Shutting down virtual device";
+ device_exerciser->ShutDown();
+ factory_ = nullptr;
+ provider_ = nullptr;
+ weak_factory_.InvalidateWeakPtrs();
+ std::move(continuation).Run();
+ }
+
+ void OpenVirtualDeviceInRendererAndWaitForPlaying(
+ base::OnceClosure finish_test_cb) {
+ DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+ embedded_test_server()->StartAcceptingConnections();
+ GURL url(embedded_test_server()->GetURL(kVideoCaptureHtmlFile));
+ NavigateToURL(shell(), url);
+
+ std::string result;
+ // Start video capture and wait until it started rendering
+ ASSERT_TRUE(ExecuteScriptAndExtractString(
+ shell(), kStartVideoCaptureAndVerifySize, &result));
+ ASSERT_EQ("OK", result);
+
+ std::move(finish_test_cb).Run();
+ }
+
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ // Note: We are not planning to actually use the fake device, but we want
+ // to avoid enumerating or otherwise calling into real capture devices.
+ command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
+ command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
+ }
+
+ void SetUp() override {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+ EnablePixelOutput();
+ ContentBrowserTest::SetUp();
+ }
+
+ void Initialize() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ main_task_runner_ = base::ThreadTaskRunnerHandle::Get();
+
+ auto* connection = content::ServiceManagerConnection::GetForProcess();
+ ASSERT_TRUE(connection);
+ auto* connector = connection->GetConnector();
+ ASSERT_TRUE(connector);
+ // We need to clone it so that we can use the clone on a different thread.
+ connector_ = connector->Clone();
+ }
+
+ base::Thread virtual_device_thread_;
+ scoped_refptr<base::TaskRunner> main_task_runner_;
+ std::unique_ptr<service_manager::Connector> connector_;
+
+ private:
+ base::TimeDelta CalculateTimeSinceFirstInvocation() {
+ if (first_frame_time_.is_null())
+ first_frame_time_ = base::TimeTicks::Now();
+ return base::TimeTicks::Now() - first_frame_time_;
+ }
+
+ base::test::ScopedFeatureList scoped_feature_list_;
+ video_capture::mojom::DeviceFactoryProviderPtr provider_;
+ video_capture::mojom::DeviceFactoryPtr factory_;
+ base::TimeTicks first_frame_time_;
+ base::WeakPtrFactory<WebRtcVideoCaptureServiceBrowserTest> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebRtcVideoCaptureServiceBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(
+ WebRtcVideoCaptureServiceBrowserTest,
+ FramesSentThroughTextureVirtualDeviceGetDisplayedOnPage) {
+ Initialize();
+ auto device_exerciser = std::make_unique<TextureDeviceExerciser>();
+ device_exerciser->Initialize();
+
+ base::RunLoop run_loop;
+ virtual_device_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcVideoCaptureServiceBrowserTest::
+ AddVirtualDeviceAndStartCapture,
+ base::Unretained(this), device_exerciser.get(),
+ media::BindToCurrentLoop(run_loop.QuitClosure())));
+ run_loop.Run();
+}
+
+IN_PROC_BROWSER_TEST_F(
+ WebRtcVideoCaptureServiceBrowserTest,
+ FramesSentThroughSharedMemoryVirtualDeviceGetDisplayedOnPage) {
+ Initialize();
+ auto device_exerciser = std::make_unique<SharedMemoryDeviceExerciser>();
+ device_exerciser->Initialize();
+
+ base::RunLoop run_loop;
+ virtual_device_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcVideoCaptureServiceBrowserTest::
+ AddVirtualDeviceAndStartCapture,
+ base::Unretained(this), device_exerciser.get(),
+ media::BindToCurrentLoop(run_loop.QuitClosure())));
+ run_loop.Run();
+}
+
+} // namespace content
+
+#endif // defined(CAN_USE_IMAGE_TRANSPORT_FACTORY)
diff --git a/chromium/content/browser/websockets/websocket_manager.cc b/chromium/content/browser/websockets/websocket_manager.cc
index c1ae8621402..13db9a3a2df 100644
--- a/chromium/content/browser/websockets/websocket_manager.cc
+++ b/chromium/content/browser/websockets/websocket_manager.cc
@@ -161,6 +161,7 @@ void WebSocketManager::CreateWebSocket(
int process_id,
int frame_id,
url::Origin origin,
+ network::mojom::AuthenticationHandlerPtr auth_handler,
network::mojom::WebSocketRequest request) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -172,9 +173,11 @@ void WebSocketManager::CreateWebSocket(
network::mojom::NetworkContext* network_context =
storage_partition->GetNetworkContext();
network_context->CreateWebSocket(std::move(request), process_id, frame_id,
- origin);
+ origin, std::move(auth_handler));
return;
}
+ // |auth_handler| is provided only for the network service path.
+ DCHECK(!auth_handler);
// Maintain a WebSocketManager per RenderProcessHost. While the instance of
// WebSocketManager is allocated on the UI thread, it must only be used and
@@ -278,7 +281,7 @@ std::unique_ptr<network::WebSocket> WebSocketManager::DoCreateWebSocketInternal(
url::Origin origin,
base::TimeDelta delay) {
return std::make_unique<network::WebSocket>(
- std::move(delegate), std::move(request),
+ std::move(delegate), std::move(request), nullptr,
std::move(pending_connection_tracker), child_id, frame_id,
std::move(origin), delay);
}
diff --git a/chromium/content/browser/websockets/websocket_manager.h b/chromium/content/browser/websockets/websocket_manager.h
index 006b5bd6ae9..c010f09ed04 100644
--- a/chromium/content/browser/websockets/websocket_manager.h
+++ b/chromium/content/browser/websockets/websocket_manager.h
@@ -34,10 +34,12 @@ class CONTENT_EXPORT WebSocketManager
// - For dedicated workers, |frame_id| should be its parent frame's id.
// - For shared workers and service workers, |frame_id| should be
// MSG_ROUTING_NONE because they do not have a frame.
- static void CreateWebSocket(int process_id,
- int frame_id,
- url::Origin origin,
- network::mojom::WebSocketRequest request);
+ static void CreateWebSocket(
+ int process_id,
+ int frame_id,
+ url::Origin origin,
+ network::mojom::AuthenticationHandlerPtr auth_handler,
+ network::mojom::WebSocketRequest request);
// net::URLRequestContextGetterObserver implementation.
void OnContextShuttingDown() override;
diff --git a/chromium/content/browser/websockets/websocket_manager_unittest.cc b/chromium/content/browser/websockets/websocket_manager_unittest.cc
index 1cee833398c..9aa0b834bf2 100644
--- a/chromium/content/browser/websockets/websocket_manager_unittest.cc
+++ b/chromium/content/browser/websockets/websocket_manager_unittest.cc
@@ -32,6 +32,7 @@ class TestWebSocketImpl : public network::WebSocket {
base::TimeDelta delay)
: network::WebSocket(std::move(delegate),
std::move(request),
+ nullptr,
std::move(pending_connection_tracker),
process_id,
frame_id,
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 d741b28c8be..5fd3c07d4ef 100644
--- a/chromium/content/browser/webui/content_web_ui_controller_factory.cc
+++ b/chromium/content/browser/webui/content_web_ui_controller_factory.cc
@@ -57,35 +57,37 @@ bool ContentWebUIControllerFactory::UseWebUIBindingsForURL(
return UseWebUIForURL(browser_context, url);
}
-WebUIController* ContentWebUIControllerFactory::CreateWebUIControllerForURL(
- WebUI* web_ui, const GURL& url) const {
+std::unique_ptr<WebUIController>
+ContentWebUIControllerFactory::CreateWebUIControllerForURL(
+ WebUI* web_ui,
+ const GURL& url) const {
if (!url.SchemeIs(kChromeUIScheme))
return nullptr;
if (url.host_piece() == kChromeUIAppCacheInternalsHost)
- return new AppCacheInternalsUI(web_ui);
+ return std::make_unique<AppCacheInternalsUI>(web_ui);
if (url.host_piece() == kChromeUIGpuHost)
- return new GpuInternalsUI(web_ui);
+ return std::make_unique<GpuInternalsUI>(web_ui);
if (url.host_piece() == kChromeUIHistogramHost)
- return new HistogramsInternalsUI(web_ui);
+ return std::make_unique<HistogramsInternalsUI>(web_ui);
if (url.host_piece() == kChromeUIIndexedDBInternalsHost)
- return new IndexedDBInternalsUI(web_ui);
+ return std::make_unique<IndexedDBInternalsUI>(web_ui);
if (url.host_piece() == kChromeUIMediaInternalsHost)
- return new MediaInternalsUI(web_ui);
+ return std::make_unique<MediaInternalsUI>(web_ui);
if (url.host_piece() == kChromeUIAccessibilityHost)
- return new AccessibilityUI(web_ui);
+ return std::make_unique<AccessibilityUI>(web_ui);
if (url.host_piece() == kChromeUIServiceWorkerInternalsHost)
- return new ServiceWorkerInternalsUI(web_ui);
+ return std::make_unique<ServiceWorkerInternalsUI>(web_ui);
if (url.host_piece() == kChromeUINetworkErrorsListingHost)
- return new NetworkErrorsListingUI(web_ui);
+ return std::make_unique<NetworkErrorsListingUI>(web_ui);
#if !defined(OS_ANDROID)
if (url.host_piece() == kChromeUITracingHost)
- return new TracingUI(web_ui);
+ return std::make_unique<TracingUI>(web_ui);
#endif
if (url.host_piece() == kChromeUIWebRTCInternalsHost)
- return new WebRTCInternalsUI(web_ui);
+ return std::make_unique<WebRTCInternalsUI>(web_ui);
if (url.host_piece() == kChromeUIProcessInternalsHost)
- return new ProcessInternalsUI(web_ui);
+ return std::make_unique<ProcessInternalsUI>(web_ui);
return nullptr;
}
diff --git a/chromium/content/browser/webui/content_web_ui_controller_factory.h b/chromium/content/browser/webui/content_web_ui_controller_factory.h
index 15f782c3255..8d5fe5737a6 100644
--- a/chromium/content/browser/webui/content_web_ui_controller_factory.h
+++ b/chromium/content/browser/webui/content_web_ui_controller_factory.h
@@ -15,16 +15,18 @@ namespace content {
class CONTENT_EXPORT ContentWebUIControllerFactory
: public WebUIControllerFactory {
public:
+ static ContentWebUIControllerFactory* GetInstance();
+
+ // WebUIControllerFactory:
WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
const GURL& url) const override;
bool UseWebUIForURL(BrowserContext* browser_context,
const GURL& url) const override;
bool UseWebUIBindingsForURL(BrowserContext* browser_context,
const GURL& url) const override;
- WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
- const GURL& url) const override;
-
- static ContentWebUIControllerFactory* GetInstance();
+ std::unique_ptr<WebUIController> CreateWebUIControllerForURL(
+ WebUI* web_ui,
+ const GURL& url) const override;
protected:
ContentWebUIControllerFactory();
diff --git a/chromium/content/browser/webui/shared_resources_data_source.cc b/chromium/content/browser/webui/shared_resources_data_source.cc
index a883e7e8c15..b00558bd012 100644
--- a/chromium/content/browser/webui/shared_resources_data_source.cc
+++ b/chromium/content/browser/webui/shared_resources_data_source.cc
@@ -7,13 +7,16 @@
#include <stddef.h>
#include "base/containers/hash_tables.h"
+#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
+#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/url_constants.h"
#include "mojo/public/js/grit/mojo_bindings_resources.h"
#include "mojo/public/js/grit/mojo_bindings_resources_map.h"
@@ -36,16 +39,50 @@ struct IdrGzipped {
};
using ResourcesMap = base::hash_map<std::string, IdrGzipped>;
-// TODO(rkc): Once we have a separate source for apps, remove '*/apps/' aliases.
-const char* const kPathAliases[][2] = {
- {"../../../third_party/polymer/v1_0/components-chromium/", "polymer/v1_0/"},
- {"../../../third_party/web-animations-js/sources/",
- "polymer/v1_0/web-animations-js/"},
- {"../../views/resources/default_100_percent/common/", "images/apps/"},
- {"../../views/resources/default_200_percent/common/", "images/2x/apps/"},
- {"../../webui/resources/cr_components/", "cr_components/"},
- {"../../webui/resources/cr_elements/", "cr_elements/"},
-};
+const std::map<std::string, std::string> CreateAliasesMap() {
+ // TODO(rkc): Once we have a separate source for apps, remove '*/apps/'
+ // aliases.
+ std::map<std::string, std::string> aliases = {
+ {"../../../third_party/polymer/v1_0/components-chromium/",
+ "polymer/v1_0/"},
+ {"../../../third_party/web-animations-js/sources/",
+ "polymer/v1_0/web-animations-js/"},
+ {"../../views/resources/default_100_percent/common/", "images/apps/"},
+ {"../../views/resources/default_200_percent/common/", "images/2x/apps/"},
+ {"../../webui/resources/cr_components/", "cr_components/"},
+ {"../../webui/resources/cr_elements/", "cr_elements/"},
+ };
+
+#if !defined(OS_ANDROID)
+ if (base::FeatureList::IsEnabled(features::kWebUIPolymer2)) {
+ aliases["../../../third_party/polymer/v1_0/components-chromium/polymer2/"] =
+ "polymer/v1_0/polymer/";
+ }
+#endif // !defined(OS_ANDROID)
+ return aliases;
+}
+
+#if !defined(OS_ANDROID)
+bool ShouldIgnore(std::string resource) {
+ if (base::FeatureList::IsEnabled(features::kWebUIPolymer2) &&
+ base::StartsWith(
+ resource,
+ "../../../third_party/polymer/v1_0/components-chromium/polymer/",
+ base::CompareCase::SENSITIVE)) {
+ return true;
+ }
+
+ if (!base::FeatureList::IsEnabled(features::kWebUIPolymer2) &&
+ base::StartsWith(
+ resource,
+ "../../../third_party/polymer/v1_0/components-chromium/polymer2/",
+ base::CompareCase::SENSITIVE)) {
+ return true;
+ }
+
+ return false;
+}
+#endif // !defined(OS_ANDROID)
void AddResource(const std::string& path,
int resource_id,
@@ -57,15 +94,24 @@ void AddResource(const std::string& path,
}
const ResourcesMap* CreateResourcesMap() {
+ std::map<std::string, std::string> aliases = CreateAliasesMap();
+
ResourcesMap* result = new ResourcesMap();
for (size_t i = 0; i < kWebuiResourcesSize; ++i) {
const auto& resource = kWebuiResources[i];
+
+#if !defined(OS_ANDROID)
+ if (ShouldIgnore(resource.name))
+ continue;
+#endif // !defined(OS_ANDROID)
+
AddResource(resource.name, resource.value, resource.gzipped, result);
- for (const char* const (&alias)[2] : kPathAliases) {
- if (base::StartsWith(resource.name, alias[0],
+
+ for (auto it = aliases.begin(); it != aliases.end(); ++it) {
+ if (base::StartsWith(resource.name, it->first,
base::CompareCase::SENSITIVE)) {
std::string resource_name(resource.name);
- AddResource(alias[1] + resource_name.substr(strlen(alias[0])),
+ AddResource(it->second + resource_name.substr(it->first.length()),
resource.value, resource.gzipped, result);
}
}
diff --git a/chromium/content/browser/webui/url_data_manager_backend.cc b/chromium/content/browser/webui/url_data_manager_backend.cc
index 96d91340510..80f12df9d42 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend.cc
@@ -16,8 +16,8 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
-#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -63,7 +63,7 @@ const char kNetworkErrorKey[] = "netError";
bool SchemeIsInSchemes(const std::string& scheme,
const std::vector<std::string>& schemes) {
- return std::find(schemes.begin(), schemes.end(), scheme) != schemes.end();
+ return base::ContainsValue(schemes, scheme);
}
// Returns a value of 'Origin:' header for the |request| if the header is set.
@@ -119,9 +119,7 @@ class URLRequestChromeJob : public net::URLRequestJob {
is_gzipped_ = is_gzipped;
}
- void SetReplacements(const ui::TemplateReplacements* replacements) {
- replacements_ = replacements;
- }
+ void SetSource(scoped_refptr<URLDataSourceImpl> source) { source_ = source; }
private:
~URLRequestChromeJob() override;
@@ -162,8 +160,10 @@ class URLRequestChromeJob : public net::URLRequestJob {
// resources in resources.pak use compress="gzip".
bool is_gzipped_;
- // Replacement dictionary for i18n.
- const ui::TemplateReplacements* replacements_;
+ // The URLDataSourceImpl that is servicing this request. This is a shared
+ // pointer so that the request can continue to be served even if the source is
+ // detached from the backend that initially owned it.
+ scoped_refptr<URLDataSourceImpl> source_;
// The backend is owned by net::URLRequestContext and always outlives us.
URLDataManagerBackend* const backend_;
@@ -181,7 +181,6 @@ URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request,
data_available_status_(net::OK),
pending_buf_size_(0),
is_gzipped_(false),
- replacements_(nullptr),
backend_(backend),
weak_factory_(this) {
DCHECK(backend);
@@ -247,9 +246,20 @@ std::unique_ptr<net::SourceStream> URLRequestChromeJob::SetUpSourceStream() {
net::SourceStream::TYPE_GZIP);
}
- if (replacements_) {
+ // The URLRequestJob and the SourceStreams we are creating are owned by the
+ // same parent URLRequest, thus it is safe to pass the replacements via a raw
+ // pointer.
+ const ui::TemplateReplacements* replacements = nullptr;
+ if (source_)
+ replacements = source_->GetReplacements();
+ if (replacements) {
+ // It is safe to pass the raw replacements directly to the source stream, as
+ // both this URLRequestChromeJob and the I18nSourceStream are owned by the
+ // same root URLRequest. The replacements are owned by the URLDataSourceImpl
+ // which we keep alive via |source_|, ensuring its lifetime is also bound
+ // to the safe URLRequest.
source_stream = ui::I18nSourceStream::Create(
- std::move(source_stream), net::SourceStream::TYPE_NONE, replacements_);
+ std::move(source_stream), net::SourceStream::TYPE_NONE, replacements);
}
return source_stream;
@@ -404,18 +414,14 @@ class ChromeProtocolHandler
} // namespace
URLDataManagerBackend::URLDataManagerBackend()
- : next_request_id_(0) {
+ : next_request_id_(0), weak_factory_(this) {
URLDataSource* shared_source = new SharedResourcesDataSource();
URLDataSourceImpl* source_impl =
new URLDataSourceImpl(shared_source->GetSource(), shared_source);
AddDataSource(source_impl);
}
-URLDataManagerBackend::~URLDataManagerBackend() {
- for (const auto& i : data_sources_)
- i.second->backend_ = nullptr;
- data_sources_.clear();
-}
+URLDataManagerBackend::~URLDataManagerBackend() = default;
// static
std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>
@@ -430,14 +436,13 @@ URLDataManagerBackend::CreateProtocolHandler(
void URLDataManagerBackend::AddDataSource(
URLDataSourceImpl* source) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DataSourceMap::iterator i = data_sources_.find(source->source_name());
- if (i != data_sources_.end()) {
- if (!source->source()->ShouldReplaceExistingSource())
+ if (!source->source()->ShouldReplaceExistingSource()) {
+ DataSourceMap::iterator i = data_sources_.find(source->source_name());
+ if (i != data_sources_.end())
return;
- i->second->backend_ = nullptr;
}
data_sources_[source->source_name()] = source;
- source->backend_ = this;
+ source->backend_ = weak_factory_.GetWeakPtr();
}
void URLDataManagerBackend::UpdateWebUIDataSource(
@@ -493,7 +498,7 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
// replacements upon.
std::string mime_type = source->source()->GetMimeType(path);
if (mime_type == "text/html")
- job->SetReplacements(source->GetReplacements());
+ job->SetSource(source);
// Also notifies that the headers are complete.
job->MimeTypeAvailable(mime_type);
diff --git a/chromium/content/browser/webui/url_data_manager_backend.h b/chromium/content/browser/webui/url_data_manager_backend.h
index a6f3ab913fb..d5009883c92 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.h
+++ b/chromium/content/browser/webui/url_data_manager_backend.h
@@ -12,6 +12,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "base/values.h"
#include "content/browser/webui/url_data_manager.h"
@@ -123,6 +124,12 @@ class URLDataManagerBackend : public base::SupportsUserData::Data {
// The ID we'll use for the next request we receive.
RequestID next_request_id_;
+ // Vends weak pointers to URLDataSources, allowing them to continue referring
+ // to the backend that originally owned them, even if they've been replaced
+ // and detached from the backend. This allows outstanding asynchronous queries
+ // to be served and routed to the backend to which they were original issued.
+ base::WeakPtrFactory<URLDataManagerBackend> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(URLDataManagerBackend);
};
diff --git a/chromium/content/browser/webui/url_data_source_impl.h b/chromium/content/browser/webui/url_data_source_impl.h
index 77c2e975d7a..62cbd439883 100644
--- a/chromium/content/browser/webui/url_data_source_impl.h
+++ b/chromium/content/browser/webui/url_data_source_impl.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
#include "content/browser/webui/url_data_manager.h"
#include "content/common/content_export.h"
@@ -90,13 +91,18 @@ class URLDataSourceImpl : public base::RefCountedThreadSafe<
const std::string source_name_;
// This field is set and maintained by URLDataManagerBackend. It is set when
- // the DataSource is added, and unset if the DataSource is removed. A
- // DataSource can be removed in two ways: the URLDataManagerBackend is
- // deleted, or another DataSource is registered with the same name. backend_
- // should only be accessed on the IO thread. This reference can't be via a
- // scoped_refptr else there would be a cycle between the backend and data
- // source.
- URLDataManagerBackend* backend_;
+ // the DataSource is added. A DataSource can be removed in two ways:
+ // (1) The URLDataManagerBackend is deleted, and the weak ptr is invalidated.
+ // In this case queries pending against this data source will implicitly
+ // be dropped as their responses will have no backend for routing.
+ // (2) Another DataSource is registered with the same name. In this case the
+ // backend still exists and remains referenced by this data source,
+ // allowing pending queries to be routed to the backend that formerly
+ // owned them.
+ // This field should only be referenced on the IO thread. This reference can't
+ // be via a scoped_refptr else there would be a cycle between the backend and
+ // the data source.
+ base::WeakPtr<URLDataManagerBackend> backend_;
std::unique_ptr<URLDataSource> source_;
};
diff --git a/chromium/content/browser/webui/web_ui_controller_factory_registry.cc b/chromium/content/browser/webui/web_ui_controller_factory_registry.cc
index dd0e955be8d..ab265d71210 100644
--- a/chromium/content/browser/webui/web_ui_controller_factory_registry.cc
+++ b/chromium/content/browser/webui/web_ui_controller_factory_registry.cc
@@ -9,6 +9,7 @@
#include "base/lazy_instance.h"
#include "content/browser/frame_host/debug_urls.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "url/gurl.h"
@@ -39,13 +40,14 @@ WebUIControllerFactoryRegistry* WebUIControllerFactoryRegistry::GetInstance() {
return base::Singleton<WebUIControllerFactoryRegistry>::get();
}
-WebUIController* WebUIControllerFactoryRegistry::CreateWebUIControllerForURL(
- WebUI* web_ui, const GURL& url) const {
- std::vector<WebUIControllerFactory*>* factories =
- g_web_ui_controller_factories.Pointer();
- for (size_t i = 0; i < factories->size(); ++i) {
- WebUIController* controller = (*factories)[i]->CreateWebUIControllerForURL(
- web_ui, url);
+std::unique_ptr<WebUIController>
+WebUIControllerFactoryRegistry::CreateWebUIControllerForURL(
+ WebUI* web_ui,
+ const GURL& url) const {
+ std::vector<WebUIControllerFactory*>& factories =
+ g_web_ui_controller_factories.Get();
+ for (const WebUIControllerFactory* factory : factories) {
+ auto controller = factory->CreateWebUIControllerForURL(web_ui, url);
if (controller)
return controller;
}
diff --git a/chromium/content/browser/webui/web_ui_controller_factory_registry.h b/chromium/content/browser/webui/web_ui_controller_factory_registry.h
index 11020c2da24..466a62d67bb 100644
--- a/chromium/content/browser/webui/web_ui_controller_factory_registry.h
+++ b/chromium/content/browser/webui/web_ui_controller_factory_registry.h
@@ -20,8 +20,9 @@ class CONTENT_EXPORT WebUIControllerFactoryRegistry
// WebUIControllerFactory implementation. Each method loops through the same
// method on all the factories.
- WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
- const GURL& url) const override;
+ std::unique_ptr<WebUIController> CreateWebUIControllerForURL(
+ WebUI* web_ui,
+ const GURL& url) const override;
WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
const GURL& url) const override;
bool UseWebUIForURL(BrowserContext* browser_context,
diff --git a/chromium/content/browser/webui/web_ui_impl.cc b/chromium/content/browser/webui/web_ui_impl.cc
index ceac82cbc8d..1868b575f02 100644
--- a/chromium/content/browser/webui/web_ui_impl.cc
+++ b/chromium/content/browser/webui/web_ui_impl.cc
@@ -177,8 +177,9 @@ WebUIController* WebUIImpl::GetController() const {
return controller_.get();
}
-void WebUIImpl::SetController(WebUIController* controller) {
- controller_.reset(controller);
+void WebUIImpl::SetController(std::unique_ptr<WebUIController> controller) {
+ DCHECK(controller);
+ controller_ = std::move(controller);
}
bool WebUIImpl::CanCallJavascript() {
@@ -250,7 +251,7 @@ void WebUIImpl::CallJavascriptFunctionUnsafe(
void WebUIImpl::RegisterMessageCallback(base::StringPiece message,
const MessageCallback& callback) {
- message_callbacks_.emplace(message, callback);
+ message_callbacks_.emplace(message.as_string(), callback);
}
void WebUIImpl::ProcessWebUIMessage(const GURL& source_url,
diff --git a/chromium/content/browser/webui/web_ui_impl.h b/chromium/content/browser/webui/web_ui_impl.h
index 484f918c98c..a0e36cec6e3 100644
--- a/chromium/content/browser/webui/web_ui_impl.h
+++ b/chromium/content/browser/webui/web_ui_impl.h
@@ -45,7 +45,7 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
// WebUI implementation:
WebContents* GetWebContents() const override;
WebUIController* GetController() const override;
- void SetController(WebUIController* controller) override;
+ void SetController(std::unique_ptr<WebUIController> controller) override;
float GetDeviceScaleFactor() const override;
const base::string16& GetOverriddenTitle() const override;
void OverrideTitle(const base::string16& title) override;
diff --git a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
index cf09e884aed..d8ab9ec2be1 100644
--- a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -5,6 +5,8 @@
#include <limits>
#include <utility>
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/macros.h"
@@ -13,6 +15,7 @@
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_frame_host.h"
@@ -22,8 +25,10 @@
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/bindings_policy.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/common/url_utils.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -32,7 +37,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 "net/test/embedded_test_server/embedded_test_server.h"
#include "services/service_manager/public/cpp/binder_registry.h"
namespace content {
@@ -101,8 +105,11 @@ class BrowserTargetImpl : public mojom::BrowserTarget {
// WebUIController that sets up mojo bindings.
class TestWebUIController : public WebUIController {
public:
- TestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
+ TestWebUIController(WebUI* web_ui,
+ base::RunLoop* run_loop,
+ int bindings = BINDINGS_POLICY_MOJO_WEB_UI)
: WebUIController(web_ui), run_loop_(run_loop) {
+ web_ui->SetBindings(bindings);
WebUIDataSource* data_source = WebUIDataSource::Create("mojo-web-ui");
data_source->SetRequestFilter(base::Bind(&GetResource));
WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
@@ -152,36 +159,76 @@ class PingTestWebUIController : public TestWebUIController,
// WebUIControllerFactory that creates TestWebUIController.
class TestWebUIControllerFactory : public WebUIControllerFactory {
public:
- TestWebUIControllerFactory() : run_loop_(nullptr) {}
+ TestWebUIControllerFactory()
+ : run_loop_(nullptr),
+ registered_controllers_(
+ {{"ping", base::BindRepeating(
+ &TestWebUIControllerFactory::CreatePingController,
+ base::Unretained(this))},
+ {"hybrid", base::BindRepeating(
+ &TestWebUIControllerFactory::CreateHybridController,
+ base::Unretained(this))},
+ {"webui_bindings",
+ base::BindRepeating(
+ &TestWebUIControllerFactory::CreateWebUIController,
+ base::Unretained(this))}}) {}
void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }
- WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
- const GURL& url) const override {
- if (url.query() == "ping")
- return new PingTestWebUIController(web_ui, run_loop_);
- return new TestWebUIController(web_ui, run_loop_);
+ std::unique_ptr<WebUIController> CreateWebUIControllerForURL(
+ WebUI* web_ui,
+ const GURL& url) const override {
+ if (!web_ui_enabled_ || !url.SchemeIs(kChromeUIScheme))
+ return nullptr;
+
+ auto it = registered_controllers_.find(url.query());
+ if (it != registered_controllers_.end())
+ return it->second.Run(web_ui);
+
+ return std::make_unique<TestWebUIController>(web_ui, run_loop_);
}
+
WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
const GURL& url) const override {
- if (!web_ui_enabled_)
+ if (!web_ui_enabled_ || !url.SchemeIs(kChromeUIScheme))
return WebUI::kNoWebUI;
+
return reinterpret_cast<WebUI::TypeID>(1);
}
+
bool UseWebUIForURL(BrowserContext* browser_context,
const GURL& url) const override {
- return true;
+ return GetWebUIType(browser_context, url) != WebUI::kNoWebUI;
}
bool UseWebUIBindingsForURL(BrowserContext* browser_context,
const GURL& url) const override {
- return true;
+ return GetWebUIType(browser_context, url) != WebUI::kNoWebUI;
}
void set_web_ui_enabled(bool enabled) { web_ui_enabled_ = enabled; }
private:
+ std::unique_ptr<WebUIController> CreatePingController(WebUI* web_ui) {
+ return std::make_unique<PingTestWebUIController>(web_ui, run_loop_);
+ }
+
+ std::unique_ptr<WebUIController> CreateHybridController(WebUI* web_ui) {
+ return std::make_unique<TestWebUIController>(
+ web_ui, run_loop_,
+ BINDINGS_POLICY_WEB_UI | BINDINGS_POLICY_MOJO_WEB_UI);
+ }
+
+ std::unique_ptr<WebUIController> CreateWebUIController(WebUI* web_ui) {
+ return std::make_unique<TestWebUIController>(web_ui, run_loop_,
+ BINDINGS_POLICY_WEB_UI);
+ }
+
base::RunLoop* run_loop_;
bool web_ui_enabled_ = true;
+ const base::flat_map<
+ std::string,
+ base::RepeatingCallback<std::unique_ptr<WebUIController>(WebUI*)>>
+ registered_controllers_;
DISALLOW_COPY_AND_ASSIGN(TestWebUIControllerFactory);
};
@@ -198,6 +245,24 @@ class WebUIMojoTest : public ContentBrowserTest {
TestWebUIControllerFactory* factory() { return &factory_; }
+ void NavigateWithNewWebUI(const std::string& path) {
+ // Load an invalid URL first so that a new WebUI is set up when we load
+ // the URL we're actually interested in.
+ EXPECT_FALSE(NavigateToURL(shell(), GURL()));
+
+ constexpr char kChromeUIMojoWebUIOrigin[] = "chrome://mojo-web-ui/";
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(kChromeUIMojoWebUIOrigin + path)));
+ }
+
+ // Run |script| and return a boolean result.
+ bool RunBoolFunction(const std::string& script) {
+ bool result = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ shell()->web_contents(), "domAutomationController.send(" + script + ")",
+ &result));
+ return result;
+ }
+
private:
TestWebUIControllerFactory factory_;
@@ -225,7 +290,6 @@ IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEndPing) {
return;
g_got_message = false;
- ASSERT_TRUE(embedded_test_server()->Start());
base::RunLoop run_loop;
factory()->set_run_loop(&run_loop);
GURL test_url("chrome://mojo-web-ui/web_ui_mojo.html?ping");
@@ -248,29 +312,60 @@ IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEndPing) {
other_shell->web_contents()->GetMainFrame()->GetProcess());
}
-IN_PROC_BROWSER_TEST_F(WebUIMojoTest, NativeMojoAvailable) {
- ASSERT_TRUE(embedded_test_server()->Start());
- const GURL kTestWebUIUrl("chrome://mojo-web-ui/web_ui_mojo_native.html");
- NavigateToURL(shell(), kTestWebUIUrl);
+// Disabled due to flakiness: crbug.com/860385.
+#if defined(OS_ANDROID)
+#define MAYBE_NativeMojoAvailable DISABLED_NativeMojoAvailable
+#else
+#define MAYBE_NativeMojoAvailable NativeMojoAvailable
+#endif
+IN_PROC_BROWSER_TEST_F(WebUIMojoTest, MAYBE_NativeMojoAvailable) {
+ // Mojo bindings should be enabled.
+ NavigateWithNewWebUI("web_ui_mojo_native.html");
+ EXPECT_TRUE(RunBoolFunction("isNativeMojoAvailable()"));
+
+ // Now navigate again with normal WebUI bindings and ensure chrome.send is
+ // available.
+ NavigateWithNewWebUI("web_ui_mojo_native.html?webui_bindings");
+ EXPECT_FALSE(RunBoolFunction("isNativeMojoAvailable()"));
- bool is_native_mojo_available = false;
- const std::string kTestScript("isNativeMojoAvailable()");
- ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "domAutomationController.send(" + kTestScript + ")",
- &is_native_mojo_available));
- EXPECT_TRUE(is_native_mojo_available);
+ // Now navigate again both WebUI and Mojo bindings and ensure chrome.send is
+ // available.
+ NavigateWithNewWebUI("web_ui_mojo_native.html?hybrid");
+ EXPECT_TRUE(RunBoolFunction("isNativeMojoAvailable()"));
// Now navigate again with WebUI disabled and ensure the native bindings are
// not available.
factory()->set_web_ui_enabled(false);
- const std::string kTestNonWebUIUrl("/web_ui_mojo_native.html");
- NavigateToURL(shell(), embedded_test_server()->GetURL(kTestNonWebUIUrl));
- ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "domAutomationController.send(" + kTestScript + ")",
- &is_native_mojo_available));
- EXPECT_FALSE(is_native_mojo_available);
+ NavigateWithNewWebUI("web_ui_mojo_native.html?hybrid");
+ EXPECT_FALSE(RunBoolFunction("isNativeMojoAvailable()"));
+}
+
+// Disabled due to flakiness: crbug.com/860385.
+#if defined(OS_ANDROID)
+#define MAYBE_ChromeSendAvailable DISABLED_ChromeSendAvailable
+#else
+#define MAYBE_ChromeSendAvailable ChromeSendAvailable
+#endif
+IN_PROC_BROWSER_TEST_F(WebUIMojoTest, MAYBE_ChromeSendAvailable) {
+ // chrome.send is not available on mojo-only WebUIs.
+ NavigateWithNewWebUI("web_ui_mojo_native.html");
+ EXPECT_FALSE(RunBoolFunction("isChromeSendAvailable()"));
+
+ // Now navigate again with normal WebUI bindings and ensure chrome.send is
+ // available.
+ NavigateWithNewWebUI("web_ui_mojo_native.html?webui_bindings");
+ EXPECT_TRUE(RunBoolFunction("isChromeSendAvailable()"));
+
+ // Now navigate again both WebUI and Mojo bindings and ensure chrome.send is
+ // available.
+ NavigateWithNewWebUI("web_ui_mojo_native.html?hybrid");
+ EXPECT_TRUE(RunBoolFunction("isChromeSendAvailable()"));
+
+ // Now navigate again with WebUI disabled and ensure that chrome.send is
+ // not available.
+ factory()->set_web_ui_enabled(false);
+ NavigateWithNewWebUI("web_ui_mojo_native.html?hybrid");
+ EXPECT_FALSE(RunBoolFunction("isChromeSendAvailable()"));
}
} // namespace
diff --git a/chromium/content/browser/webui/web_ui_url_loader_factory.cc b/chromium/content/browser/webui/web_ui_url_loader_factory.cc
index baa74f4c5e5..653e22e0ee5 100644
--- a/chromium/content/browser/webui/web_ui_url_loader_factory.cc
+++ b/chromium/content/browser/webui/web_ui_url_loader_factory.cc
@@ -66,7 +66,7 @@ void ReadData(scoped_refptr<network::ResourceResponse> headers,
network::mojom::URLLoaderClientPtr client;
client.Bind(std::move(client_info));
- client->OnReceiveResponse(headers->head, nullptr);
+ client->OnReceiveResponse(headers->head);
base::StringPiece input(reinterpret_cast<const char*>(bytes->front()),
bytes->size());
@@ -119,6 +119,7 @@ void ReadData(scoped_refptr<network::ResourceResponse> headers,
network::URLLoaderCompletionStatus status(net::OK);
status.encoded_data_length = output_size;
status.encoded_body_length = output_size;
+ status.decoded_body_length = output_size;
client->OnComplete(status);
}
@@ -244,7 +245,6 @@ class WebUIURLLoaderFactory : public network::mojom::URLLoaderFactory,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!request.download_to_file);
if (request.url.scheme() != scheme_) {
DVLOG(1) << "Bad scheme: " << request.url.scheme();